Source

webwork / docs / wikidocs / Xwork's Component Architecture.html

Full commit
<html>
    <head>
        <title>WebWork 2 : Xwork's Component Architecture</title>
	    <link rel="stylesheet" href="styles/site.css" type="text/css" />
        <META http-equiv="Content-Type" content="text/html; charset=UTF-8">	    
    </head>

    <body>
	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
		    <tr>
			    <td valign="top" class="pagebody">
				    <div class="pageheader">
					    <span class="pagetitle">
                            WebWork 2 : Xwork's Component Architecture
                                                    </span>
				    </div>
				    <div class="pagesubheading">
					    This page last changed on Jun 18, 2004 by <font color="#0050B2">plightbo</font>.
				    </div>

				    <p class="paragraph"><h2 style="margin: 4px 0px 4px 0px;" class="heading2"><a name="Xwork%27sComponentArchitecture-WritingComponentClasses"> Writing Component Classes</a></h2></p>In <a href="http://wiki.opensymphony.com//display/XW/XWork" title="XWork">XW:XWork</a> the 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:<br/>

<div class="code"><div class="codeContent">
<pre><span class="java&#45;keyword">public</span> class MyComponent <span class="java&#45;keyword">implements</span> Intializable, Disposable &#123;&#10;    <span class="java&#45;keyword">public</span> void init () &#123;&#10;         <span class="java&#45;comment">//<span class="java&#45;keyword">do</span> initialization here</span>&#10;    &#125;&#10;&#10;    <span class="java&#45;keyword">public</span> void dispose() &#123;&#10;         <span class="java&#45;comment">//<span class="java&#45;keyword">do</span> any clean up necessary before garbage collection of <span class="java&#45;keyword">this</span> component</span>&#10;    &#125;&#10;&#125;</pre>
</div></div><p class="paragraph"><h2 class="heading2"><a name="Xwork%27sComponentArchitecture-ComponentDependencies"> Component Dependencies</a></h2></p>One 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:<br/>

<ol>
<li> Instantiate C and call it&#039;s init() method if it implements Initializable.</li>
<li> Instantiate B, then using the enabler method, set C to be used by B</li>
<li> Call B&#039;s init() method, if it implements Intitializable.</li>
<li> Set B using B&#039;s enabler method to be used by A.</li>
</ol><br/>
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.<p class="paragraph"><h2 class="heading2"><a name="Xwork%27sComponentArchitecture-WritingEnablers"> Writing Enablers</a></h2></p>An 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&#039;s superclasses. XWork does not care what the name of the enabler&#039;s method is.<p class="paragraph">Here is an example of what the ExchangeRateAware enabler might look like:</p><div class="code"><div class="codeContent">
<pre><span class="java&#45;keyword">public</span>&#160;<span class="java&#45;keyword">interface</span> ExchangeRateAware &#123;&#10;    <span class="java&#45;keyword">public</span> void setExchangeRateService(ExchangeRateService exchangeRateService);&#10;&#125;</pre>
</div></div><p class="paragraph">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.</p><h2 class="heading2"><a name="Xwork%27sComponentArchitecture-Writing%26quot%3BEnableraware%26quot%3BActions"> Writing &quot;Enabler-aware&quot; Actions</a></h2><p class="paragraph">All an action needs to do is implement the relevant enabler interface. XWork will then call the action&#039;s enabler method just prior to the action&#039;s execution. As a simple example:</p><div class="code"><div class="codeContent">
<pre><span class="java&#45;keyword">public</span> class MyAction <span class="java&#45;keyword">extends</span> ActionSupport <span class="java&#45;keyword">implements</span> ExchangeRateAware &#123;&#10;    ExchangeRateService ers;&#10;    &#10;    <span class="java&#45;keyword">public</span> void setExchangeRateService(ExchangeRateService exchangeRateService) &#123;&#10;        ers = exchangeRateService;&#10;    &#125;&#10;    &#10;    <span class="java&#45;keyword">public</span>&#160;<span class="java&#45;object">String</span> execute() <span class="java&#45;keyword">throws</span> Exception &#123;&#10;        <span class="java&#45;object">System</span>.out.println(<span class="java&#45;quote">&quot;The base currency is &quot;</span> &#43; ers.getBaseCurrency());&#10;    &#125;&#10;&#125;</pre>
</div></div><p class="paragraph">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);</p><h2 class="heading2"><a name="Xwork%27sComponentArchitecture-Usinganexternalreferenceresolver"> Using an external reference resolver</a></h2><p class="paragraph">You 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 <a href="http://www.springframework.org" title="Visit page outside Confluence">Spring Framework</a></p>You just need to write an external reference resolver and then tell XWork to use it in the package declaration:
<div class="code"><div class="codeContent">
<pre><span class="xml&#45;tag">&lt;package&#10;    name=<span class="xml&#45;quote">&quot;default&quot;</span>&#10;    externalReferenceResolver=<span class="xml&#45;quote">&quot;com.atlassian.xwork.ext.SpringServletContextReferenceResolver&quot;</span>&gt;</span></pre>
</div></div><br/>
Now, to use external references you do something like this:
<div class="code"><div class="codeContent">
<pre><span class="xml&#45;tag">&lt;external&#45;ref name=<span class="xml&#45;quote">&quot;foo&quot;</span>&gt;</span>Foo<span class="xml&#45;tag">&lt;/external&#45;ref&gt;</span></pre>
</div></div><br/>
Where the name attribute is the setter method name and Foo is the reference to lookup.<p class="paragraph">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 <a href="http://jira.opensymphony.com/secure/ViewIssue.jspa?key=XW-122" title="Visit page outside Confluence">XW-122</a></p>-Chris

				    
                    			    </td>
		    </tr>
	    </table>
	    <table border="0" cellpadding="0" cellspacing="0" width="100%">
			<tr>
				<td height="12" background="border/border_bottom.gif"><img src="border/spacer.gif" width="1" height="1" border="0"/></td>
			</tr>
		    <tr>
			    <td align="center"><font color="grey">Document generated by Confluence on Oct 18, 2004 00:08</font></td>
		    </tr>
	    </table>
    </body>
</html>