Fork me on GitHub

Implementing an Avalon Service

Defining an Interface and an Implementation Class

The evry first step is to define an interface and a corresponding implementation class.

  • org.apache.fulcrum.yaafi.service.systemproperty.SystemPropertyService as interface
  • org.apache.fulcrum.yaafi.service.systemproperty.SystemPropertyServiceImpl as implementation class

Writing the interface

The interface exposes only business methods and never ever one of the various Avalon interfaces.

public interface SystemPropertyService
{
    // This interface doesn't exposes any other methods
}
          

Chasing the Interfaces to Implement

The Avalon Service Container interacts with an Avalon service through a bunch of interfaces also known as Avalon Lifecycle Management Specification. Finding the right interface might be challenge in the beginning but it is not an unsurmountable task. Our service needs access to the logging infrastructure, to the component configuration and needs to tell the Avalon Service Container that it is reconfigurable. To make things more interesting we want to dump the updated system properties into the temp directory of the application during service initialization.

public class SystemPropertyServiceImpl
    extends AbstractLogEnabled
    implements SystemPropertyService, Reconfigurable, Contextualizable, Initializable
{
    // here comes the implementation ...
}
          

Our service derives from "AbstractLogEnabled" which takes care of getting access to the logger. The implementation class also implements the "Reconfigurable" interface which tells the Avalon Service Container that the service implements

  • public void configure(Configuration configuration)
  • public void reconfigure(Configuration configuration)

The information about the application context is provided by the "Contextualizable" interface while the service initialization needs the "Initializable" interface.

Accessing the Avalon Context

The Avalon Context contains environment settings such as the current working directory, the temporary directory or the name of the service.

public void contextualize(Context context) throws ContextException
{
    this.tempDir = (File) context.get("urn:avalon:temp");
}
            

Accessing the Component Configuration

In the Role Configuration file we defined "SystemPropertyService" as shorthand for accessing the Component Configuration. The Component Configuration we use is shown below

<SystemPropertyService>
    <property name="FOO">BAR</property>
</SystemPropertyService>
            

Let's access the configuration to set the system properties - we get all childrem from the configuration instance and process them. Each child consists of an attribute containing the name and text for the value of the system property to be set. We also write some diagnostic ouptut by requesting the logger instance from "AbstractLogEnabled".

public void configure(Configuration configuration) throws ConfigurationException
{
    Configuration[] systemProperties = configuration.getChildren("property");

    for( int i=0; i<systemProperties.length; i++ )
    {
        String key = systemProperties[i].getAttribute("name");
        String value = systemProperties[i].getValue();
        this.getLogger().debug( "Setting the value of " + key + " to " + value );
        System.setProperty( key, value );
    }
}
            

Service Initialization

Since we have done most of our work already we use the service initialization to dump the current system properties into the temporary directory.

public void initialize() throws Exception
{
    FileOutputStream fos = new FileOutputStream( new File(this.tempDir,"system.properties") );
    System.getProperties().store( fos, "system.properties" );
    fos.flush();
    fos.close();
}
            

Implementing the Reconfiguration

Making our service reconfigurable is simple. When the service is reconfigured a new configuration instance is passed. We just reuse the configure() method to reinitalize our service - that's it.

public void reconfigure(Configuration configuration) throws ConfigurationException
{
    this.configure(configuration);
}
          

Putting it all together

Below you find your first complete and fully functional Avalon service.

public interface SystemPropertyService
{
    // This interface doesn't exposes any other methods
}

public class SystemPropertyServiceImpl
    extends AbstractLogEnabled
    implements SystemPropertyService, Reconfigurable, Contextualizable, Initializable
{
    /** the Avalon temp directory */
    private File tempDir;

    /**
     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
     */
    public void contextualize(Context context) throws ContextException
    {
        this.tempDir = (File) context.get("urn:avalon:temp");
    }

    /**
     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
     */
    public void configure(Configuration configuration) throws ConfigurationException
    {
        Configuration[] systemProperties = configuration.getChildren("property");

        for( int i=0; i<systemProperties.length; i++ )
        {
            String key = systemProperties[i].getAttribute("name");
            String value = systemProperties[i].getValue();
            this.getLogger().debug( "Setting the value of " + key + " to " + value );
            System.setProperty( key, value );
        }
    }

    /**
     * @see org.apache.avalon.framework.activity.Initializable#initialize()
     */
    public void initialize() throws Exception
    {
        FileOutputStream fos = new FileOutputStream( new File(this.tempDir,"system.properties") );
        System.getProperties().store( fos, "system.properties" );
        fos.flush();
        fos.close();
    }

    /**
     * @see org.apache.avalon.framework.configuration.Reconfigurable#reconfigure(org.apache.avalon.framework.configuration.Configuration)
     */
    public void reconfigure(Configuration configuration)
        throws ConfigurationException
    {
        this.configure(configuration);
    }
}