The contents of this document are a work in progress

Configuring a Plexus Component via descriptor

We change the Component Role interface to look like this:

public interface WebsiteMonitor
{

    /**
     * Role used to register component implementations with the container.
     */
    String ROLE = WebsiteMonitor.class.getName();

    /**
     * Monitor the specified website at the specified time intervals.
     * 
     * @throws Exception
     *             error encountered while performing the monitoring request.
     */
    public void monitor()
        throws Exception;

    /**
     * Specify a list of websites that can be monitored by this component.
     * 
     * @param websites List of websites
     */
    void addWebsites( List websites );

    /**
     * Determines if the website monitor component was properly initialized.
     *  
     * @return <code>true</code> if initiailized, else <code>false</code>.
     */
    boolean isInitialized();
}

and, factor our component provider implementation to look like this:

public class DefaultWebsiteMonitor
    extends AbstractLogEnabled
    implements WebsiteMonitor
{

    /**
     * Websites to monitor.
     * 
     * @plexus.configuration
     */
    private List websites;

    /**
     * @see org.codehaus.plexus.tutorial.WebsiteMonitor#monitor(java.lang.String)
     */
    public void monitor()
        throws Exception
    {
        HttpClient client = new HttpClient();

        for ( Iterator it = websites.iterator(); it.hasNext(); )
        {
            String website = (String) it.next();
            HttpMethod getMethod = new GetMethod( website );
            getMethod.setFollowRedirects( false );

            try
            {
                int statusCode = client.executeMethod( getMethod );

                if ( statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES )
                {
                    if ( getLogger().isErrorEnabled() )
                        getLogger().error(
                                           "HTTP request returned HTTP status code: " + statusCode + " for website: "
                                               + website );
                    throw new Exception( "HTTP request returned HTTP status code: " + statusCode + " for website: "
                        + website );
                }
                if ( getLogger().isInfoEnabled() )
                    getLogger().info(
                                      "HTTP request returned HTTP status code: " + statusCode + " for website: "
                                          + website );
            }
            catch ( UnknownHostException e )
            {
                if ( getLogger().isErrorEnabled() )
                    getLogger().error( "Specified host '" + website + "' could not be resolved." );
                throw e;
            }
            finally
            {
                if ( null != getMethod )
                    getMethod.releaseConnection();
            }
        }
    }

    public void addWebsites( List websites )
    {
        this.websites = websites;
    }

    public boolean isInitialized()
    {
        return ( null != websites && this.websites.size() > 0 );
    }

}

Note how 'websites' is now a java.util.List property rather than a argument to the method. Also notice the annotation @plexus.configuration that indicates that this property is a plexus configuration element. This annotation is processed by Plexus' Component Descriptor Creator (or CDC). The CDC can parse and generate a components.xml from Java sources.

Now that we made 'websites' to be a configuration property, we need to update the component's descriptor and specify values for websites. We add a list of websites as shown the the snippet below. Plexus container ensures that a component's fields are mapped and initialized and mapped from a component's configuration file. It can intelligently discover and map configuration items of different types like String, Lists (in this case). You can also specify you own configuration implementation class by specifying an 'implementation' attribute on <configuration> element. Plexus will then attempt to inject the values from the XML configuration into the Configuration implementation's properties. Each of the nested element maps to a configuration property in the implementation class.

This mandates a change in the descriptor, which now looks something like this:

<component-set>
  <components>
    <component>
      <role>org.codehaus.plexus.tutorial.WebsiteMonitor</role>
      <implementation>
        org.codehaus.plexus.tutorial.DefaultWebsiteMonitor
      </implementation>
      <configuration>
        <websites>
          <website>http://www.google.co.nz/</website>
          <website>http://www.nonexistent.yadayada3249834739547.org/</website>
          <website>http://maven.apache.org/</website>
        </websites>
      </configuration>
    </component>
  </components>
</component-set>