Friday, July 18, 2008

A little bit of dependency injection with Struts 2 and Spring 2

I'm using Struts 2 + Hibernate 3 + Spring 2 for my current project. I have to admit that Struts+Spring integration is really easy. The key integration point is Struts 2 Spring plugin. I'll not repeat the docs here. Only one thing I should admit that I prefer to handle spring dependencies by myself because of little bit different version of Spring - 2.0.5 in plugin and 2.0.8 in my project. So, I have this lines in my pom.xml (Maven 2 build file)

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.0.11.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
and
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
etc. I'm injecting Spring powered services into Struts 2 actions, but I had never had a chance to inject some kind of static list. Now I have, so the story about it.

I have a static list of countries. I think it doesn't make sense to store this info in database. The number of countries is not that large. If so, I need to store this data in some data structure and place it in memory. It could be List or Map - it depends on situation. And init this data structure once application starts. In web app when war file being deployed, Spring's WebApplicationContext initialized. So, when we define our list as Spring bean, it will be initialized at the application start and will be ready to other manipulations. I've defined it as so :

<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd">

<util:list id="countryList" list-class="java.util.LinkedList">
<value>item1</value>
<value>item2</value>
<value>item3</value>
</util:list>

</beans>
Here is the one question on Spring forum and official docs about it. For now we have a LinkedList filled with countries. We are going to inject it into Spring action and then show it at the "view" jsp.

Please note that id of our list is countryList. In fact it is a name of the bean. It's name really important since Struts 2 Spring pluring's default autowiring strategy is by name (I'm using default autowiring type and happy with that). It means that we can use setter injection this way
public class SomeStruts2Action extends ActionSupport
{
public List countryList;

public void setCountryList(List countryList) {
this.countryList = countryList;
}
.......
}
Please note that id and class member name with type List are equal. That is all ! But actually not all :) We have to tell where is our list definition is. In my case it's at one of jars so I have this line in web.xml :

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-myCountryList.xml,
/WEB-INF/appContext-web.xml</param-value>
</context-param>

Have fun !

No comments: