Friday, February 17, 2012

Spring utilty template - merging with Hello Word

I had previously meant to do a blog on using a spring template utility to do the hello world example in chapter 2 from the Spring 2.5 Recipe book, but got sidetracked. So, let's give it another go.

The basics of it are, when you create a Simple Spring Utility project from STS (new, Spring Template Project, Simple Spring Utility Project), you get an ExampleService and a Service interface generated for you. The Service interface is just this:


package com.apress.springrecipes.hello;

public interface Service {

String getMessage();

}



And the ExampleService implements the Service interface and returns "hello, World":



package com.apress.springrecipes.hello;

import org.springframework.stereotype.Component;


/**
* {@link Service} with hard-coded input data.
*/
@Component
public class ExampleService implements Service {

/**
* Reads next record from input
*/
public String getMessage() {
return "Hello world!";
}

}


The above example includes an example of using the @Component annotation, which means you don't have to specify the bean in the spring xml file. If we look in there (in "src/main/resources/META-INF/spring/app-context.xml"), we'll see the following declaration:


<context:component-scan base-package="com.apress.springrecipes.hello" />


This tells the Spring container to look through the specified package and subpackages for any class with the "@Component" annotation and make it a bean. (There are also subclasses of @Component, but that's the gist of it).

Getting back to the main point, to see this in action, you need to run the unit tests that get generated from the template. For example, if you drill down into "src/test/java", you'll find a class called "ExampleServiceTests.java", that looks like this:



package com.apress.springrecipes.hello;

import com.apress.springrecipes.hello.ExampleService;
import junit.framework.TestCase;

public class ExampleServiceTests extends TestCase {

private ExampleService service = new ExampleService();

public void testReadOnce() throws Exception {
assertEquals("Hello world!", service.getMessage());
}

}


If you right-click and run that as a junit test, you'll see the green bar indicating it passed the test.

However, we'd like to run the code from the Spring Recipe book:



package com.apress.springrecipes.hello;

public class HelloWorld {

public void hello() {
System.out.println("Hello world!");
}
}




Based on the book, the main class should look (roughly) like this:



public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("app-context.xml"); // why would expect to find beans.xml?

HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
helloWorld.hello();
}



Note that I changed the name of the spring beans file to "app-context.xml". It's in "src/main/resources/META-INF/spring/app-context.xml".

Let's add the entry for HelloWorld into it:


<bean id="helloWorld" class="com.apress.springrecipes.hello.HelloWorld">
</bean>


Now, if you just run main like this, it will crash, because app-context.xml (the bean configuration file) isn't in the classpath. It's in "src/main/resources/META-INF/spring/app-context.xml.


So, how to we get it that into the class path?

Here's how:

In the STS, select Run > Run Configurations. Click on the user entries item in the dialog box, then advanced > add external folder, then drill down to the path leading up to the configurations file. Also, obviously, use the main class above as the main class. When you run it, you should see "hello world!" in your console output.

No comments:

Post a Comment