| <?xml version="1.0"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Fulcrum YAAFI Avalon Container Tutorial Step 3</title> |
| <author email="siegfried.goeschl@it20one.at">Siegfried Goeschl</author> |
| </properties> |
| |
| <body> |
| |
| <section name="Implementing an Avalon Service"> |
| |
| <subsection name="Defining an Interface and an Implementation Class"> |
| <p> |
| The evry first step is to define an interface and a corresponding implementation |
| class. |
| <ul> |
| <li>org.apache.fulcrum.yaafi.service.systemproperty.SystemPropertyService as interface</li> |
| <li>org.apache.fulcrum.yaafi.service.systemproperty.SystemPropertyServiceImpl as implementation class</li> |
| </ul> |
| </p> |
| </subsection> |
| |
| <subsection name="Writing the interface"> |
| <p> |
| The interface exposes only business methods and never ever one of the various Avalon |
| interfaces. |
| <source><![CDATA[ |
| public interface SystemPropertyService |
| { |
| // This interface doesn't exposes any other methods |
| } |
| ]]></source> |
| </p> |
| </subsection> |
| |
| <subsection name="Chasing the Interfaces to Implement"> |
| <p> |
| The Avalon Service Container interacts with an Avalon service |
| through a bunch of interfaces also known as |
| <a href="../lifecycle/index.html">Avalon Lifecycle |
| Management Specification</a>. 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. |
| <source><![CDATA[ |
| public class SystemPropertyServiceImpl |
| extends AbstractLogEnabled |
| implements SystemPropertyService, Reconfigurable, Contextualizable, Initializable |
| { |
| // here comes the implementation ... |
| } |
| ]]></source> |
| </p> |
| <p> |
| 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 |
| <ul> |
| <li>public void configure(Configuration configuration)</li> |
| <li>public void reconfigure(Configuration configuration)</li> |
| </ul> |
| </p> |
| <p> |
| The information about the application context is provided by |
| the "Contextualizable" interface while the service initialization |
| needs the "Initializable" interface. |
| </p> |
| </subsection> |
| |
| <subsection name="Accessing the Avalon Context"> |
| <p> |
| The <a href="../specification/context.html">Avalon Context </a>contains |
| environment settings such as the current working directory, the |
| temporary directory or the name of the service. |
| <source><![CDATA[ |
| public void contextualize(Context context) throws ContextException |
| { |
| this.tempDir = (File) context.get("urn:avalon:temp"); |
| } |
| ]]></source> |
| </p> |
| </subsection> |
| |
| <subsection name="Accessing the Component Configuration"> |
| <p> |
| In the Role Configuration file we defined "SystemPropertyService" as shorthand for accessing |
| the Component Configuration. The Component Configuration we use is shown below |
| <source><![CDATA[ |
| <SystemPropertyService> |
| <property name="FOO">BAR</property> |
| </SystemPropertyService> |
| ]]></source> |
| </p> |
| <p> |
| 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". |
| <source><![CDATA[ |
| 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 ); |
| } |
| } |
| ]]></source> |
| </p> |
| </subsection> |
| |
| <subsection name="Service Initialization "> |
| <p> |
| Since we have done most of our work already we use the |
| service initialization to dump the current system properties |
| into the temporary directory. |
| <source><![CDATA[ |
| 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(); |
| } |
| ]]></source> |
| </p> |
| </subsection> |
| |
| <subsection name="Implementing the Reconfiguration"> |
| <p> |
| 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. |
| <source><![CDATA[ |
| public void reconfigure(Configuration configuration) throws ConfigurationException |
| { |
| this.configure(configuration); |
| } |
| ]]></source> |
| </p> |
| </subsection> |
| |
| <subsection name="Putting it all together"> |
| <p> |
| Below you find your first complete and fully functional Avalon service. |
| <source><![CDATA[ |
| 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); |
| } |
| } |
| ]]></source> |
| </p> |
| </subsection> |
| |
| </section> |
| |
| </body> |
| |
| </document> |