Java Programming/Spring framework

From Wikibooks, open books for an open world
Jump to: navigation, search

This is intended to be a short, simple tutorial on writing a Java application that uses the Spring framework. Please note, this tutorial is intended for those with a moderate amount of background with Java, and a basic working knowledge of XML.

For this tutorial, we will be making an application that reads short stories from a Spring bean configuration file. (For the sake of this example, these short stories are real short stories.) There will be three Java classes, and one Spring config file. So let's begin…

Step 1: Setting up your environment[edit]

Before we can directly make the files, we first need to setup Spring. I'm assuming you already have the latest version of Java installed. If not, you can download Java Development Kit here.

Spring recommends to use Maven or Gradle to set up your dependencies. If you don't have them installed or provided by your IDE such as Eclipse, you can find instruction how to use and download them here and here. Maven or Gradle will make sure that your dependencies, and those they depend upon are loaded in your project.

See section QuickStart in http://projects.spring.io/spring-framework/ on how to add spring dependencies to your project. Using maven you will need to provide a pom.xml file with the following content in the root of your project:

If you are using Maven make sure that you provide a pom.xml file which contains the following line.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mygroup</groupId>
  <artifactId>spring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 
  <!-- Copy the following lines from http://projects.spring.io/spring-framework/ to depend on the latest version of spring -->
  <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.3.RELEASE</version>
    </dependency>
</dependencies>
</project>

From here on out, you can just copy and paste the text into the files for Steps 2, 3, and 4; skip the explanations; and run the program yourself. The explanations are only there to provide you with a background of the way Spring puts it all together. Ok, now on to the meat and potatoes, story_configuration.xml.

Step 2: Creating a Spring beans configuration file[edit]

Create a new XML file in the directory where you are planning to put your java files. Call it story_configuration.xml. Then copy and paste the text below into the file and save it:

story_configuration.xml[edit]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
      "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
   <bean id="StoryList" class="spring.StoryList">
      <property name="stories">
         <list>
           <ref bean="HelloWorld"/>
           <ref bean="OnceUpon"/>
         </list>
       </property>
   </bean>
 
   <bean id="HelloWorld" class="spring.Story">
      <property name="title">
         <value>Hello World!</value>
      </property>
      <property name="author">
         <value>User:Hyad</value>
      </property>
      <property name="content">
         <value>This is a simple story.
This is a story about a man who said, "Hello, World."
See, now wasn't that simple.</value>
      </property>
   </bean>
 
   <bean id="OnceUpon" class="spring.Story">
      <property name="title">
         <value>Once Upon a Time</value>
      </property>
      <property name="author">
         <value>Rob Yates</value>
      </property>
      <property name="content">
         <value>Once upon a time there were some interesting things going on.
The end.</value>
      </property>
   </bean>
</beans>

Explanation[edit]

The first two lines are just standard XML declarations. Technically we don't really need them, but we'll put them in anyway. Next, you'll see the <beans> tag, this is where all the Java beans go.

Below that you'll see <bean class="spring.StoryList">. This will be a bean for our Java class, StoryList.java in package spring. This class is simply a placeholder for the List where we will be holding our stories. Note the attributes of the bean element: there must always be a class attribute to represent the Java Class the bean is using. The id attribute is optional; it is used by the XMLBeanFactory class, to tell it what bean to get with the getBean method: ex. getBean("My id attribute name here"). If no ID attribute is provided, like with <bean class="StoryList">, the class name is used as if it were the id attribute. Think: <bean id="StoryList" class="spring.StoryList">. Also note a bean's id value must not have any spaces, ex. don't write id="Story List".

Next we have <property name="stories">. The property tag just specifies what property variable in the Java bean file we want to specify with a bean property. The <list> tag is used next to tell Spring that we're dealing with a List of things, not just one. Next we have <ref bean="HelloWorld"/>, this tells Spring to return the <bean id="HelloWorld" class="spring.Story"> bean inside this List. In a different example, you might simply need a list of values like Strings. For a grocery list you might have something like,

<list>
	<value>milk</value>
	<value>eggs</value>
	<value>bread</value>
</list>

Either way your property is mapped to a LIST

For our HelloWorld story, we have <bean id="HelloWorld" class="spring.Story">. Hopefully, nothing too surprising here. There are three properties of this bean, <property name="title">, <property name="author">, <property name="content">. These are again mapping to property variables: title, author, content in the Story class. Within each value we have: <value>Hello World!</value>, <value>User:Hyad</value>, <value>This is a simple story.

This is a story about a man who said, "Hello, World."

See, now wasn't that simple.</value> Since we are dealing with Strings, everything between the start and end value tags is converted into a String. Hence to add a newline, we must actually put text on separate lines without any indentation. Be aware that values don't have to be mapped to Strings, they can be primitives like int or char, or objects like Integer or Float. Spring automatically knows how to convert them.

We won't be covering the OnceUpon bean, it's essentially the same thing as HelloWorld, only with different values. In fact, that is the main purpose for using Spring, storing different sets of values for a Java class as a bean instead of making a new class. Up next are the Java Bean classes themselves.

Step 3: Making JavaBean classes[edit]

There are two JavaBean classes: Story.java and StoryList.java, both in the package spring. Copy and paste the following text into their respective classes.

Story.java[edit]

package spring;
 
public class Story {
 
	private String title;
	private String author;
	private String content;
 
	public Story () {
	}	
	public void setTitle(String title) {
		this.title = title;
	}
	public String getTitle() {
		return title;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getAuthor() {
		return author;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getContent() {
		return content;
	}
}

StoryList.java[edit]

package spring;
 
import java.util.List;
 
public class StoryList {
 
	private List stories;
 
	public StoryList (){
	}
	public void setStories(List stories) {
		this.stories = stories;
	}
	public List getStories() {
		return stories;
	}
}

Explanation[edit]

Not too complicated, right? These are JavaBeans; simple classes with getters and setters for property variables, and a constructor without any parameters. For a more in-depth discussion of JavaBeans visit Wikipedia:JavaBeans. The setters, like setTitle(String title), are what Spring uses to create the beans in the XmlBeanFactory. The setters must follow specific bean naming conventions. For example, settitle(String title) with a lowercase "t" won't work. However, as an example setURL(String url) with property name "URL" will work because the second letter "R" is also capitalized in addition to the first "U". Getters aren't actually used by Spring in this example, however StoryReader needs them as we'll see later on. In addition, we don't actually have to specify a no-argument constructor, we could just leave it out and the Java compiler will automatically put one in the class when it's compiled. However, writing a constructor with one or more arguments without a no-argument constructor would invalidate the class as a bean.

Step 4: A main method to put it all together[edit]

As we have before, copy and paste the text. And save your class as StoryReader.java.

StoryReader.java[edit]

package spring;
 
import java.util.List;
 
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
 
public class StoryReader {
 
	public static void main(String args[]) {
		ClassPathXmlApplicationContext springApplicationContext = new ClassPathXmlApplicationContext("story_configuration.xml");
 
		StoryList storyList = (StoryList) springApplicationContext.getBean("StoryList");
 
		List myStories = storyList.getStories();
 
		for (int i = 0; i < myStories.size(); i++) {
			Story currentStory = (Story) myStories.get(i);
			System.out.println("\"" + currentStory.getTitle() + "\" by "
					+ currentStory.getAuthor() + ":");
			System.out.println(currentStory.getContent());
			System.out.println();
		}
	}//end main
 
}//end StoryReader

Explanation[edit]

Here is our main class, StoryReader.java in package spring. First we have to import two Spring classes, XmlBeanFactory and ClassPathResource. XmlBeanFactory is essentially a Java class representation of the Spring XML configuation file, story_configuration.xml. However, before we can get the XML file, we have to tell Spring to look in our class path for that file. That's where ClassPathResource comes in. It searchs the class path, which is where our .class files are stored, for the file specified in its constructor, story_configuration.xml. Any other class that implements the Resource interface may be used, such as org.springframework.core.io.FileSystemResource. Therefore, we see XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("story_configuration.xml")); creates a new bean factory from story_configuration.xml.

The next line, StoryList storyList = (StoryList) beanFactory.getBean("StoryList");, tells us which bean we want to get next. The getBean("StoryList") tells the bean factory to return an object corresponding to the bean with the id "StoryList", since it is the class name. Since it is an Object, we have to cast it into a StoryList class.

Next, we get the list of stories from the StoryList class, and loop through them. Since this is a bean, the Stories are already there in the list, within the values already in the stories. All we have to do is print them out; which we do. Note: \" is used to escape quotes within the String.

Step 5: Running your program[edit]

So now that we're done creating our classes and files, lets run the program! Fix any errors you get by making sure you copied everything correctly. When you run the main method of StoryReader, your output should be as follows:

Mar 12, 2006 5:42:30 PM org.springframework.core.CollectionFactory <clinit>
INFO: JDK 1.4+ collections available
Mar 12, 2006 5:42:30 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [story_configuration.xml]
"Hello World!" by User:Hyad:
This is a simple story.
This is a story about a man who said, "Hello, World."
See, now wasn't that simple.

"Once Upon a Time" by Rob Yates:
Once upon a time there were some interesting things going on.
The end.

The dates will obviously be different when you run it yourself. Also, the four lines that begin with either a date or the word "INFO" are printed to System.err and may be above, or below, or even in between the rest of the output. This is because some operating systems may print to System.out and System.err at different times. Check that your output matches the one shown, disregarding the dates and order of the four lines that Spring prints. Now, you have a fully functioning Spring application, but what next?

Afterthoughts[edit]

Things to remember[edit]

As I mentioned earlier, Spring performs automatic conversion of values to both primitives and Objects; int, float, char, Double, boolean, Byte, you name it. Also note that <list>, which is simply a list of values, can be mapped to a List object, an Array object, or a primitive array (the two square brackets kind). There are even <set> and <map> tags which can be mapped to Sets and Maps, respectively. And at any point you can replace a value with a reference to a bean, like replace <value>myValue</value> with <ref bean="myBeanId"/>. This reference will return the corresponding JavaBean and Spring will store it as that variable.

In addition, Spring can also serve as a replacement for properties files. An advantage is that Spring is XML based, so any XML parser can read it. And multiple beans can be stored for the same class within the same file. However, you may also place beans across multiple files, and use <import resource="myOtherBeanConfigFile.xml"/> to "import" other beans, just like importing Java classes.

The last thing you may want to know is that Spring is most helpful when you use one bean to reference to other beans, classes, files, etc. You may have one bean contain a list of beans, which contain a list of beans, each of which contain another list of beans, … This way only the file name and location of most top level bean is "hard-coded" in the Java class, and everything else is specified by the XML configuration files.

Try it yourself[edit]

Here are a few tasks you might do to make your Spring application more robust. Do as many, or as little, as you like:

  • Separate the StoryList bean into another XML file, using <import resource="story_configuration.xml"/> in your new file.
  • Add publication date to each of your stories. How will you store the date?
  • Make a separate class for the author. What attributes might an author have?
  • Put additional functionality into StoryList. How about a printStories() method that can be called by StoryReader's main method?
  • Create a writer so all output will be written to a file. And store that file name as a bean.
  • Add more stories. (Mine suck, I know.)
  • Instead of stories, how about TV shows, or video games?
  • Change random code around until it breaks. Have fun! :)

About the author[edit]

I go by User:Hyad on Wikipedia and Wikibooks. Having been frustrated by other Spring tutorials that were too long, I decided after actually learning (and using) Spring at work that I would actually create my own. This tutorial came the closest to what I was looking for in a good tutorial, but it was a little too short. So I figured, why not give an example that could be used in the real world. And I figured Wikibooks would be the best place for it, considering if I put it on my website, 1. It would be too cumbersome to edit, and 2. Other people wouldn't be able to edit and update it easily. So drop me a line at my Wikipedia talk page and tell me what you think.

References[edit]