xwork.xml
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.0.dtd"> <xwork> <package name="default"> <result-types> <result-type name="chain" class="com.opensymphony.xwork.ActionChainResult"/> </result-types> <interceptors> <interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/> <interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/> <interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/> <interceptor name="test" class="com.opensymphony.xwork.TestInterceptor"> <param name="foo">expectedFoo</param> </interceptor> <interceptor-stack name="defaultStack"> <interceptor-ref name="static-params"/> <interceptor-ref name="params"/> </interceptor-stack> <interceptor-stack name="debugStack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> </interceptor-stack> </interceptors> <global-results> <result name="login" type="chain"> <param name="actionName">login</param> </result> </global-results> <action name="Foo" class="com.opensymphony.xwork.SimpleAction"> <param name="foo">17</param> <param name="bar">23</param> <result name="success" type="chain"> <param name="actionName">Bar</param> </result> <interceptor-ref name="debugStack"/> <interceptor-ref name="defaultStack"/> </action> <action name="Bar" class="com.opensymphony.xwork.SimpleAction"> <param name="foo">17</param> <param name="bar">23</param> </action> <action name="TestInterceptorParam" class="com.opensymphony.xwork.SimpleAction"> <interceptor-ref name="test"> <param name="expectedFoo">expectedFoo</param> </interceptor-ref> </action> <action name="TestInterceptorParamOverride" class="com.opensymphony.xwork.SimpleAction"> <interceptor-ref name="test"> <param name="foo">foo123</param> <param name="expectedFoo">foo123</param> </interceptor-ref> </action> </package> <package name="bar" extends="default" namespace="/foo/bar"> <interceptors> <interceptor-stack name="barDefaultStack"> <interceptor-ref name="debugStack"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <action name="Bar" class="com.opensymphony.xwork.SimpleAction"> <interceptor-ref name="barDefaultStack"/> </action> <action name="TestInterceptorParamInheritance" class="com.opensymphony.xwork.SimpleAction"> <interceptor-ref name="test"> <param name="expectedFoo">expectedFoo</param> </interceptor-ref> </action> </package> <package name="abstractPackage" namespace="/abstract" abstract="true"> <action name="test" class="com.opensymphony.xwork.SimpleAction"/> </package> <package name="nonAbstractPackage" extends="abstractPackage" namespace="/nonAbstract"/> <package name="multipleInheritance" extends="default,abstractPackage,bar" namespace="multipleInheritance"> <action name="testMultipleInheritance" class="com.opensymphony.xwork.SimpleAction"> <result name="success" type="chain"> <param name="actionName">foo</param> </result> <interceptor-ref name="barDefaultStack"/> </action> </package> <include file="includeTest.xml"/> </xwork> xwork.xml elementsPackageThe package element has one required attribute, "name", which acts as the key to later reference this package. The "extends" attribute is optional and allows one package to inherit the configuration of one or more previous packages including all interceptor, interceptor-stack, and action configurations. Note that the configuration file is processed sequentially down the document, so the package referenced by an "extends" should be defined above the package which extends it. The "abstract" optional attribute allows you to make a package abstract, which will allow you to extend from it without the action configurations defined in the abstract package actually being available at runtime. (see above for example)
NamespaceThe optional namespace attribute warrants its own discussion section. The namespace attribute allows you to segregate action configurations into namespaces, so that you may use the same action alias in more than one namespace with different classes, parameters, etc. This is in contrast to Webwork 1.x, where all action names and aliases were global and could not be re-used in an application. The default namespace, which is "" (an empty string) is used as a "catch-all" namespace, so if an action configuration is not found in a specified namespace, the default namespace will also be searched. This allows you to have global action configurations outside of the "extends" hierarchy, as well as to allow the previous Webwork 1.x behavior by not specifying namespaces. It is also intended that the namespace functionality can be used for security, for instance by having the path before the action name be used as the namespace by the Webwork 2.0 ServletDispatcher, thus allowing the use of J2EE declarative security on paths to be easily implemented and maintained. (see above for example) Result-TypeResult types define classes and map them to names to be referred in the action configuration results. This serves as a shorthand name-value pair for these classes. InterceptorsInterceptors also serve as a name-value pairing for referring to specific Interceptor classes by a shorthand name where we use interceptor-ref elements, such as in Interceptor stacks and action configurations. Interceptor-StackThe interceptor-stack element allows you to assign a name for later referencing via interceptor-ref to an ordered list of interceptors. This allows you to create standard groups of interceptors to be used in a certain order. The interceptor stack name/value pairs are stored in the same map as the interceptor definitions, so anywhere you use an interceptor-ref to refer to an interceptor you may also refer to an interceptor stack. Interceptor ParameterizationInterceptors are instantiated and stored at the ActionConfig level, i.e. there will be one instance per action configured in xwork.xml. These Interceptor instances may be parameterized at either the declaration level, where you map an Interceptor class to a name to be referenced later, like so: <interceptor name="test" class="com.opensymphony.xwork.TestInterceptor"> <param name="foo">expectedFoo</param> </interceptor> or at the interceptor-ref level, either inside an interceptor-stack or in an action declaration, like so: <interceptor-ref name="test"> <param name="expectedFoo">expectedFoo</param> </interceptor-ref> Although it is allowed by the DTD, parameters applied to interceptor-refs which refer to interceptor-stack elements will NOT be applied, and will cause a warning message. Global-resultsThe global results allows you to define result mappings which will be used as defaults for all action configurations and will be automatically inherited by all action configurations in this package and all packages which extend this package. ActionThe action element allows the mapping of names to action classes. These names are used, along with the namespace described above, to retrieve the action config from the configuration. The action may also be parameterized by using the param elements, as above, which will set parameters into the Action at execution (with the help of the StaticParametersInterceptor). When defining actions, sometimes you actually don't need any class, but rather are just putting in a placeholder for accessing interceptors and results. You can use ActionSupport for a simple action that has all of the XWork features but doesn't actually do anything. In fact, rather than defining your action class, if you leave it empty it defaults to ActionSupport. <action name="foo">
...
</action>
The action may also have one or more results mapped to string return codes, such as "success", "error", or "input", which are the default 3 return states for actions, although ANY return string may be used and mapped to a result. The result, which is mapped to a result class by the "type" attribute which refers to the result-type name defined above, may also be parameterized by using the param element. There is one shortcut when defining results, as a lot of the time a result will have only one parameter (which is often a location to redirect to (when using XWork in the web sense)). Here is the long form of a result with a single location parameter: <result name="test"> <param name="location">foo.jsp</param> </result> and this is the 'shortcut' form: <result name="test">foo.jsp</result>
Note that this shortcut only works when there is a single parameter for the result and the result has defined what its default parameter is. If your result name is "success", then you can take this shortcut even further by just doing: <result>success.jsp</result>
<action name="foo">
<result>foo.jsp</result>
</action>
Similar to the interceptor Syntax shown above, actions may be parametrized: <action name="Foo" class="com.opensymphony.xwork.SimpleAction"> <param name="foo">17</param> ... </action> In this example, it would be tried to call the setFoo() method in SimpleAction with the given value when Foo.action is called. If SimpleAction is model driven, setFoo() is invoked on the model. The action may also define one or more interceptor refs to either interceptors or interceptor stacks to be applied before and after the action execution (see the section on Interceptors below). The ordering of these interceptor refs determines the order in which they will be applied. Includes - using multiple configuration filesThe xwork.xml configuration file may be broken up into several files, each with its own set of package declarations, by using the <include> element zero or more times at the bottom of your xwork.xml file, like so: <include file="includeTest.xml"/>
These files will be processed, in order, in the same manner as the main xwork.xml, thus may have all of the same structures, including the <include> element. Although it is, therefore, possible to have packages in configuration files listed later in an include element extend packages defined in an earlier included file, it is not recommended. It should be considered best practice, in the case of using multiple configuration files, to declare default packages meant to be extended in the xwork.xml and to have no dependencies between sub-configuration files. Configuration ProvidersXWork configuration is handled through classes which implement the ConfigurationProvider interface. The default implementation is the XmlConfigurationProvider class. You can either create a new provider by implementing the ConfigurationProvider interface or you can extend the XmlConfigurationProvider class. The XmlConfigurationProvider class includes a protected method called getInputStream() which is called to acquire the configuration InputStream which is expected to be an XML data stream. The default implementation looks for a file called xwork.xml in the class path but by overriding the getInputStream() method you can pull configuration data from any source. Custom configuration providers must be registered with the ConfigurationManager before they will be used to load configuration data. If no custom configuration providers are registered then the default configuration provider is used. If any custom configuration providers are registered then the default configuration provider will no longer be used (although you could add a new instance of it yourself to include it in the list of providers which is searched). To add a configuration provider just call the ConfigurationManager.addConfigurationProvider() method with the custom configuration provider as the argument. |