Overview

The Factory Service instantiates objects from the given class name using either the given class loader or an applicable one found from the class loader repository. If neither one is specified, the default class loader will be used.

The service provides the following benefits compared to Class.forName():

  • support for parameters in constructors,
  • internal class loader repository, which can be specified in resources,
  • optional class specific factories, which can be used for customized instantiation, and
  • integration with the Pool Service supporting recycling of instances created by the service.

Configuration

Role Configuration

    <role
        name="org.apache.fulcrum.factory.FactoryService"
        shorthand="factory"
        default-class="org.apache.fulcrum.factory.DefaultFactoryService"/>
      

Component Configuration

Item Datatype Cardinality Description
classloader String [0..n] A class loader. Class loaders will be tried in sequence when trying to create an object instance.
object-factory Complex [0|1] The parent element for object factories. Sub-elements define factories for certain class names. You can define one default factory that will be used if no others match. See the configuration example below.

Component Configuration Example

    <factory>
        <classloader>java.net.URLClassLoader</classloader>
        <object-factory>
            <javax.xml.parsers.DocumentBuilder>
                org.foo.xml.DomBuilderFactory
            </javax.xml.parsers.DocumentBuilder>
            <default>
                org.some.default.Factory
            </default>
        </object-factory>
    </factory>
      

Usage

In Turbine, the Factory Service is currently only used internally by the Pool Service. Applications can also use the service instead of Class.forName() and for unifying initialization, configuration and access to vendor specific object factories. The following is a simplified example of a customized DOM parser factory:

package org.foo.xml;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.fulcrum.ServiceException;
import org.apache.fulcrum.factory.Factory;

/**
 * A factory for instantiating DOM parsers.
 */
public class DomBuilderFactory implements Factory
{
    /**
     * The implementation of the factory.
     */
    private DocumentBuilderFactory factory;

    /**
     * Initializes the factory.
     */
    public void init(String className)
        throws ServiceException
    {
        factory = DocumentBuilderFactory.newInstance();
    }

    /**
     * Gets a DocumentBuilder instance.
     */
    public Object getInstance()
        throws ServiceException
    {
        try
        {
            return factory.newDocumentBuilder();
        }
        catch (ParserConfigurationException x)
        {
            throw new TurbineException(x);
        }
    }

    /**
     * Gets a DocumentBuilder instance.
     * The given loader is ignored.
     */
    public Object getInstance(ClassLoader loader)
        throws ServiceException
    {
        return getInstance();
    }

    /**
     * Gets a DocumentBuilder instance.
     * Constructor parameters are ignored.
     */
    public Object getInstance(Object[] params,
                              String[] signature)
        throws ServiceException
    {
        return getInstance();
    }

    /**
     * Gets a DocumentBuilder instance.
     * The given loader and constructor parameters are ignored.
     */
    public Object getInstance(ClassLoader loader,
                              Object[] params,
                              String[] signature)
        throws ServiceException
    {
        return getInstance();
    }

    /**
     * Returns false as given class loaders are not supported.
     */
    public boolean isLoaderSupported()
    {
        return false;
    }
}

The customized DOM parser factory must be specified in the component configuration like in the configuration example above before it can be used.

A DOM parser can now be instantiated with the following code fragment:

// Access the service singleton.
FactoryService service = (FactoryService)container.lookup(FactoryService.ROLE);

// Create a new DOM parser.
DocumentBuilder parser =
    service.getInstance("javax.xml.parsers.DocumentBuilder");