Tuesday, November 24, 2009

Modular application development using Struts - SwitchAction

Action classes are the important part of the Struts framework. Action classes are where your presentation logic resides. Struts 1.1 (and higher) provides some types of Action out-of-the-box, so you don't have to build them from the scratch. The Actions provided by Struts are ForwardAction, IncludeAction, DispatchAction, LookupDispatchAction and SwitchAction. All these classes are defined in org.apache.struts.actions package. These built-in actions are very helpful to address some problems faced in day to day programming. Understanding them is the key to using them effectively. All of these the Actions are frequently used, except for IncludeAction.

The SwitchAction class allows you to configure multiple application modules. In Struts1.0 (and earlier), a single config file was supported. This file, normally called struts-config.xml, was specified in web.xml as an initialization parameter for the ActionServlet as follows:
<servlet>

    <servlet-name>mybank</servlet-name>  
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

    <init-param>  
        <param-name>config</param-name>

        <param-value>/WEB-INF/struts-config.xml</param-value>  
    </init-param>

</servlet>


The single configuration file is bottleneck in large projects as all developers had to contend to modify this resource. In addition managing a monolithic file is painful and error prone. With Struts1.1 (and higher) this problem has been resolved by the addition of multiple sub application support better known as application modules. You can now have multiple configuration files, one for each module or logical group of forms. The configuration files are specified in web.xml file using multiple <init-param> - initialization parameters.

An example of the how to do this in a web.xml file is as below:




<servlet> 
    <servlet-name>action</servlet-name>

    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>  
    <init-param>

      <param-name>config</param-name>  
      <param-value>/WEB-INF/struts-config.xml</param-value>

    </init-param>  
    <init-param>

      <param-name>config/views/module1</param-name>  
      <param-value>/WEB-INF/struts-config-module1.xml</param-value>

    </init-param>  
    <init-param>

      <param-name>debug</param-name>  
      <param-value>3</param-value>

    </init-param>  
    <init-param>

      <param-name>detail</param-name>  
      <param-value>3</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>  
</servlet>
<servlet-mapping>  
    <servlet-name>action</servlet-name>

    <url-pattern>*.action</url-pattern>  
</servlet-mapping>

The above web.xml defines the servlet mapping for the action servlet to all URL patterns that ends with ‘.action’, and /WEB-INF/struts-config.xml to be the struts configuration file. You might be wondering what does the below configuration do:




<init-param> 

      <param-name>config/views/Module1</param-name>  
      <param-value>/WEB-INF/struts-config-module1.xml</param-value>  
</init-param>

The above initialization parameter name begins with ‘config/’. ‘config/’ is treated as a keyword for defining a new module. It is interpreted as a configuration for a separate module. Its corresponding value – /WEB-INF/struts-config-module1.xml is the struts configuration file containing Form bean definitions and ActionMappings for the module module1. If the URLs in the default struts-config.xml were accessed as http://localhost:8080/App1/start.action, and the corresponding ActionMapping were moved to struts-module1-config.xml then the URL would be accessed as http://localhost:8080/App1/module1/start.action where App1 is the web application context. Notice that the application URL contains the module name after the web application context as if it is a sub directory name.

The benefits of application modules are immediately obvious. You can now split your monolithic struts application into logical modules thus making maintenance easier. It will cause less contention during development time as developers working on different modules get to work on their own struts configuration files. Each Struts Configuration file and hence each application module can choose its own RequestProcessor, MessageResources and PlugIn. You can now choose to implement one or more modules with Tiles. If you find this convenient and useful then you can migrate your application to Tiles or JSF or plug in any other Struts extensions for one module at a time.

Now, lets look like how the struts-config.xml and struts-config-module1.xml files look like. Below is an extract from the struts-config.xml file:




<struts-config>

    <global-forwards>  

        <forward name="Module1" 

            path="/switch.action? page=/CreateCertificate.action&amp;prefix=/views/module1" /> 

    </global-forwards>

    <action-mappings>

        <action path="/switch"  
            type="org.apache.struts.actions.SwitchAction" />

    </action-mappings>    
    <controller processorClass="org.apache.struts.action.RequestProcessor" /> 
</struts-config>


struts-config-module1.xml file:



<struts-config>  
    <form-beans>

        <form-bean name="Form1"  
                    type="com.example.Form1"/>

        <form-bean name="Form2"

                    type="com.example.Form2"/>  
    </form-beans>


    <global-forwards>

        <forward name="mainpage" path="/"/>  
    </global-forwards>

    <action-mappings>

         <action path="/switch"

                type="org.apache.struts.actions.SwitchAction" />

         <action path="/start"  
                type="com.example.Module1Start"

                name="Form2"  
                scope="request"

                validate="true"  
                input="/input.jsp">

            <forward name="success" path="/switch.action?page=/success.jsp&amp;prefix=/views/module1"></forward>

            <forward name="failure" path="/switch.action?page=/error.jsp&amp;prefix=/views/module1"></forward>

        </action>

You might have noticed that




<action path="/switch"  
                type="org.apache.struts.actions.SwitchAction" /> 

has been defined in both the configuration files. This is important for the code to work properly.


Note: Source of most of the content- Struts Survival Guide, Author: Srikanth Shenoy.

1 comments:

Shilpa Mehta said...

Good post. It can be more meaty, if we add a scenario,which explains what purpose uses what type of Struts Action?

Post a Comment