Using Struts Actions as Spring Beans

The approach we described in the previous section represents a working solution, but it is still a bit too clumsy to use in a real application. The ideal solution is to declare the Struts actions as Spring beans and let Spring set all the required dependencies. You can achieve this using ContextLoaderPlugin. This Struts plugin loads Spring application context for a Struts ActionServlet. The loader automatically refers to the root WebApplicationContext; the namespace for the context loaded by the plugin is the name of the Struts ActionServlet with –servlet appended to it. By default, the XmlWebApplicationContext is used to load the context file.

This still does not solve the problem of having to create the actions as subclasses of ActionSupport, as shown in Listing 19-8. It would be better if we could define that the beans in the Spring application context are proxies to the Struts Actions. Let's create a SpringIndexAction class that is a direct subclass of the Action class, as shown in Listing 19-10.

Listing 19-10: SpringIndexAction Implementation

image from book
package com.apress.prospring.ch19.web.actions;      import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;      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 com.apress.prospring.ch19.business.ProductManager;      public class SpringIndexAction extends Action {          private ProductManager productManager;          public final ActionForward execute(ActionMapping mapping, ActionForm form,          HttpServletRequest request, HttpServletResponse response)          throws Exception {         request.setAttribute("products", productManager.findAll());              return mapping.findForward("success");     }          public final void setProductManager(ProductManager productManager) {         this.productManager = productManager;     } }
image from book

Furthermore, the SpringIndexAction declares a setter for the productManager property. We need to add an action declaration to the Struts configuration file (see Listing 19-11).

Listing 19-11: SpringIndexAction Declaration

image from book
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE struts-config PUBLIC     "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"     "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">      <struts-config>     <action-mappings>         <action path="/index"              type="com.apress.prospring.ch19.web.actions.IndexAction"              validate="false">             <forward name="success" path=".index"/>         </action>         <action path="/sindex"             type=" org.springframework.web.struts.DelegatingActionProxy "              validate="false">             <forward name="success" path=".index"/>         </action>     </action-mappings>     <!-- the rest of the file as usual --> </struts-config>
image from book

Notice that the action type is set to DelegatingActionProxy, which is a Spring class that delegates all calls to the real bean of the SpringIndexAction class.

Before we can use DelegatingActionProxy, we first need to add the ContextLoaderPlugin bean to the Struts configuration file, as shown in Listing 19-12.

Listing 19-12: ContextLoaderPlugin Definition

image from book
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE struts-config PUBLIC     "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"     "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">      <struts-config>     <!-- other definitions omitted -->     <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">         <set-property property="contextConfigLocation"              value="/WEB-INF/ch19-context.xml"/>     </plug-in> </struts-config> 
image from book

We set the default location of contextConfigFile to /WEB-INF/ch19-context.xml because we declare the SpringIndexAction there. The context file is empty; to be more precise, it contains a single bean defined as <bean />, that only passes the DTD validation. The last pieces of the puzzle that connect the SpringIndexAction to the Spring DI mechanism are the DelegatingActionProxy beans in the Spring application context file. You must set the bean name to the action path from the Struts configuration file. We can then set all the properties in the usual Spring way. Listing 19-13 shows the Spring application context file that introduces the true DI to Struts.

Listing 19-13: Spring Application Context File

image from book
<?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="/sindex"          bold">com.apress.prospring.ch19.web.actions.SpringIndexAction">         <property name="productManager"><ref bean="productManager"/></property>     </bean>      </beans>
image from book

When we now make a request to the /sindex.do URL, DelegatingActionProxy looks up the bean with its name set to /sindex. It uses the beans defined in the WebApplicationContext that is loaded by the ContextLoaderPlugin declared in the file specified in its contextConfigLocation property. The /sindex bean is the actual SpringIndexAction, it is instantiated, and its productManager property is set.

The final result is no different from the output you saw in Listing 19-10 except that the SpringIndexAction is a fully Spring-managed bean and we have no manual dependency lookup code in the Action.



Pro Spring
Pro Spring
ISBN: 1590594614
EAN: 2147483647
Year: 2006
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net