Fortress' Roles file syntax reference
In this section is described the Fortress' <code>.roles</code> file syntax.
The root node
<!ELEMENT root (role*)>
The root node does not have any requirements. A good convention is to use the name of your application container and possibly a configuration differenciator name appended to it if you will manage several configuration (which is often the case).
Example: <code>fooApp-light.roles</code>
<fooApp-light>
{{{ <!-- ... --> </fooApp-light>
- }}}
The root node MUST contain <code>role</code> nodes.
The <code>role</code> node
{{{ <!ELEMENT role (component+)>
<!ATTLIST role name ID #REQUIRED> }}}
The <code>role</code> node MUST have a <code>name</code> string attribute. Its value is the role name that will be use to retrieve the components that implements this role. Generally, we do use the long name of the role interface as the role name. However this is not mandatory (just a good convention) and role names may be choosen arbitrarily.
There must be at least one component implementation specified inside a <code>role</code> element.
To continue the previous example, let's imagine there is a MyService component interface in my foo application:
<fooApp-light>
{{{ <!-- ... -->
<role name="com.example.foo.MyService">
<!-- Implementation components specification -->
</role>
<!-- ... --> </fooApp-light>
- }}}
The <code>component</code> node
{{{ <!ELEMENT component EMPTY>
<!ATTLIST component shorthand ID #REQUIRED
- class CDATA #REQUIRED
handler CDATA "org.apache.avalon.fortress.impl.handler.PerThreadComponentHandler"> }}}
- class CDATA #REQUIRED
The <code>component</code> node MUST have <code>shorthand</code> and <code>class</code> string attributes. The <code>handler</code> attribute is optionnal.
The <code>shorthand</code> attribute declares a short name for the component implementation. This name will be used to refer to this component in the configuration file in order to specify the component configuration.
<code>class</code>, of course, specifies the implementation class of the component.
Finally, the <code>handler</code> attribute specifies the lifestyle the container must ensure for the component. It is, in fact, the name of the ComponentHandler class Fortress supplies for this lifestyle. See the next section for the different lifestyle that Fortress provides.
Let's continue our example and imagine we got MyServiceImpl, a thread-safe component implementation of the MyService role interface:
<fooApp-light>
{{{ <!-- ... -->
<role name="com.example.foo.MyService">
<component shorthand="myService"
class="com.example.foo.impl.MyServiceImpl"
handler="org.apache.avalon.fortress.impl.handler.ThreadSafeComponentHandler"/>
<!-- Some other MyService implementations... -->
</role>
<!-- ... --> </fooApp-light>
- }}}
The <code>handler</code> attribute possible values
The value set in the <code>handler</code> attribute of the <code>component</code> element corresponds to the class names of the different lifestyle that Fortress provides. Here is the actual list of lifestyle and their description. You should find more informations about those in the Developing w. Avalon guide.
<code>org.apache.avalon.fortress.impl.handler.PerThreadComponentHandler</code> (default) The container returns a different instance for each thread.
<code>org.apache.avalon.fortress.impl.handler.ThreadSafeComponentHandler</code> The container returns a single instance for all thread. Note that only the initialization of the component is synchronized.
<code>org.apache.avalon.fortress.impl.handler.PoolableComponentHandler</code> The container returns instances on demand and gets those instances from a pool. Note that there is a special <code>pool-min</code> attribute to specify the minimum number of instances the pool must contain (default value is 10).
<code>org.apache.avalon.fortress.impl.handler.FactoryComponentHandler</code> The container returns a new instance at every lookup.
Relationship between role definitions and components' lookups code
The relationship between role definitions in the <code>.roles</code> file and the lookup code you must use in the component implementations are very simple.
Let's first define a <code>ROLE</code> constant in the service role interface. (This is good practice!)
public interface MyService
{
{{{ public final static String ROLE = MyService.class.getName();
// ... }
- }}}
Here are the rules:
If there is a single implementation of the MyService role defined in the roles file, then <code>serviceManager.lookup(MyService.ROLE)</code> will return an instance of the actual component
If there are multiple implementations of the MyService role defined in the roles file, then <code>serviceManager.lookup(MyService.ROLE)</code> will return an instance of the first defined component (Note that you can change that behaviour by saying in the configuration file what implementation is the default) <code>serviceManager.lookup(MyService.ROLE+"/shorthand")</code> will return an instance of the component defined with the <code>shorthand</code> shorthand <code>serviceManager.lookup(MyService.ROLE+"Selector")</code> will return a ServiceSelector instance for this role
Finally, you should always remember when you write components that you rarely know the assembler's choices about your components' lifestyle. So you should always release the components you did acquire.