Adding Custom Resource Factories

If none of the standard resource factories meet your needs, you can write your own factory and integrate it into Tomcat, and then configure the use of this factory in the <Context> element for the web application. In the example below, we will create a factory that only knows how to create com.mycompany.MyBean beans from theGeneric JavaBean Resources example above.

  1. Write A Resource Factory Class

You must write a class that implements the JNDI service provider javax.naming.spi.ObjectFactory inteface. Every time your web application calls lookup() on a context entry that is bound to this factory (assuming that the factory is configured with singleton=”false”), the getObjectInstance() method is called, with the following arguments:

  • Communication across the network is cheap and fast.

Object obj – The (possibly null) object containing location or reference information that can be used in creating an object. For Tomcat, this will always be an object of type javax.naming.Reference, which contains the class name of this factory class, as well as the configuration properties (from the <Context> for the web application) to use in creating objects to be returned.

Name name – The name to which this factory is bound relative to nameCtx, or null if no name is specified.

Context nameCtx – The context relative to which the name parameter is specified, or null if name is relative to the default initial context.

Hashtable environment – The (possibly null) environment that is used in creating this object. This is generally ignored in Tomcat object factories.

 

To create a resource factory that knows how to produce MyBean instances, you might create a class like this:

package com.mycompany;

import java.util.Enumeration;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.Name;

import javax.naming.NamingException;

import javax.naming.RefAddr;

import javax.naming.Reference;

import javax.naming.spi.ObjectFactory;

 

public class MyBeanFactory implements ObjectFactory {

 

public Object getObjectInstance(Object obj,

Name name, Context nameCtx, Hashtable environment)

throws NamingException {

 

// Acquire an instance of our specified bean class

MyBean bean = new MyBean();

 

// Customize the bean properties from our attributes

Reference ref = (Reference) obj;

Enumeration addrs = ref.getAll();

while (addrs.hasMoreElements()) {

RefAddr addr = (RefAddr) addrs.nextElement();

String name = addr.getType();

String value = (String) addr.getContent();

if (name.equals(“foo”)) {

bean.setFoo(value);

} else if (name.equals(“bar”)) {

try {

bean.setBar(Integer.parseInt(value));

} catch (NumberFormatException e) {

throw new NamingException(“Invalid ‘bar’ value ” + value);

}

}

}

 

// Return the customized instance

return (bean);

 

}

}

In this example, we are unconditionally creating a new instance of the com.mycompany.MyBean class, and populating its properties based on the parameters included in the <ResourceParams> element that configures this factory. You should note that any parameter named factory should be skipped – that parameter is used to specify the name of the factory class itself (in this case, com.mycompany.MyBeanFactory) rather than a property of the bean being configured.

You will need to compile this class against a class path that includes all of the JAR files in the$CATALINA_HOME/lib directory. When you are through, place the factory class (and the corresponding bean class) unpacked under $CATALINA_HOME/lib, or in a JAR file inside $CATALINA_HOME/lib. In this way, the required class files are visible to both Catalina internal resources and your web application.

  1. Declare Your Resource Requirements

Next, modify your web application deployment descriptor (/WEB-INF/web.xml) to declare the JNDI name under which you will request new instances of this bean. The simplest approach is to use a <resource-env-ref>element, like this:

 

<resource-env-ref>

<description>

Object factory for MyBean instances.

</description>

<resource-env-ref-name>

bean/MyBeanFactory

</resource-env-ref-name>

<resource-env-ref-type>

com.mycompany.MyBean

</resource-env-ref-type>

<resource-env-ref>

 

Be sure you respect the element ordering that is required by the DTD for web application deployment descriptors!

  1. Code Your Application’s Use Of This Resource

A typical use of this resource environment reference might look like this:

 

Context initCtx = new InitialContext();

Context envCtx = (Context) initCtx.lookup(“java:comp/env”);

MyBean bean = (MyBean) envCtx.lookup(“bean/MyBeanFactory”);

 

writer.println(“foo = ” + bean.getFoo() + “, bar = ” +

bean.getBar());

  1. Configure Tomcat’s Resource Factory

To configure Tomcat’s resource factory, add an elements like this to the <Context> element for this web application.

 

<Context …>

<Resource name=”bean/MyBeanFactory” auth=”Container”

type=”com.mycompany.MyBean”

factory=”com.mycompany.MyBeanFactory”

singleton=”false”

bar=”23″/>

</Context>

Note that the resource name (here, bean/MyBeanFactory must match the value specified in the web application deployment descriptor. We are also initializing the value of the bar property, which will cause setBar(23) to be called before the new bean is returned. Because we are not initializing the foo property (although we could have), the bean will contain whatever default value is set up by its constructor.

You will also note that, from the application developer’s perspective, the declaration of the resource environment reference, and the programming used to request new instances, is identical to the approach used for the Generic JavaBean Resources example. This illustrates one of the advantages of using JNDI resources to encapsulate functionality – you can change the underlying implementation without necessarily having to modify applications using the resources, as long as you maintain compatible APIs.

Share this post
[social_warfare]
Tomcat Standard Resource Factories
JNDI Datasource

Get industry recognized certification – Contact us

keyboard_arrow_up