Apache Struts 1.x and 2.x - Java-Springs

Struts used to be the de facto web framework for Java applications, mainly because it was one of the first to be released (June 2001). It has now been renamed to Struts 1 (as opposed to Struts 2). Many applications still use it. Invented by Craig McClanahan, Struts is an open source project hosted by the Apache Software Foundation. At the time, it greatly simplified the JSP/Servlet programming paradigm and won over many developers who were using proprietary frameworks. It simplified the programming model, it was open source (and thus free as in beer), and it had a large community, which allowed the project to grow and become popular among Java web developers.

To integrate your Struts 1.x application with Spring, you have two options:

  • Configure Spring to manage your Actions as beans, using the Context Loader Plugin, and set their dependencies in a Spring context file.
  • Subclass Spring's ActionSupport classes and grab your Spring-managed beans explicitly using a get Web Application Context() method.

ContextLoaderPlugin
The ContextLoaderPlugin is a Struts 1.1+ plug-in that loads a Spring context file for the Struts ActionServlet. This context refers to the root WebApplicationContext (loaded by the ContextLoader Listener) as its parent. The default name of the context file is the name of the mapped servlet, plus -servlet.xml. If ActionServlet is defined in web.xml as <servlet-name>action</servlet-name>, the default is /WEB-INF/action-servlet.xml.

To configure this plug-in, add the following XML to the plug-ins section near the bottom of your struts-config.xml file:

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"/>
The location of the context configuration files can be customized using the
'contextConfigLocation' property.
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml,/WEB-INF/applicationContext.xml"/>
</plug-in>

It is possible to use this plugin to load all your context files, which can be useful when using testing tools like StrutsTestCase. StrutsTestCase's MockStrutsTestCase won't initialize Listeners on startup so putting all your context files in the plugin is a workaround. (A bug has been filed for this issue, but has been closed as 'Wont Fix').

After configuring this plug-in in struts-config.xml, you can configure your Action to be managed by Spring. Spring (1.1.3+) provides two ways to do this:

  • Override Struts' default Request Processor with Spring's Delegating Request Processor.
  • Use the Delegating ActionProxy class in the type attribute of your <action-mapping>.

Both of these methods allow you to manage your Actions and their dependencies in the action-servlet.xml file. The bridge between the Action in struts-config.xml and action-servlet.xml is built with the action-mapping's "path" and the bean's "name". If you have the following in your struts-config.xml file:

<action path="/users" .../>
You must define that Action's bean with the "/users" name in action-servlet.xml:
<bean name="/users" .../>

DelegatingRequestProcessor
To configure the DelegatingRequestProcessor in your struts-config.xml file, override the "processorClass" property in the <controller> element. These lines follow the <action-mapping> element.

<controller>
<set-property property="processorClass"
value="org.springframework.web.struts.DelegatingRequestProcessor"/>
</controller>

After adding this setting, your Action will automatically be looked up in Spring's context file, no matter what the type. In fact, you don't even need to specify a type. Both of the following snippets will work:

<action path="/user" type="com.whatever.struts.UserAction"/>
<action path="/user"/>

If you're using Struts' modules feature, your bean names must contain the module prefix. For example, an action defined as <action path="/user"/> with module prefix "admin" requires a bean name with <bean name="/admin/user"/>.

DelegatingActionProxy
If you have a custom RequestProcessor and can't use the DelegatingRequestProcessor or DelegatingTilesRequestProcessor approaches, you can use the DelegatingActionProxy as the type in your action-mapping.

<action path="/user" type="org.springframework.web.struts.DelegatingActionProxy"
name="userForm" scope="request" validate="false" parameter="method">
<forward name="list" path="/userList.jsp"/>
<forward name="edit" path="/userForm.jsp"/>
</action>

The bean definition in action-servlet.xml remains the same, whether you use a custom RequestProcessor or the DelegatingActionProxy.

If you define your Action in a context file, the full feature set of Spring's bean container will be available for it: dependency injection as well as the option to instantiate a new Action instance for each request. To activate the latter, add scope="prototype" to your Action's bean definition.

<bean name="/user" scope="prototype" autowire="byName"
class="org.example.web.UserAction"/>

ActionSupport Classes
You can retrieve the WebApplicationContext from the ServletContext using the WebApplicationContextUtils class. An easier way is to extend Spring's Action classes for Struts. For example, instead of subclassing Struts' Action class, you can subclass Spring's ActionSupport class.

The ActionSupport class provides additional convenience methods, like getWeb ApplicationContext(). Below is an example of how you might use this in an Action:

public class UserAction extends DispatchActionSupport {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (log.isDebugEnabled()) {
log.debug("entering 'delete' method...");
}
WebApplicationContext ctx = getWebApplicationContext();
UserManager mgr = (UserManager) ctx.getBean("userManager");
// talk to manager for business logic
return mapping.findForward("success");
}
}

Spring includes subclasses for all of the standard Struts Actions - the Spring versions merely have Support appended to the name:

  • ActionSupport,
  • DispatchActionSupport,
  • LookupDispatchActionSupport and
  • MappingDispatchActionSupport.

The recommended strategy is to use the approach that best suits your project. Subclassing makes your code more readable, and you know exactly how your dependencies are resolved. In contrast, using the ContextLoaderPlugin allows you to easily add new dependencies in your context XML file. Either way, Spring provides some nice options for integrating with Struts.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Java-Springs Topics