Archive for the ‘Spring’ Category

Articles

Spring Tutorial One (Old)

In Spring,Tutorial on 06/02/2011 by pier0w

Right so… what is Spring? Well the Spring About page has a good description of what it does but not how it does it or how you can does stuff with it. My self, I see Spring as a container that initialises and sticks all your classes together. This is handy because it means you don’t have to bother writing factory classes or singletons because Spring will start up a single instance of each class then propagate those single instances throughout any classes that require them. So you could almost think of Spring as duct tape for Java.

Springs main goal is to provide a paradigm called Inversion of Control or IoC. The wikipedia explanation is ok but it doesn’t really give you any idea about how this relates to Spring. Springs version of IoC can be easily summed up with the term Dependency Injection. Now coming from a unix background and being quite used to the dependency resolution of package managers, when I first heard that term I instantly thought Spring must be dynamically pulling down all the dependant libraries you have used and injecting them into your class path and maybe even dynamically adding the imports at compile time. This is of course not the case at all, but oddly is pretty much exactly what Maven does except for adding the imports, that’s what your IDE is for. Springs dependency injection refers to the dynamic injection of a classes properties during the start up of an application.

So say we have the following classes:

public class MyClassOne {

        private Integer one;

        // All classes that are to be used within Spring MUST have a default constructor.
        // This is so that Spring can instantiate the class before injecting the properties.
        public MyClassOne () {
        }

        public MyClassOne (Integer one) {
                this.one = one;
        }

        public Integer getOne() {
                return one;
        }

        public void setOne(Integer one) {
                this.one = one;
        }
}
public class MyClassTwo {

        private Integer two;

        // All classes that are to be used within Spring MUST have a default constructor.
        // This is so that Spring can instantiate the class before injecting the properties.
        public MyClassTwo () {
        }

        public MyClassTwo (Integer two) {
                this.two = two;
        }

        public Integer getTwo() {
                return two;
        }

        public void setTwo(Integer two) {
                this.two = two;
        }
}
public class MyHolder {

        private MyClassOne one;
        private MyClassTwo two;

        // All classes that are to be used within Spring MUST have a default constructor.
        // This is so that Spring can instantiate the class before injecting the properties.
        public MyHolder() {
        }

        public MyHolder(MyClassOne one, MyClassTwo two) {
                this.one = one;
                this.two = two;
        }

        public MyClassOne getMyClassOne() {
                return one;
        }

        public void setMyClassOne(MyClassOne one) {
                this.one = one;
        }

        public MyClassTwo getMyClassTwo() {
                return two;
        }

        public void setMyClassTwo(MyClassTwo two) {
                this.two = two;
        }

}

Spring would handle these classes by first instantiate MyClassOne and then MyClassTwo, Spring might even set an Integer value for both classes. The two new instances would then be used to create an instance of MyHolder, this would be done by injecting the instance of MyClassOne into the property named one and then injecting the instance of MyClassTwo into the property named two.

For my example I have only used concrete classes, it should also be noted that it is of course possible for Spring to inject a property with any object that can be cast into the properties type. So a property could just have the type of an interface which is great because your code then becomes a lot more generic since you don’t ever have to care about the implementation of your properties, you can let Spring decide on the best implementation for you.

Spring can do the injection in three different ways. First it can be told to instantiate the MyHolder class using the constructor that contains the arguments one and two and place the new MyClassOne and MyClassTwo instances in the correct slots. If this method is used the MyHolder class would not require a default constructor.
Secondly Spring could instantiate an empty MyHolder class then use the setter and getter methods to populate the one and two properties.
Lastly through the use of annotations Spring could then use reflection to directly access and set the values for the one and two properties.

If the last method is used it is actually possible to create classes that look like they would be impossible to use. For example it would be quite valid for the MyHolder classes code to be as follows:

public class MyHolder {

        @Autowired // Spring annotation that will be explained later.
        private MyClassOne one;

        @Autowired
        private MyClassTwo two;
}

It now looks like there is no way to set the properties in the MyHolder class but Spring can do this quite happily. It also looks rather clean and wizz bang nifty. Personally I don’t like using Spring like this because it tightly couples your cope to the Spring framework which I guess in reality is fine because you’ll rewrite your application before you’ll actually ever move away from Spring. But I personally think it is bad practice, if you wish to use Spring in this way I would still make sure to add all the getters and setters at the very least. I my self also add the property constructor as well.

So that is what the very basic core of Spring does, though there are now quite a lot of extra modules that make up the core Spring echo system that provide far more functionality including, web interface security, data validation, data base transacting and even more.

For this initial tutorial we will only be looking at the different types of dependency injection and how to start the Spring container outside of a J2EE container, which is the most common place to use Spring. The next tutorial will look at how to use Spring with the J2EE containers Tomcat and Jetty.

Before starting this tutorial we need to make sure we have all the right equipment.

First the build tool we will be using is Maven, so make sure to have this installed and that you are connected to the internet. Though odds are if you are reading this you should have the second half of that done. Installing maven is very simple so I won’t be discussing how to do it here. We will just be using the default maven config so no extra configuration is required.

Secondly the SCM we will be using is git. Again this just has to be installed and working, there is no need for any extra configuration, we won’t even be using a remote repository so that doesn’t even have to be set up.

Lastly the IDE I will be using for these examples will be Intellij IDEA. I am going to use the free Community Edition.

Once your environment is set up we can begin.

First generate your self a maven project by running the following command.

#> mvn archetype:generate
...
365: remote -> wicket-scala-archetype (-)
366: remote -> wikbook.archetype (-)
367: remote -> circumflex-archetype (-)
368: remote -> javg-minimal-archetype (-)
Choose a number: 99:

This will kick off a process to allow you to easily generate a maven project. You’ll be displayed with a list of around 300 – 400 custom maven projects that provide you with good starting points for different situations and frameworks, if there was a nice independent Spring template I would tell you to use it now, but as of writing this there isn’t one so just choose the default option (99: remote -> maven-archetype-quickstart) by pressing ENTER.

367: remote -> circumflex-archetype (-)
368: remote -> javg-minimal-archetype (-)
Choose a number: 99: 
Choose version: 
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6:

Next you will be asked which version of the template you would like to use, select the latest by pressing ENTER again.

Now you need to select how you want to name your project by giving the group id (namespace), artifactId (name), version, and package name (generally but not always the same as your given groupId) of your project. Fill these in with the same values as I have shown below.

5: 1.0
6: 1.1
Choose a number: 6: 
Define value for property 'groupId': : uk.co.bbc.spring 
Define value for property 'artifactId': : spring
Define value for property 'version': 1.0-SNAPSHOT: 1.0
Define value for property 'package': uk.co.bbc.spring: #Press ENTER to select the groupId as the package name by default
Confirm properties configuration:
groupId: uk.co.bbc.spring
artifactId: spring
version: 1.0
package: uk.co.bbc.spring
Y: #Press ENTER to confirm

You will now have a brand new maven project.

#> ls -R spring
spring:
pom.xml  src

spring/src:
main  test

spring/src/main:
java

spring/src/main/java:
uk

spring/src/main/java/uk:
co

spring/src/main/java/uk/co:
bbc

spring/src/main/java/uk/co/bbc:
spring

spring/src/main/java/uk/co/bbc/spring:
App.java

spring/src/test:
java

spring/src/test/java:
uk

spring/src/test/java/uk:
co

spring/src/test/java/uk/co:
bbc

spring/src/test/java/uk/co/bbc:
spring

spring/src/test/java/uk/co/bbc/spring:
AppTest.java

Ok so next we need get git to start tracking the changes on the project so move into the projects directory and run the git init command.

#> cd spring/
#> git init
Initialized empty Git repository in /some/dir/projects/spring/.git/

Now we can check to see what git has found in our project with the git status command.

#> git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#	pom.xml
#	src/
nothing added to commit but untracked files present (use "git add" to track)

It has found the maven pom file and the source directory for our project lets tell git to start tracking these by adding them to the repository and then carrying out our first commit.

#> git add pom.xml src/
#> git status # Just running git status again to check what files have been added.
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached ..." to unstage)
#
#	new file:   pom.xml
#	new file:   src/main/java/uk/co/bbc/spring/App.java
#	new file:   src/test/java/uk/co/bbc/spring/AppTest.java
# 
#> git commit -m "First commit." # Our first commit. Ignore the warnings, you can do what it says to stop git complaining if you like.
[master (root-commit) 4100aeb] First commit.
 Committer: Some One 
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

If the identity used for this commit is wrong, you can fix it with:

    git commit --amend --author='Your Name '

 3 files changed, 76 insertions(+), 0 deletions(-)
 create mode 100644 pom.xml
 create mode 100644 src/main/java/uk/co/bbc/spring/App.java
 create mode 100644 src/test/java/uk/co/bbc/spring/AppTest.java

Git is now tracking all of our files so it is time to open the project in our IDE. If you are using Intellij IDEA select File->Open Project... then find the spring directory select it and click the OK button. Once the project is open click on the Project tab in the top left hand corner and you will see the project structure and all it’s files.
Intellij will create some of it’s own project files within the spring directory, we do not want git to track these so to tell git to ignore them create a file called .gitignore within the spring directory and enter the following into it.

# Ignore intellij IDEA project files.
*.iml
*.ipr
*.iws

# Ignore the maven temporary build directory.
target/

Notice we are also going to ignore the maven build directory. Once that file is created add it to git and commit.

#> git add .gitignore
#> git commit -m "Created .gitignore file to stop tracking IDE project files and maven build directory."

You can now tell Intellij to recheck the git status by selecting Version Control->Refresh File Status. You will now see that the project files are no longer being tracked.

Now lets create our main class that we will use to run this project. Right click on the uk.co.bbc.spring package under the java directory and select New->Java Class and give the class the name Main. If you are asked whether you would like to add the new file to git tick the box to tell Intellij to stop asking and then click Yes.
We now have an empty main class, lets give it a method called doStuff so we have something to test.

package uk.co.bbc.spring;

public class Main {

    public String doStuff() {
        return "Do Stuff.";
    }
}

You will now notice something odd, Intellij doesn’t seem to recognise the Java String class. This doesn’t seem right since that is part of the Java core library. The reason for this is that you have to tell Intellij which Java compiler it should use on your code. To do this place the cursor inside the word String that is the return type of the method. After a few moments you should see a red light bulb appear to the left of the word public. Now hover the cursor over the red light buld and click on the drop down arrow that appears and select the Setup JDK option, then click the Configure... button. Next click the small + button at the top left of the Configure SDK window, then select the JSDK option. Intellij should now be showing you the home directory of you JDK, select it and click OK, then click ok in the Configure SDK window, then finally click OK in the Select Project SDK window. Your Java compiler should now be setup.

The next thing to do will be to create a test class for Main. But before we do that we should update two things within our maven pom file.

First is the Java Compiler version, by default this is set to 1.4 which is far too old so we are going to upgrade it to 1.6 by adding the following to the root of the pom file.

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <compilerVersion>1.6</compilerVersion>
                    <fork>true</fork>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

Pro tip: Press CTRL-ALT-L to format any code including XML.

Then we are going to update the JUnit verion to 4.7 by changing the version tag within the dependency.

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

Pro tip: Delete the number inside the version tag then press CTRL-SPACE to get a list of all the versions that are available for any maven dependency. This will work in most of the tags within the maven pom file so you could also use it to find all the artefacts within the junit group.

After editing the pom file Intellij will pop out a small message at the top of the code window asking to import the new changes from the pom file, click the Import Changes link in this pop out to tell Intellij to process the changes. Now that we have finished editing the pom file lets commit the changes by right clicking on the code and then selecting Git->Commit File..., this will pop up the commit changes window. The first thing to do here is to untick the Perform code analyses for affected file tick box. This will speed up your commits and also stop you getting bugged by Intellij. Then write your commit message into the Commit text area and click Commit.

Now click back into the Main class’s code and make sure the cursor is somewhere within the code for the class, clicking in it’s name is good then press CTRL-SHIFT-T to start the process of generating a JUnit test class. Click on the Creat New Test... option then make sure to select the JUnit4 radio button at the top of the Create Test window, also tick the doStuff method to generate a test method, then click ok.
We now have a test class so lets right a pointless test to make sure that the doStuff method is returning the correct string. For this we will need to statically import the junit assert methods.

package uk.co.bbc.spring;

import org.junit.Test;

import static junit.framework.Assert.*;

public class MainTest {
    
    // Test strings and other variables should be set up as constants so that they 
    // can be easily modified and used across multiple tests.    
    private static final String DO_STUFF = "Do Stuff.";

    @Test
    public void testDoStuff() throws Exception {
        Main main = new Main();

        // Assert that the method is returning the correct value.
        assertEquals("test do stuff method's return string", DO_STUFF, main.doStuff());
    }
}

To run the test right click on the method name and select Run "testDoStuff()".

Now that we have a new class and it’s corresponding test class we can safely delete the generated AppTest and App classes, in that order so that Intellij’s safe delete doesn’t complain. Once that is done it would also be a good idea to commit the new Main files to git. From now on I’m going to leave the commiting up to you.

At this point we should now have a very simple and completely useless maven project. You can test to see if it will build with the following command.

#> mvn clean install

You should get a pointless yet successful build. Lets take this one step further by making a pointless yet executable project by creating a main method within the main class that outputs the string from the doStuff method.

package uk.co.bbc.spring;

public class Main {

    public static void main(String[] args) {
        Main main = new Main();

        System.out.println(main.doStuff());
    }

    public String doStuff() {
        return "Do Stuff.";
    }
}

Pro tip: Type psvm inside the class and press the TAB key, this will automatically generate a main method. Also then type sout within the main method and press TAB, this will generate System.out.println().

We can now execute our class, try it by right clicking on the main method or the class in the Project pain and select Run "Main.main()". Similar to how you previously ran the test.

Ok so far for a Spring tutorial there is very little about Spring so lets fix that.
To be able to use Spring in our project we are going to need to add it as a dependency within our pom file.

   <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.0.3.RELEASE</version>
        </dependency>
    </dependencies>

We have added the spring-context module which will give us access to the Spring context which is where Spring stores all of it’s instantiated objects.

Now that we have access to all the classes we can start up the Spring container, so to do this we first have to create a context (config) file for the container to use on startup.
To create the context file first create a directory called resources in the directory called main within the project, then create a file called context.xml and place the following inside it. The resources directory within a maven project is where all config and “resource” files should be placed.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation=" http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>

You now have an empty context file that can be used to start up a Spring container. So lets start it up, to do that we have to instantiate the ClassPathXmlApplicationContext class and give it the path to the context file as an argument.

package uk.co.bbc.spring;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("context.xml");

        Main main = new Main();

        System.out.println(main.doStuff());
    }

    public String doStuff() {
        return "Do Stuff.";
    }
}

Run the main class again and you should get some Spring output, but not much else. Now as I mentioned before Spring’s main feature is Dependency Injection, so lets inject some classes.

Before we can inject anything we need something to inject, so lets create the same classes that were mentioned at the start of this tutorial. MyClassOne, MyClassTwo, and MyHolder.

Once these classes have been created you can use Spring to inject and instantiate them by adding bean definitions to the context file. For the two my classes we are going to us property injection then for the holder we are going to use constructor injection.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation=" http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="myClassOne" class="uk.co.bbc.spring.MyClassOne">
        <property name="one" value="1"/>
    </bean>

    <bean id="myClassTwo" class="uk.co.bbc.spring.MyClassTwo">
        <property name="two" value="2"/>
    </bean>

    <bean id="myHolder" class="uk.co.bbc.spring.MyHolder">
        <constructor-arg name="one" ref="myClassOne"/>
        <constructor-arg name="two" ref="myClassTwo"/>
    </bean>
</beans>

Now lets access the new beans from the Spring context with the following code.

package uk.co.bbc.spring;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        Main main = new Main();

        System.out.println(main.doStuff());

        AbstractApplicationContext context = new ClassPathXmlApplicationContext("context.xml");

        // Retrieve MyClassOne using just the id. Casting required because no type set.
        MyClassOne one = (MyClassOne) context.getBean("myClassOne");

        // Retrieve MyClassTwo using the id and type. No cast required.
        MyClassTwo two = context.getBean("myClassTwo", MyClassTwo.class);

        System.out.println("Spring instantiated MyClassOne one value: " + one.getOne());
        System.out.println("Spring instantiated MyClassTwo two value: " + two.getTwo());

        // Retrieve MyHolder with just the type because there is only ever one instance instantiated.
        MyHolder holder = context.getBean(MyHolder.class);

        System.out.println("Spring instantiated MyHolder one value: " + holder.getOne().getOne());
        System.out.println("Spring instantiated MyHolder two value: " + holder.getTwo().getTwo());
    }

    public String doStuff() {
        return "Do Stuff.";
    }
}

Now if we run the application we should get output similar to the following.

Do Stuff.
06-Feb-2011 19:44:27 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1815859: startup date [Sun Feb 06 19:44:27 GMT 2011]; root of context hierarchy
06-Feb-2011 19:44:27 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [context.xml]
06-Feb-2011 19:44:27 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1d2fc36: defining beans [myClassOne,myClassTwo,myHolder]; root of factory hierarchy
Spring instantiated MyClassOne one value: 1
Spring instantiated MyClassTwo two value: 2
Spring instantiated MyHolder one value: 1
Spring instantiated MyHolder two value: 2

The Spring project now actually does something interesting, it instantiates and injects some beans then retrieves and displays their content.

Lastly lets do some injection with Spring annotations. First we need to update the context file so that Spring knows where to look for the annotated classes. To do this add the spring context XSD to the context file to enable access to the context tags then add the component scan tag to scan for any annotated classes under the uk.co.bbc.spring package. Lastly comment out the wiring of the holder object in the context file.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="myClassOne" class="uk.co.bbc.spring.MyClassOne">
        <property name="one" value="1"/>
    </bean>

    <bean id="myClassTwo" class="uk.co.bbc.spring.MyClassTwo">
        <property name="two" value="2"/>
    </bean>

    <context:component-scan base-package="uk.co.bbc.spring"/>

    <!--<bean id="myHolder" class="uk.co.bbc.spring.MyHolder">-->
    <!--<constructor-arg name="one" ref="myClassOne"/>-->
    <!--<constructor-arg name="two" ref="myClassTwo"/>-->
    <!--</bean>-->

</beans>

Now we need to add the right annotations to the MyHolder class. FIrst we annotate the class with the org.springframework.stereotype.Component annotation. This tells Spring that this class should be instantiated and injected. Then we annotate the properties with org.springframework.beans.factory.annotation.Autowired, this tells Spring that the properties should be populated with beans in the context that match their type. It is also possible to just annotate the property constructor and then Spring will instantiate the class in the same way that it did with the previous context file configuration.

package uk.co.bbc.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyHolder {

    @Autowired
    private MyClassOne one;

    @Autowired
    private MyClassTwo two;

    public MyHolder() {
    }

    public MyHolder(MyClassOne one, MyClassTwo two) {
        this.one = one;
        this.two = two;
    }

    public MyClassOne getOne() {
        return one;
    }

    public void setOne(MyClassOne one) {
        this.one = one;
    }

    public MyClassTwo getTwo() {
        return two;
    }

    public void setTwo(MyClassTwo two) {
        this.two = two;
    }
}

And there you have it the end of the first Spring tutorial, where you have learned a little about what Spring does, how it does it, and the different ways to does things with it.

Advertisements