Struts Configuration Semantics


This section discusses the configuration objects that the controller creates, caches, and uses for controlling the behavior of the framework. All configuration objects are available to a developer in request handlers via the ModuleConfig object; this object can be accessed using the Action.getModuleConfig() method; the configuration objects can be extended for implementing custom functionality.

Parsing the Configuration File

The configuration file, struts-config.xml, is parsed in the controller's init() method using an instance of org.apache.commons.digester.Digester; the Digester extends org.xml.sax.helpers.DefaultHandler. Internally, the Digester uses a SAX parser to parse the configuration file. From the configuration file, the Digester constructs an object hierarchy of configuration objects, rooted in the ModuleConfig object, using the rules specified in org.apache.struts.config.ConfigRuleSet; these rules govern object creation and population. More information about Digester is available at http://jakarta.apache.org/commons/digester.html. The rule set provided by ConfigRuleSet can be augmented by specifying the rulesets initialization parameter that provides a comma-delimited list of class names containing additional rules. The configuration file location is provided in web.xml by the config initialization parameter as follows:

 <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> </servlet> 

The configuration object hierarchy is created in the init() method of the controller and saved in the ServletContext using org.apache.struts.Globals.MODULE. At the root of the configuration hierarchy is the ModuleConfig object. The ModuleConfig object contains references to collections of all other configuration objects, with convenience methods for saving and retrieving these objects. The semantics of creating a configuration object tree is explained in the section "Creating Configuration Objects." The following sections briefly explain the purpose for each configuration object.

ActionMapping This object is created from the <action> element. It provides the mapping between an incoming request and the corresponding request handler. It also embeds ExceptionConfig and ActionForward objects; these subordinate objects are in the local scope of the ActionMapping object.

ActionForward This object is created from the <forward> element. It provides the URI of the next web component. ActionForward(s) are specified both in the local and global scope. Global scope is used when a required ActionForward is not found in the scope of the current ActionMapping object.

ActionFormBean This object is created from the <form-bean> element. It provides the mapping between a form name in the ActionMapping to an ActionForm subclass.

FormPropertyConfig This object is created from the <form-property> element. It provides the dynamic attribute names and types for creating a DynaActionForm object.

DataSourceConfig This object is created from the <data-source> element. It provides information for configuring a data source in the framework.

MessageResourcesConfig This object is created from the <message-resources> element. It provides the base name of a family of resource bundles.

ExceptionConfig This object is created from the <exception> element. It provides a message key and a URI of the next web component when an exception of a given type is thrown by the request handlers. ExceptionConfig(s) are specified both in the local and global scope. Global scope is used when a required ExceptionConfig is not found in the scope of the current ActionMapping object.

PlugInConfig This object is created from the <plug-in> element. It provides the class name of an external resource that needs to be instantiated within the framework, and whose init and destroy methods are to be called by the framework.

ControllerConfig This object is created from the <controller> element. It provides information for configuring the framework.

For a complete list of all the attributes that can be specified for each configuration object, refer to the API at http://jakarta.apache.org/struts/api/index.html.

ModuleConfig The ModuleConfig object caches configuration information as follows:

  1. ActionMapping objects are cached using a HashMap, keyed by the path attribute of the <action> element. The default ActionMapping class org.apache.struts.action.ActionMapping specified in the ModuleConfig class can be overridden using the mapping initialization parameter in the <servlet> declaration.

    Each ActionMapping object caches subordinate configuration information as follows:

    • ActionForward objects are cached using a HashMap, keyed by the name attribute in the <forward> element nested within the <action> tag.

    • ExceptionConfig objects are cached using a HashMap, keyed by the type attribute in the <exception> element nested in the <action> tag.

  2. ActionForward objects are cached using a HashMap, keyed by the name attribute of the <forward> element nested within the <global-forwards> tag.

  3. ActionFormBean objects are cached using a HashMap, keyed by the name attribute of the <form-bean> element.

    Each ActionFormBean caches subordinate configuration information as follows:

    • FormPropertyConfig objects are cached using a HashMap, keyed by name attribute of the <form-property> element nested within the <form-bean> tag.

  4. DataSourceConfig objects are cached using a HashMap, keyed by a default Globals.DATA_SOURCE_KEY or the key attribute on the <data-source> element.

  5. ExceptionConfig objects are cached using a HashMap, keyed by the type attribute of the <exception> element nested in the <global-exceptions> tag.

  6. MessageResourcesConfig objects are cached using a HashMap, keyed by a default Globals.MESSAGES_KEY or key attribute of the <message-resources> element.

  7. PlugInConfig objects are cached using an ArrayList.

  8. A single ControllerConfig is placed in the ModuleConfig.

Creating Configuration Objects

Each rule in the ConfigRuleSet is associated with an element nesting pattern; an example pattern appears as the first argument in the addObjectCreate () signature shown next. The patterns and associated rules are first registered with the Digester using several addRuleName() methods encapsulated in ConfigRuleSet class. During struts-config.xml parsing, the rules are fired when an element nesting pattern in the struts-config.xml file matches with a pattern for which a rule is registered. For a given pattern, there could be more than one registered rule; in this case all matching rules are evaluated in the order they were first registered. Refer to the API documentation at http://jakarta.apache.org/commons/digester/api/index.html for additional information.

In this section, the ConfigRuleSet is annotated for clarifying the relationship between different configuration objects and their creation sequence. The following convention is used for adding rules to the digester's rules cache.

 digester.addObjectCreate("struts-config/data-sources/data-source",          "org.apache.struts.config.DataSourceConfig",          "className"); 

The preceding snippet is equivalent to the following code:

 digester.addRule("struts-config/data-sources/data-source",      new ObjectCreateRule("org.apache.struts.config.DataSourceConfig", "className")); 

Annotated ConfigRuleSet

It is not necessary to read this subsection if your intent is only to use the Struts framework; however, if you wanted to extend the framework to suite the needs of your project, this "under the hood" discussion can provide you with useful information on how you can declaratively add additional properties to the various configuration objects used by Struts, and even add new configuration objects.

Digester uses a stack to create the configuration object hierarchy. It pushes the most recently created object on top of the stack, therefore, the object to which all rules apply is the object that was most recently created and pushed on the stack by the Digester using the ObjectCreateRule. The object on the top of the stack goes out of scope, and is subsequently popped, when the corresponding tag in struts-config.xml goes out of scope. It is convenient to equate the ModuleConfig object to document root, which is <struts-config>. The runtime representation of rules are concrete objects that extend the Rule class. The order of rules firing, as depicted next, is important for creating an appropriate object hierarchy.

The ObjectCreateRule instantiated as a result of the element nesting pattern struts-config/data-sources/data-source shown here will create a DataSourceConfig object. If the <data-source> element specifies a className attribute, the class specified by this attribute will be used, instead of DataSourceConfig, for creating the configuration object. The default DataSource object created by DataSourceConfig is of the type org.apache.struts.util .GenericDataSource.

 digester.addObjectCreate("struts-config/data-sources/data-source",          "org.apache.struts.config.DataSourceConfig",          "className"); 

The SetPropertiesRule shown next will set the properties of this object with attributes specified in the <data-source> element of the configuration file.

 digester.addSetProperties("struts-config/data-sources/data-source"); 

The SetNextRule shown next will call the addDataSourceConfig method of the root object in the configuration hierarchy to add a reference to the DataSourceConfig object in the root object; the configuration root object is ModuleConfig.

 digester.addSetNext("struts-config/data-sources/data-source",          "addDataSourceConfig",          "org.apache.struts.config.DataSourceConfig"); 

The AddDataSourcePropertyRule instantiated as a result of the element nesting pattern struts-config/data-sources/data-source/set-property shown next will add dynamic properties and their values to the DataSourceConfig object as specified in the <set-property> element of the configuration file.

 digester.addRule("struts-config/data-sources/data-source/set-property",          new AddDataSourcePropertyRule(digester)); 

The struts-config.xml file will have following declarations for the preceding rule:

 <struts-config>   <data-sources>     <data-source>       <set-property property="autoCommit"  value="false"/>       <set-property property="password"    value="mypassword"/>     </data-source>   </data-sources> </struts-config> 

The SetActionMappingClassRule instantiated as a result of the element nesting pattern struts-config/action-mappings, as shown next, will set the class name of the action mapping class for instantiating ActionMapping objects. The action mapping class name is set in the ModuleConfig object using the type attribute in the <action-mappings> element. A default action mapping class org.apache.struts.action.ActionMapping is preconfigured in ModuleConfig.

 digester.addRule("struts-config/action-mappings",          new SetActionMappingClassRule(digester)); //As of Struts 1.1 beta 2, SetActionMappingClassRule class is in ConfigRuleSet.java file 

The FactoryCreateRule is instantiated as a result of the element nesting pattern struts-config/action-mappings/action, as shown next. This rule will instantiate an ActionMapping object via the ActionMappingFactory.createObject() method which uses the class specified by the className attribute in the <action> element; if this element is not specified, it will use the action mapping class specified in the ModuleConfig object.

 digester.addFactoryCreate("struts-config/action-mappings/action",          new ActionMappingFactory()); //As of Struts 1.1, ActionMappingFactory class is in ConfigRuleSet.java file 

The SetPropertiesRule shown next will set the properties of the ActionMapping object with attributes specified on the <action> element of the configuration file; the SetNextRule shown next will call the addActionConfig method to add a reference to this ActionMapping object in the parent object, which is ModuleConfig. As discussed in the earlier section "Parsing the Configuration File," all ActionMapping objects are cached inside the ModuleConfig in a HashMap. Similar discussion holds good for all other configuration objects with the exception of PlugInConfig, which is cached in an ArrayList.

 digester.addSetProperties("struts-config/action-mappings/action"); digester.addSetNext("struts-config/action-mappings/action",          "addActionConfig",          "org.apache.struts.config.ActionConfig"); 

The SetPropertyRule shown next is instantiated as a result of the element nesting pattern struts-config/action-mappings/action/set-property. This rule allows declaration of two attributes; the first attribute will contain the name of the property, and the second attribute will contain the property value. Incidentally, in the following example, the first attribute that will contain the name of the property has a value "property", and the second attribute that will contain the property value is named "value". The ActionMapping object accessor is called for setting the value of the specified property for each <set-property> element. This is just another way of setting properties of the configuration objects.

 digester.addSetProperty("struts-config/action-mappings/action/set-property", "property", "value"); 

The struts-config.xml file will have the following declarations for the preceding rule:

 <struts-config>    <action-mappings>       <action path="/editCustomerProfile"               type="packageName.EditCustomerAction"               name="customerProfileForm"               scope="request">          <set-property property="scope" value="request"/>       </action>    </action-mappings> </struts-config> 

The following snippet creates the ExceptionConfig object, sets it properties as specified in the <exception> element of the configuration file, and sets a reference in its parent object, which is currently the ActionMapping object. The parent object is apparent from the element nesting pattern /action/exception:

 digester.addObjectCreate("struts-config/action-mappings/action/exception",          "org.apache.struts.config.ExceptionConfig",          "className"); digester.addSetProperties("struts-config/action-mappings/action/exception"); digester.addSetNext("struts-config/action-mappings/action/exception",          "addExceptionConfig",          "org.apache.struts.config.ExceptionConfig"); digester.addSetProperty("struts-config/action-mappings/action/exception/set- property",          "property", "value"); 

The following snippet creates the ActionForward object, sets it properties as specified in the <forward> element of the configuration file, and sets a reference in its parent object, which is currently the ActionMapping object. The parent object is apparent from element nesting pattern /action/forward:

 digester.addObjectCreate("struts-config/action-mappings/action/forward",          "org.apache.struts.action.ActionForward",          "className"); digester.addSetProperties("struts-config/action-mappings/action/forward"); digester.addSetNext("struts-config/action-mappings/action/forward",          "addForwardConfig",          "org.apache.struts.config.ForwardConfig"); digester.addSetProperty("struts-config/action-mappings/action/forward/set-prop erty",          "property", "value"); 

For the next rule, notice that the parent object is again the ModuleConfig object that is associated with the document root <struts-config>. The following snippet creates the ControllerConfig object, sets it properties as specified in the <controller> element of the configuration file, and sets a reference in its parent object, which is currently the ModuleConfig object:

 digester.addObjectCreate("struts-config/controller",          "org.apache.struts.config.ControllerConfig",          "className"); digester.addSetProperties("struts-config/controller"); digester.addSetNext("struts-config/controller",          "setControllerConfig",          "org.apache.struts.config.ControllerConfig"); digester.addSetProperty("struts-config/controller/set-property",          "property", "value"); 

The following creates the ActionFormBean object, sets it properties as specified in the <form-bean> element of the configuration file, and sets a reference in its parent object, which is currently the ModuleConfig object:

 digester.addObjectCreate("struts-config/form-beans/form-bean",          "org.apache.struts.action.ActionFormBean",          "className"); digester.addSetProperties("struts-config/form-beans/form-bean"); digester.addSetNext("struts-config/form-beans/form-bean",          "addFormBeanConfig",          "org.apache.struts.config.FormBeanConfig"); digester.addSetProperty("struts-config/form-beans/form-bean/set-property",          "property", "value"); 

The following snippet creates the FormPropertyConfig object, sets it properties as specified in the <form-property> element of the configuration file, and sets a reference in its parent object, which is currently the ActionFormBean object:

 digester.addObjectCreate("struts-config/form-beans/form-bean/form-property",          "org.apache.struts.config.FormPropertyConfig",          "className"); digester.addSetProperties("struts-config/form-beans/form-bean/form-property"); digester.addSetNext("struts-config/form-beans/form-bean/form-property",          "addFormPropertyConfig",          "org.apache.struts.config.FormPropertyConfig"); digester.addSetProperty(          "struts-config/form-beans/form-bean/form-property/set-property",          "property", "value"); 

The following snippet creates the global ExceptionConfig object, sets it properties as specified in the <exception> element of the configuration file, and sets a reference in its parent object, which is currently the ModuleConfig object:

 digester.addObjectCreate("struts-config/global-exceptions/exception",          "org.apache.struts.config.ExceptionConfig",          "className"); digester.addSetProperties("struts-config/global-exceptions/exception"); digester.addSetNext("struts-config/global-exceptions/exception",          "addExceptionConfig",          "org.apache.struts.config.ExceptionConfig"); digester.addSetProperty("struts-config/global-exceptions/exception/set-property",          "property", "value"); 

The following snippet creates the global ActionForward object, sets it properties as specified in the <forward> element of the configuration file, and sets a reference in its parent object, which is currently the ModuleConfig object:

 digester.addObjectCreate("struts-config/global-forwards/forward",          "org.apache.struts.action.ActionForward",          "className"); digester.addSetProperties("struts-config/global-forwards/forward"); digester.addSetNext("struts-config/global-forwards/forward",          "addForwardConfig",          "org.apache.struts.config.ForwardConfig"); digester.addSetProperty("struts-config/global-forwards/forward/set-property",          "property", "value"); 

The following snippet creates the MessageResourcesConfig object, sets it properties as specified in the <message-resources> element of the configuration file, and sets a reference in its parent object, which is currently the ModuleConfig object:

 digester.addObjectCreate("struts-config/message-resources",          "org.apache.struts.config.MessageResourcesConfig",          "className"); digester.addSetProperties("struts-config/message-resources"); digester.addSetNext("struts-config/message-resources",          "addMessageResourcesConfig",          "org.apache.struts.config.MessageResourcesConfig"); digester.addSetProperty("struts-config/message-resources/set-property",          "property", "value"); 

The following snippet creates the PlugInConfig object, sets it properties as specified in the <plug-in> element of the configuration file, and sets a reference in its parent object, which is currently the ModuleConfig object:

 digester.addObjectCreate("struts-config/plug-in",          "org.apache.struts.config.PlugInConfig"); digester.addSetProperties("struts-config/plug-in"); digester.addSetNext("struts-config/plug-in",          "addPlugInConfig",          "org.apache.struts.config.PlugInConfig"); digester.addRule("struts-config/plug-in/set-property",          new PlugInSetPropertyRule(digester)); //As of Struts 1.1, PlugInSetProperty class is in ConfigRuleSet.java file 




Practical J2ee Application Architecture
Practical J2EE Application Architecture
ISBN: 0072227117
EAN: 2147483647
Year: 2003
Pages: 111
Authors: Nadir Gulzar

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