Using Struts 2 and Spring Frameworks Together

Introduction

In the execute method of many Struts 2 ActionSupport classes are statements that create objects and then have those objects execute methods that perform needed tasks. Whenever one class creates an object of another class that introduces a dependency between the two classes. The Spring framework makes it easier for the application developer to manage these dependencies and helps makes the application more flexible and maintainable. For more information about the Spring framework consult references 1 and 2.

This article will introduce how to use the two frameworks together. To show how this works I've used the previous Struts 2 example project built for the article on Struts 2 validation. Please note that this is a very simple example and there is much more you can do with both Struts 2 and Spring.

Setting Up Struts 2 and Spring To Work Together

You can download an archived MyEclipse web project that is an example of using Spring in a Struts 2 web application (see reference 4).

In the Struts 2 web application you'll need to add to the lib directory two jar files. Struts 2 comes with a plugin for integrating the Spring and Struts 2 frameworks. The Spring plugin jar file can be found in \struts-2.0.11.1\lib and is named struts2-spring-plugin-2.0.11.1.jar. Note that if your version of Struts 2 is different than 2.0.11 then the folder and file names will be slightly different. Copy the Spring plugin jar to your Struts 2 web application's lib folder.

You'll also need the spring.jar provided from the Spring framework. You can download the latest Spring framework by visiting reference 2. After you unzip the downloaded file from the Spring framework website, copy spring.jar (which I found in \spring-framework-2.5.5\dist) to your Struts 2 web application's lib folder.

Modify Your ActionSupport Class So Spring Can Manage Dependencies

If you download and import into MyEclipse or Eclipse the example project (reference 4) you'll see that I've added a PersonService interface and a PersonFileService class that implements that interface. If I was not using Spring to manage dependencies I would need to create a PersonService object in the Register ActionSupport class in order to get a reference to a PersonService object so I could call its save method. For example:


public String execute(){
    
//create a PersonService object    

PersonService personService = new PersonFileService();
        
//store personBean

personService.save( personBean );
        
return SUCCESS;
        
}

So now I have a dependency between the Register class and the PersonFileService class. If in the future I want to change the specific type of PersonService object that I want to use--for example PersonDAOService--I would need to change the above Java object creation statement. If my application has numerous places where I created a PersonFileService object I'd need to find those statements and change them all.

Integrating Spring into my Struts 2 application makes it simpler to manage dependencies and change them in the future. To use Spring with my Register class I need to add this code to class Register:



private PersonService personService;

public PersonService getPersonService() {
    
return personService;
    
}

public void setPersonService(PersonService personService) {
    
this.personService = personService;
    
}

Basically I've made the PersonService object an instance variable of the Register class and added standard Java bean setter and getter methods. Now I can change my execute method to this:


public String execute(){
    
//store personBean

personService.save( personBean );
        
return SUCCESS;
        
}

Using Spring to manage the dependency between the Register and PersonService classes means I don't need to create a specific PersonService object. Spring will "inject" a PersonService object into the Register class by sending a specific PersonService object to the setPersonService method. So the personService instance variable in class Register will get a reference to a specific PersonService object that was created and provided to the Register class by the Spring framework.

"Wiring" Spring to Manage A Dependency

I needed to add the following to my web.xml file to make the application aware of Spring.


<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

I also needed to create another XML file named applicationContext.xml under WEB-INF. This file contains:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
         "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

<bean id="personService" class="edu.ku.si.service.PersonFileService" scope="request" />

</beans>

The important part of this XML file are the bean nodes. The id value matches the name of the instance variable in the Register class. The class value specifies the class that Spring should create and pass to the setPersonService method. Note that I didn't specify the Register class anywhere in this XML. I'm using the Spring auto configuration mode that enables Spring to look over my classes and where it finds a setPersonService method, it will automatically create an object of PersonFileService and send it to the setPersonService method of that class.

The scope attribute is set to "request." This is a new bean scope added in Spring 2.0.

With the above bean definition in place, the Spring container will create a brand new instance of the PersonFileService bean using the 'personService' bean definition for each and every HTTP request. That is, the 'personService' bean will be effectively scoped at the HTTP request level. You can change or dirty the internal state of the instance that is created as much as you want, safe in the knowledge that other requests that are also using instances created off the back of the same 'personService' bean definition will not be seeing these changes in state since they are particular to an individual request. When the request is finished processing, the bean that is scoped to the request will be discarded. [Reference 5]

Advantage of Using Spring

If I need to change out the specific PersonService object type used by my application (say from PersonFileService to PersonDAOService) I'll just need to change the value for the class attribute in this line in applicationContext.xml:


<bean id="personService" class="edu.ku.si.service.PersonFileService" scope="request" />

In a larger Struts 2 application, you'll have many dependencies between classes and using Spring provides you a central place to manage those and change them in the future.

Another advantage is Spring helps reduce how tightly coupled are my classes. If you examine the Register class you'll see that this class only knows about (is coupled to) the PersonService interface type. The creation of a specific PersonService object is not done in class Register. Coding to an interface type is a more flexible way to couple classes.

Summary

I've just provided a very simple and bare-bones introduction to using the Struts 2 and Spring frameworks together. The references below provide much more information.

References

  1. Introduction to the Spring Framework
  2. Spring Framework
  3. Documentation For The Spring Plugin for Struts 2
  4. Struts 2 Spring Example
  5. Spring Framework Bean Scope
  6. Chapter 9, Struts 2 in Action, Manning Publishing 2008

Related Blog Entries

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner