08
Sep
09

Integrating Core Spring with the Struts Framework


This page explains how to take the “core spring hello world application” and integrate it with struts framework.

Requirements

A typical Struts application is a collection of Action classes. The trick to integrating spring framework into one of these application is to convert the action classes to spring beans. Spring beans are managed by the spring container. The container is initialized via xml configuration file.

In the Example application listed at the above URL you were introduced with an account transfer process. The customer wanted some amount of money transferred between 2 accounts. For this we used the AccountTransferService. The service used 2 data mangers configured as spring beans. Once the datamangers were configured they were “injected” into the AccountTransferService. All of this was done thru XML configuration and none of the components of the system knew how to construct each other. This leads to a loosely coupled system since we can swap out the implementation of the datamangers for testing or development purposes.

In this page we will convert the Struts Actions into spring enabled beans. We will “inject” the objects that the action needs to do its job. In this case the AccountTransferService will be injected into the Action. The action will handle the request, delegate the processing of the request to the AccountTransferService, then forward to the success page.

ContextLoaderPlugin

This plugin loads a spring context file for the struts ActionServlet. This allows your struts actions to be managed by Spring. You can do this 2 ways.

  • Override Struts’ default RequestProcessor with Spring’s DelegatingRequestProcessor
  • Use the DelegatingActionProxy class in the type attribute of your action-mapping element.

In the first method the type attribute of the struts action element will be ignored. In the second method you can use the DelegatingActionProxy as the type in your action-mapping. This is the approach we will cover here.

DelegatingActionProxy

The job of this class is to delegate the handling of a request to an Action Bean that is “spring enabled”. Spring enabling a bean means that we have defined it in a spring configuration file and injected it with the dependencies it needs to do its job.

It will chose the spring-enabled bean based on the URI of the incoming request. If we are asking for accountTransfer.do it will look for a spring bean named “/accountTransfer” in the spring application context.

The bridge between the Action in struts-config.xml and the strutsConfiguration.xml is built with the action-mapping’s “path” and the bean’s “name”. If you have the following in your struts-config.xml


<action path="/users" .../>

You must define that Action’s bean with the “/users” name in the strutsConfiguration.xml file.


<bean name="/users" .../>

Before we can start making this we need to add a few things to the pom.xml file.

Insert the pom file modifications here.

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc-struts</artifactId>
        <version>2.5.5</version>
</dependency>
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc-struts</artifactId>
        <version>2.5.5</version>
</dependency>

Modify the struts-config.xml and add the following towards the end of the file.

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
 <set-property property="contextConfigLocation" value="/WEB-INF/spring-config.xml"/>
</plug-in>

We will create an Action called AccountTransferAction. We will have this action spring enabled by putting it into the spring configuration file.

Modify application.xml and add the following section.

<bean name="/accountTransfer" class="strutsexample.AccountTransferAction">
<property name="accountTransferService" ref="accountTransferService"/>
</bean>

Update the struts-config.xml file and replace the strutsexample.AccountTransferAction with org.springframework.web.struts.DelegatingActionProxy. As you can see in the above bean definition the “accountTransferService” is injected into the “Spring Enabled” struts action.

<action path="/AccountTransfer" forward="/pages/accountInput.jsp" />
<!--
 <action path="/AccountTransferSubmit"  type="strutsexample.AccountTransferAction">
 <forward name="success" path="/pages/accountTransferSuccess.jsp"></forward>
 </action>

 <action path="/AccountTransferSubmit"  type="org.springframework.web.struts.DelegatingActionProxy">
 <forward name="success" path="/pages/accountTransferSuccess.jsp"></forward>
 </action>
 -->

The code in comments represents 2 ways to define an action. The first one is how you would typically define a struts action. The second element represents a spring enabled struts action. Go ahead and copy the second element outside the comments and save the file.

The following is the

src/main/webapp/WEB-INF/spring-config.xml

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

<beans>
        <bean name="/AccountTransferSubmit" class="strutsexample.AccountTransferAction">
                <property name="accountTransferService" ref="accountTransferService"/>
        </bean>
</beans>

The following is the

src/main/webapp/WEB-INF/applicationContext.xml

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

<beans>
        <bean name="accountDataManager" class="accountTransfer.AccountDataManagerImpl"/>
        <bean name="customerDataManager" class="accountTransfer.CustomerDataManagerImpl"/>
        <bean name="accountTransferService" class="accountTransfer.AccountTransferServiceImpl">
                <property name="accountDataManager" ref="accountDataManager"/>
                <property name="customerDataManager" ref="customerDataManager"/>
        </bean>
</beans>

Add the following Action class file to the project

package strutsexample;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import accountTransfer.AccountTransferServiceIF;

public class AccountTransferAction extends Action {
        private static final Log logger = LogFactory.getLog(AccountTransferAction.class);

        private AccountTransferServiceIF accountTransferService;

        public AccountTransferServiceIF getAccountTransferService() {
                return accountTransferService;
        }

        public void setAccountTransferService(
                        AccountTransferServiceIF accountTransferService) {
                this.accountTransferService = accountTransferService;
        }

        @Override
        public ActionForward execute(ActionMapping mapping, ActionForm form,
                        HttpServletRequest request, HttpServletResponse response)
                        throws Exception {

                logger.info("struts action ran with: " + accountTransferService);

                return mapping.findForward("success");
        }
}

Add the following JSP’s to the project.

src/main/webapp/pages/accountTransferSuccess.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
 <title>XHTML 1.0 Strict Template</title>
 <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
 <meta http-equiv="Content-Language" content="en-us" />
 </head>
 <body>

Account Transfer Success!

</body>
</html>

src/main/webapp/pages/accountInput.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
        <title>XHTML 1.0 Strict Template</title>
        <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
        <meta http-equiv="Content-Language" content="en-us" />
</head>
<body>
        <form action="AccountTransferSubmit.do">
        <input type="text" value="test" />
        <input type="submit"/>
        </form>
</body>
</html>

That’s all! you just spring enabled your struts application!

package strutsexample;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import accountTransfer.AccountTransferServiceIF;

public class AccountTransferAction extends Action {
private static final Log logger = LogFactory.getLog(AccountTransferAction.class);

private AccountTransferServiceIF accountTransferService;

public AccountTransferServiceIF getAccountTransferService() {
return accountTransferService;
}

public void setAccountTransferService(
AccountTransferServiceIF accountTransferService) {
this.accountTransferService = accountTransferService;
}

@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {

logger.info(“struts action ran with: ” + accountTransferService);

return mapping.findForward(“success”);
}
}

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
Advertisements

2 Responses to “Integrating Core Spring with the Struts Framework”


  1. September 10, 2010 at 2:06 pm

    Thanks for this post.

    I had the struts-to-spring imported as a resource not as a plug-in; after reading this.. it all came together.

    Cheers,

    Andrew


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 74 other followers

September 2009
S M T W T F S
« Aug   Oct »
 12345
6789101112
13141516171819
20212223242526
27282930  

Blog Stats

  • 801,304 hits

%d bloggers like this: