I did some work on some docs. Here's the beginnings... Please feel free to add :-)Title: Xwork Documentation
XWork
Introduction
What is Xwork?
Xwork is a generic command pattern framework.
Xwork 1.0 Mission Statement:The Purpose: To create a generic, reusable, and extensible command pattern framework not tied to any particular usage.
Features:
* Flexible and customizable configuration based on a simple Configuration interface
* Core command pattern framework which can be customized and extended through the use of interceptors to fit any request / response environment
* Built in type conversion and action property validation using Ognl
* Powerful validation framework based on runtime attributes and a validation interceptor
How does Xwork relate to Webwork?
Webwork 2.0 is built on top of Xwork.
Webwork 2.0 Mission Statement:
The Purpose: To create the best Model-2 MVC web application framework supporting advanced web application development paradigms such as component based development and code reuse.
Features:
* Built on XWork, but customized to be specifically tailored for web application development
* Custom web-specific Xwork interceptors
* Flexible configuration extended from Xwork with web-specific configuration parameters
* Multiple web-based views, including custom JSP taglibs, Velocity support with pre-built macros, XSLT views, and JasperReport
The Basics
Actions
Actions are the basic unit of execution...
The Action Interface
ActionSupport
ActionContext
Lifecycle
No FormBeans?
Xwork / Webwork does not require the use of FormBeans
like Struts...
Configuration - Xwork.xml
Xwork is configured through the use of a file named xwork.xml in the root of the classpath. This file defines the action and interceptor configurations and mappings.
Packages
The primary unit of configuration in XWork is a package. Packages define a context for configuring and referencing actions and interceptors. All action and interceptor references are scoped inside a package. Here's an example package definition:
<package name="foo" extends="default" namespace="/foo">
<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="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
<interceptor name="result" class="com.opensymphony.xwork.interceptor.ResultInterceptor"/>
<interceptor name="stack" class="com.opensymphony.xwork.interceptor.StackInterceptor"/><interceptor-stack name="defaultStack">
<interceptor-ref name="result"/>
<interceptor-ref name="static-params"/>
<interceptor-ref name="params"/>
<interceptor-ref name="stack"/>
</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>
</package>We'll take the components of this package declaration one-by-one to understand what this file is doing.
Package
The package element has one required attribute, "name", which acts as the key for later reference to this package. The "extends" attribute is optional and allows one package to inherit the configuration of a previous package 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.
Namespace
The 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.
Result-Type
Result 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.
Interceptors
Interceptors 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-Stack
The 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.
Global-results
The 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.
Action
The 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). 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. 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.
Ognl
Ognl is used as both the expresion language and bean population utility for Xwork...
Interceptors
Interceptors allow you to define code to be executed before and after the execution of an action. They are defined outside the action class, yet have access to the action and the action execution environment at runtime, allowing you to encapsulate cross-cutting concerns and provide separation of concerns. Interceptors are given the ActionInvocation object at runtime, and may do whatever processing needed, then forward processing to the rest of the ActionInvocation, which will either call the next Interceptor or the Action, if there are no more Interceptors, and do whatever post-processing needed. Interceptors may also decide to short-circuit processing and return whatever result string desired WITHOUT forwarding processing, thus keeping the Action from executing. This ability should be used with caution, however, as any data loading or processing expected to be done by the Action will not happen.
Utility InterceptorsThe AbstractInterceptor defines a base class for interceptor implementations. It delegates calls to subclasses, which must implement the abstract methods before() and after(). The before() call is first called, then the rest of the ActionInvocation is called and the String result is saved (and is available to the Interceptor implementation during the after() method). Finally, the after() method is called and the result is returned.
The TimerInterceptor and LoggingInterceptor are provided as simple examples and utilities. The LoggingInterceptor simply logs before and after executing the rest of the ActionInvocation. The TimerInterceptor times the execution of the remainder of the ActionInvocation by setting a java.lang.Long into the ActionContext before executing the remainder of the ActionInvocation, then it retrieves the Long from the ActionContext afterwards and uses it to compute the total execution time. The reason that the TimerInterceptor saves the Long into the ActionContext is that Interceptors must be stateless, and because the TimerInterceptor extends AbstractInterceptor, which provides callback methods for before() and after(). If TimerInterceptor directly implemented Interceptor, it could contain the before and after processing with the execution of the rest of the ActionInvocation in one method call (the call to invoke() from the Interceptor interface).
Parameter Interceptors - populating your ActionThe StaticParametersInterceptor and ParametersInterceptor populate your Action fields during the ActionInvocation execution. The StaticParametersInterceptor applies the parameters defined in the Action configuration with the <param> elements. The ParametersInterceptor populates the Action with the parameters passed in as part of the request. The StaticParametersInterceptor should be applied before the ParametersInterceptor so that the static parameters may be set as the defaults and overridden by the request parameters.
ResultInterceptor, ChainingInterceptor, StackInterceptor...Patrick please fill in here....
Validation Framework (optional)
To be filled in...The ValidationInterceptor
Defining validation rules in a validation.xml
Building a FieldValidator
Localized and Parameterized messages