Adding Custom Resource Factories
This topic has not yet been written. The content below is from the topic description.
Adding Custom Resource Factories If none of the standard resource factories meet your needs, you can write your own factory and integrate it into JBoss Web, and then configure the use of this factory in the conf/server.xml configuration file. In the example below, we will create a factory that only knows how to create com.mycompany.MyBean beans, from the Generic 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, the getObjectInstance() method is called, with the following arguments: Object obj - The (possibly null) object containing location or reference information that can be used in creating an object. For JBoss Web, 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 conf/server.xml) 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 JBoss Web 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 element that configures this factory (see below). 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. For more information about ObjectFactory, see the JNDI 1.2 Service Provider Interface (SPI) Specification. 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. 2. 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 element, like this: Object factory for MyBean instances. bean/MyBeanFactory com.mycompany.MyBean WARNING - Be sure you respect the element ordering that is required by the DTD for web application deployment descriptors! See the Servlet Specification for details. 3. 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()); 4. Configure JBoss Web's Resource Factory To configure JBoss Web's resource factory, add an elements like this to the $CATALINA_HOME/conf/server.xml file, nested inside the Context element for this web application. ... ... 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.