Parent Component Manager
When using Apache Cocoon it is sometimes neccessary to obtain
components from other sources than the user.roles file,
or preferable to have a common component manager for several web applications.
The pattern chosen for Cocoon is the dynamic loading of a component manager class.
The initialization parameter parent-component-manager in web.xml specifies a class
that will be loaded, instantiated and used as a parent component manager for
Cocoon's component manager.
The recommended procedure is for the class, when it is initialized, to create a
delegate in the form of an ExcaliburComponentManager , configure it
by looking up a Configuration object via JNDI, and delegate any requests to it.
In order to provide a way to pass parameters to the parent component manager class
(the class specified in parent-component-manager), Cocoon will instantiate the class
via the constructor that takes a single String argument, passing
anything to the right of the first '/' in the parameter value to the
constructor. Subsequently Cocoon examines whether the class implements
org.apache.avalon.framework.logger.Loggable and/or
org.apache.avalon.framework.activity.Initializable and calls
setLogger and/or initialize , as appropriate.
The instance is then used as a parent component manager.
Since that didn't make much sense in itself, let's look at the sample.
The goal is to define a component that can give us the time of day and
let it be managed by a parent component manager.
So, first we need to put a Configuration object into JNDI, and then
grab that object, use it to configure an ExcaliburComponentManager,
and pass on any requests to that manager.
Step 1: Creating a configuration object
We'll do this the quick and dirty way. The static initializer of a class
will create a Configuration instance with a single role and bind it
to org/apache/cocoon/samples/parentcm/ParentCMConfigration .
The following code was taken from org/apache/cocoon/samples/parentcm/Configurator.java
| | |
|
public class Configurator {
static {
try {
//
// Create a new role.
//
DefaultConfiguration config = new DefaultConfiguration("roles", "");
DefaultConfiguration timeComponent = new DefaultConfiguration("role", "roles");
timeComponent.addAttribute("name", Time.ROLE);
timeComponent.addAttribute("default-class", TimeComponent.class.getName());
timeComponent.addAttribute("shorthand", "samples-parentcm-time");
config.addChild(timeComponent);
//
// Bind it - get an initial context.
//
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
MemoryInitialContextFactory.class.getName());
initialContext = new InitialContext(environment);
//
// Create subcontexts and bind the configuration.
//
Context ctx = initialContext.createSubcontext("org");
ctx = ctx.createSubcontext("apache");
ctx = ctx.createSubcontext("cocoon");
ctx = ctx.createSubcontext("samples");
ctx = ctx.createSubcontext("parentcm");
ctx.rebind("ParentCMConfiguration", config);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
| |
| | |
To make sure the static initializer runs we make Cocoon force-load the class
by making a change to the web.xml file:
| | |
|
<init-param>
<param-name>load-class</param-name>
<param-value>
<!-- For IBM WebSphere:
com.ibm.servlet.classloader.Handler -->
<!-- For Database Driver: -->
org.hsqldb.jdbcDriver
<!-- For parent ComponentManager sample:
This will cause the static initializer to run,
and thus the Configuration object to be created
and bound. -->
org.apache.cocoon.samples.parentcm.Configurator
</param-value>
</init-param>
| |
| | |
Step 2: Write the component manager
Now that the configuration object is sitting there waiting for us, let's craft
the component manager. Please see the file org/apache/cocoon/samples/parentcm/ParentComponentManager.java
for an example. It is too much to paste in here.
Step 3: Tell Cocoon to use the component manager
Change the web.xml file to:
| | |
|
<init-param>
<param-name>parent-component-manager</param-name>
<param-value>org.apache.cocoon.samples.parentcm.ParentComponentManager/(remove this line break)
org/apache/cocoon/samples/parentcm/ParentCMConfiguration</param-value>
</init-param>
| |
| | |
Cocoon will now do the following: First, it will split the parameter value at the first slash,
in this case ending up with the strings "org.apache.cocoon.samples.parentcm.ParentComponentManager"
and "org/apache/cocoon/samples/parentcm/ParentCMConfiguration" . The first string is the
class to instantiate. The second is the parameter that will be passed to the constructor.
Next, Cocoon loads the component manager class and uses reflection to find a constructor that
will accept a single String argument. Upon finding one, it instantiates the
class in a manner similar to:
| | |
|
ComponentManager cm = new
org.apache.cocoon.samples.parentcm.ParentComponentManager(
"org/apache/cocoon/samples/parentcm/ParentCMConfiguration");
| |
| | |
After this Cocoon checks whether the parent component manager class implements Initializable and/or
Loggable . Since the ParentComponentManager class implements both, Cocoon
does the following (with simplification):
| | |
|
((Loggable) cm).setLogger(logger);
((Initializable) cm).initialize();
| |
| | |
Finally, the instance is used as parent component manager of Cocoon's own component manager.
Step 4: Use the component
Cocoon components can now use the ComponentManager given to them by Cocoon to look up the
component managed by the parent component manager:
The following code was taken from org/apache/cocoon/samples/parentcm/Generator.java
| | |
|
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
throws ProcessingException, SAXException, IOException {
Time timeGiver = null;
try {
timeGiver = (Time) manager.lookup(Time.ROLE);
this.time = timeGiver.getTime ();
} catch (ComponentException ce) {
throw new ProcessingException ("Could not obtain current time.", ce);
} finally {
manager.release(timeGiver);
}
}
| |
| | |
And that concludes the tour. A parent component manager was initialized with a configuration
obtained via JNDI and its components used by a Cocoon generator.
|