XWork : Components
This page last changed on Jun 25, 2004 by unkyaku.
OverviewXWork provides the ComponentManager interface (and a corresponding implementation in the DefaultComponentManager class) to allow a design pattern known as Inversion of Control (or IoC for short) to be applied to your actions or other arbitrary objects. In a nutshell, the IoC pattern allows a parent object (in this case XWork's ComponentManager instance) to control a client object (usually an action, but it could be any object that implements the appropriate enabler).You may also want to look at WW:Components to see how WW2 uses XWork's IoC architecture. Why IoC?So why is IoC useful? It means that you can develop components (generally services of some sort) in a top-down fashion, without the need to build a registry class that the client must then call to obtain the component instance. Traditionally when implementing services you are probably used to following steps similar to these:
Using IoC, the process is reduced to the following:
XWork takes care of passing components through to enabled action classes or other components. Some other benefits that IoC can provide include:
Configuration - xwork.xmlThe ComponentInterceptor class is used to apply the IoC pattern to XWork actions (ie, to supply components to actions). The ComponentInterceptor should be declared in the <interceptors> block of xwork.xml as follows: <interceptor name="component"
class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
You should ensure that any actions that are to be supplied with components have this interceptor applied. (See XW:Interceptors for information on how to apply interceptors to actions.) If you want to apply IoC to objects other than actions or other components, you will need to use the ComponentManager object directly.Writing Component ClassesThe actual component class can be virtually anything you like. The only constraints on it are that it must be a concrete class with a default constructor so that XWork can create instances of it as required. Optionally, a component may implement the Initializable and/or Disposable interfaces so it will receive lifecycle events just after it is created or before it is destroyed. Simply:public class MyComponent implements Intializable, Disposable { public void init () { //do initialization here } public void dispose() { //do any clean up necessary before garbage collection of this component } } Component DependenciesOne feature that is not immediately obvious is that it is possible for components to depend on other components. For example if the ExchangeRateService described above depended on a Configuration component, XWork will pass the Configuration component through to the ExchangeRateService instance after ExchangeRateService is instantiated. Note that XWork automatically takes care of initializing the components in the correct order, so if A is an action or component that depends on B and C, and B depends on C and if A, B, and C have not been previously instantiated, the ComponentManager will in the following order:
And so on and so forth. Of course, if there are instances of B or C that would be reused in this case, those instances would be passed using the enabler method rather than a new instance. Writing EnablersAn enabler should consist of just a single method that accepts a single parameter. The parameter class should either be the component class that is to be enabled, or one of the component's superclasses. XWork does not care what the name of the enabler's method is.Here is an example of what the ExchangeRateAware enabler might look like: public interface ExchangeRateAware { public void setExchangeRateService(ExchangeRateService exchangeRateService); } Note that typically an enabler would be an interface, however there is nothing to prevent you from using a class instead if you so choose. Writing "Enabler-aware" ActionsAll an action needs to do is implement the relevant enabler interface. XWork will then call the action's enabler method just prior to the action's execution. As a simple example: public class MyAction extends ActionSupport implements ExchangeRateAware { ExchangeRateService ers; public void setExchangeRateService(ExchangeRateService exchangeRateService) { ers = exchangeRateService; } public String execute() throws Exception { System.out.println("The base currency is " + ers.getBaseCurrency()); } } If you have an object that is not an action or another component, you must explictly tell XWork to supply any enabled components to your object by calling componentManager.initializeObject(enabledObject); Using an external reference resolverYou can also use an external reference resolver in XWork, i.e., references that will be resolved not by XWork itself. One such example is using an external resolver to integrate XWork with the Spring Framework You just need to write an external reference resolver and then tell XWork to use it in the package declaration:<package
name="default"
externalReferenceResolver="com.atlassian.xwork.ext.SpringServletContextReferenceResolver">
Now, to use external references you do something like this: <external-ref name="foo">Foo</external-ref> Where the name attribute is the setter method name and Foo is the reference to lookup. For more details and sample code about this integration, take a look at the javadocs to the com.opensymphony.xwork.config.ExternalReferenceResolver class (unfortunately unavailable online) and at XW-122 -Chris |
![]() |
Document generated by Confluence on Dec 12, 2004 12:35 |