As stated, using modules allows you to partition your Struts application into discrete functional areas, almost like having wholly separate applications. Each module has its own Struts configuration file, actions, forwards, and JSPs, allowing it to function independently of other modules. Using modules in a Struts application involves these three steps:
Create a Struts configuration file for each module.
Configure the web.xml deployment descriptor for modules.
Configure links to access module-specific JSPs.
The following sections explain how to configure and use modules in detail.
In order to separate each module's configuration details, you must create a separate Struts configuration file for each module. Having a separate configuration file for each module allows all of a module's actions, forwards, and so on to be grouped into one module-specific file that is independent of other modules' configuration data. You configure actions, forwards, and so on inside the file, just as you would with a non-modularized application. The only difference with module configuration files is in the way the Tiles and Validator plugin definitions are set up, which is described later in this chapter.
The typical naming convention for module configuration files is struts-config-module. xml, where module is the name of the module that the file is for. Note, however, that there are no restrictions on the names of module configuration files and thus any name can be used as long as it is unique. Alternatively, if your application is using Tiles and/or Validator, you may want to create a module-specific directory under /WEB-INF/ for each module to store its configuration files. For example, if your application is using modules, Tiles, and Validator, you could arrange the files as shown next:
/WEB-INF/moduleA/struts-config.xml /WEB-INF/moduleA/tiles-defs.xml /WEB-INF/moduleA/validation.xml /WEB-INF/moduleB/struts-config.xml /WEB-INF/moduleB/tiles-defs.xml /WEB-INF/moduleB/validation.xml
With this arrangement you wouldn't have to use the module name in the names of the configuration files, because they are under a module-specific directory.
Detailed information on the Struts configuration file is found in Chapter 18.
Each module's Struts configuration file has to be specified in the web.xml deployment descriptor, just as is done for non-modularized Struts applications; however, the way they are configured is slightly different. Recall that with a non-modularized application, you specify the path to the Struts configuration file with the config initialization parameter for the ActionServlet controller servlet, as shown next:
<!-- Action Servlet Configuration --> <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> <load-on-startup>1</load-on-startup> </servlet>
The config parameter is set to the location of your application's Struts configuration file.
To specify module configuration files, you need an initialization parameter for each module and it must be named config/moduleName, where moduleName is the name you want to assign to the module. For example, to specify two modules named moduleA and moduleB, your ActionServlet definition must look like this:
<!-- Action Servlet Configuration --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config/moduleA</param-name> <param-value>/WEB-INF/struts-config-moduleA.xml</param-value> </init-param> <init-param> <param-name>config/moduleB</param-name> <param-value>/WEB-INF/struts-config-moduleB.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
In this file, two configuration files are specified: struts-config-moduleA.xml and struts-config-moduleB.xml.
The name given to the module through the param-name tag is known as the module prefix and is very important. Struts uses the module prefix to distinguish and route requests to the module. The module name becomes part of the URL that must be used to access the module's actions.
It is important to understand that all of a module's action paths are relative to the module. For example, the modularized version of the Mini HR application developed later in this chapter is deployed at /MiniHR/ on the server (i.e., http://localhost:8080/MiniHR/). It has a module named employee, which has an action mapped to /search. Therefore, the URL to access the action is /MiniHR/employee/search.do. Figure 9-1 shows a breakdown of what each piece of the URL is.
Figure 9-1: The module URL breakdown
When using modules, the standard config parameter (that is, the one without any module name appended to it) is used to specify a configuration file for a default module. The default module has no module prefix, so any URL whose path does not include a module name will be routed to the default module. Thus, using the Mini HR example developed later in this chapter, if a request were made to /MiniHR/admin/viewAppUsers.do, Struts would execute the action mapped to /admin/viewAppUsers in the default module's configuration file, because the URL does not contain a module prefix.
A side effect of using modules is that you cannot use path mapping (e.g., /do/*) for the ActionServlet controller servlet. Instead, you must use extension mapping (e.g., *.do) because Struts uses the URL path to determine which module a request is being made for; using path mapping would interfere with that mechanism. For more information on setting up ActionServlet's mapping, refer to Chapter 5.
Modules fundamentally change the way JSPs are linked to and accessed in a Struts application. Recall that in non-modularized Struts applications, you link to and access JSPs just as you would in any Web application. With modules, the rules change because Struts requires that URLs that are used to access a module must have a module prefix that designates which module is being accessed. This is necessary to enable Struts to select the correct module configuration data to use for each request.
When using modules, Struts needs some way to know how to select the correct module configuration data to use for a JSP. Here's why: When you access JSPs, the request for the JSP does not go through the Struts controller servlet, as requests for actions do. Because of this, Struts does not have the opportunity to select the correct module configuration data to use for the JSP. Thus, if the JSP is using any Struts tag library tags that reference a Struts action, Struts will not know how to determine what action the JSP is trying to reference, because no module has been selected.
To solve this problem, all requests for module JSPs must be routed through the Struts controller servlet. Struts provides a built-in action called org.apache.struts.actions. SwitchAction to help with this. SwitchAction allows you to create module-specific JSP links that preserve the module name so that Struts can properly select the right module configuration data. SwitchAction does this by taking a module name and a JSP as request parameters. When executed, it takes care of selecting the module specified and then forwarding to the specified JSP.
This way, the module configuration data is set up for the JSP. To use SwitchAction, you must add an action definition for it in your Struts configuration file. Typically this is added to the default module configuration file, but you can add it to module-specific configuration files, too. Following is a sample SwitchAction definition:
<action path="/switchMod" type="org.apache.struts.actions.SwitchAction"/>
You can put this definition to use with the following example link:
<html:link action="/switchMod?prefix=/moduleA&page=/main.jsp"> ModuleA main JSP </html:link>
This example usage creates a link that will route the Struts request processor to the JSP at /moduleA/main.jsp and select the configuration data for moduleA.