Set up a simple container using Fortress

You need a container for your application. This container will host the components you developed for your application.

To set up a simple container, you'll do the following tasks:

We will finally discuss how to implement a custom container class, as you may also sometimes want to.


Make the configuration

A container configuration typically contains three kinds of declarations:

Those declarations are specified in two different files. The Avalon configuration files are all XML files (we often refer to them as the xfiles) :

where <code><foo></code> is the name of your application or the name of one of its possible configuration.

Additionaly you must specify the logging mechanisms used by your application. This is the prupose of the <code><foo>.xlog</code> file.

The roles file

Let us see how to specify a single component :

<foo>
{{{    <role name="com.example.foo.MyComponent"> 
        <component shorthand="myComponent" class="com.example.foo.impl.MyComponentImpl" 
            handler="org.apache.avalon.fortress.impl.handler.ThreadSafeComponentHandler"/> 
    </role> 

</foo>

In the above, we do tell the container the following:

Note that the root element name (here <code>foo</code>) is arbitrarily choosen.

For more informations, you should refer to the [Fortress/RolesFileSyntax|<code>.roles</code> file syntax reference].

The configuration file

For each of your components, you must specify a configuration node in a XML element that

<foo>
{{{    <myComponent id="myComponent" logger="bar"> 
        <!-- ... here you place the configuration for the myComponent component --> 
    </myComponent> 

</foo>

Note that this component configuration is the simplest form you may use. For more informations about configuring your components, you should refer to the [Fortress/XConfFileSyntax|<code>.xconf</code> file syntax reference].

The logger definition file

Here is a simple logger definition file. Note that this file follows the syntax of the LogKit component configuration.

<logkit>
{{{    <factories> 
        <factory type="file" class="org.apache.avalon.excalibur.logger.factory.FileTargetFactory"/> 
    </factories> 

    <targets> 
        <file id="root"> 
            <filename>../../logs/pudding.log</filename> 
            <format type="extended"> 
                %7.7{priority} %23.23{time:yyyy-MM-dd HH:mm:ss:SSS}   [%{category}]: %{message}\n%{throwable} 
            </format> 
        </file> 
    </targets> 

    <categories> 
        <category name='''''' log-level="DEBUG"> 
            <log-target id-ref="root"/> 
        </category> 
    </categories> 

</logkit>

This files simply defines

Refer to the LogKit component configuration for more informations.


Implement the main routine

In the main routine, you will

For instance the following snippet defines a class that uses a ContainerManager to create a Container. It is meant to be used by a non-avalonized piece of code, for example a main program or a servlet.

public class MyBootstrap
{
{{{    private ContainerManager m_containerManager; 
     
    public ContainerManager createContainerManager(String base) throws Exception 
    { 
        // Create the fortress context configuration object 
        FortressConfig config = new FortressConfig(); 
        config.setContextDirectory( "./" ); 
        config.setWorkDirectory( "./" ); 
         
        // Specifies the configuration files location 
        config.setContainerConfiguration( base + "/myContainer.xconf" ); 
        config.setLoggerManagerConfiguration( base + "/myContainer.xlog" ); 
        config.setRoleManagerConfiguration( base + "/myContainer.roles" ); 
         
        m_containerManager = new DefaultContainerManager( config.getContext() ); 
        ContainerUtil.initialize( m_containerManager ); 
         
        return m_containerManager; 
    } 
     
    public void disposeContainerManager() 
    { 
        ContainerUtil.dispose( m_containerManager ); 
    } 
     
    public DefaultContainer getContainer() 
    { 
        return (DefaultContainer) m_containerManager.getContainer(); 
    } 

}

Note that we do only provide, for now, a context and a working directory along with the location of the configuration files to the ContainerManager.

Possible informations to be supplied to the FortressConfig object are:

You may adjust this configuration according your needs, see also AvalonFortressFAQ/ExtendingTheFortressConfiguration as example for a servlet environment.


Implement a custom container class

Let us see how to implement a custom container class. While this is not mandatory, this is sometime usefull... (DISCUSSION??)

The simplest container class you can do is a subclass of the Fortress DefaultContainer class.

public class MyContainer extends DefaultContainer
{
}

For which, you have added the following line to the bootstrap code:

config.setContainerClass(MyContainer.class);

Then you can add you own component methods in order to make the container a facade for the components it contains.

public class MyContainer extends DefaultContainer
{
{{{    public Object myMethod1(Object argument) throws MyException 
    { 
        try 
        { 
            MyComponent myComponent = 
                (MyComponent) getServiceManager().lookup( MyComponent.ROLE ); 
            return myComponent.doMyMethod1(argument); 
        } 
        catch (ServiceException se) 
        { 
            throw new MyException("Can't do this", se); 
        } 
        finally 
        { 
            getServiceManager().release( myComponent ); 
        } 
    } 
     
    // Additional such methods... 

}

You might notice that this class has nothing really specific to the fact it is a container (except its superclass). Instead, from a user point of view, we do consider that it is a component. Once you understood this, you could [Fortress/WriteSimpleContainerContainer|write a container of containers].

Fortress/SetUpSimpleContainer (last edited 2009-09-20 23:31:25 by localhost)