Hi, I recently worked on getting a JDBC connection pool/DataSource working on Tomcat 4.0b7. I was interested in trying out the OracleConnectionCacheImpl which Oracle provides in their JDBC drivers. I eventually found out that the only way to make an instance of this class available from JNDI was to create my own Factory class for it. It seemed to me like there should be a simpler way to do something like this so I created a factory class (BeanFactory) which can instantiate any class which conforms to the JavaBeans spec (i.e. most classes...). What would I have to do to contribute this class so it ships as a standard part of Tomcat? The class has worked out well for my purposes but I am not sure if the ClassLoader portion of the code is doing the right thing, I copied it from one of the other factory classes in org.apache.naming.factory. Using this class, I am able to make the Oracle DataSource implementation available to all my servlets using the following xml fragment in server.xml <DefaultContext> <Resource name="jdbc/myDataSource" auth="SERVLET" type="oracle.jdbc.pool.OracleConnectionCacheImpl"/> <ResourceParams name="jdbc/myDataSource"> <parameter> <name>factory</name> <value>org.apache.naming.factory.BeanFactory</value> </parameter> <parameter><name>driverType</name><value>thin</value></parameter> <parameter><name>serverName</name><value>hue</value></parameter> <parameter><name>networkProtocol</name><value>tcp</value></parameter> <parameter><name>databaseName</name><value>XXXX</value></parameter> <parameter><name>portNumber</name><value>NNNN</value></parameter> <parameter><name>user</name><value>XXXX</value></parameter> <parameter><name>password</name><value>XXXX</value></parameter> <parameter><name>maxLimit</name><value>5</value></parameter> </ResourceParams> </DefaultContext> Similarly, you could make ANY JavaBean available from jndi using this factory. I have attached my implementation to this message if anybody is interested in getting it incorporated into Tomcat. Thanks, - Aner
package org.apache.naming.factory; import java.util.Hashtable; import java.util.Enumeration; import javax.naming.Name; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.RefAddr; import javax.naming.spi.ObjectFactory; import org.apache.naming.ResourceRef; import java.beans.Introspector; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; /** * Object factory for any Object conforming to the JavaBean spec. */ public class BeanFactory implements ObjectFactory { // ----------------------------------------------------------- Constructors // -------------------------------------------------------------- Constants // ----------------------------------------------------- Instance Variables // --------------------------------------------------------- Public Methods // -------------------------------------------------- ObjectFactory Methods /** * Create a new Bean instance. * * @param obj The reference object describing the Bean */ public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws NamingException { System.out.println("BeanFactory.getObjectInstance()"); if (obj instanceof ResourceRef) { try { Reference ref = (Reference) obj; String beanClassName = ref.getClassName(); Class beanClass = null; ClassLoader tcl = Thread.currentThread().getContextClassLoader(); if (tcl != null) { try { beanClass = tcl.loadClass(beanClassName); } catch(ClassNotFoundException e) { } } else { try { beanClass = Class.forName(beanClassName); } catch(ClassNotFoundException e) { e.printStackTrace(); } } if(beanClass == null) throw new NamingException("Class not found: " + beanClassName); BeanInfo bi = Introspector.getBeanInfo(beanClass); PropertyDescriptor[] pda = bi.getPropertyDescriptors(); Object bean = beanClass.newInstance(); Enumeration e = ref.getAll(); while(e.hasMoreElements()) { RefAddr ra = (RefAddr) e.nextElement(); String propName = ra.getType(); if(propName.equals(Constants.FACTORY) || propName.equals("scope") || propName.equals("auth")) continue; String value = (String)ra.getContent(); Object[] valueArray = new Object[1]; int i = 0; for(i=0;i<pda.length;i++) { if(pda[i].getName().equals(propName)) { Class propType = pda[i].getPropertyType(); if(propType.equals(String.class)) valueArray[0] = value; else if(propType.equals(Character.class) || propType.equals(char.class)) valueArray[0] = new Character(value.charAt(0)); else if(propType.equals(Byte.class) || propType.equals(byte.class)) valueArray[0] = new Byte(value); else if(propType.equals(Short.class) || propType.equals(short.class)) valueArray[0] = new Short(value); else if(propType.equals(Integer.class) || propType.equals(int.class)) valueArray[0] = new Integer(value); else if(propType.equals(Long.class) || propType.equals(long.class)) valueArray[0] = new Long(value); else if(propType.equals(Float.class) || propType.equals(float.class)) valueArray[0] = new Float(value); else if(propType.equals(Double.class) || propType.equals(double.class)) valueArray[0] = new Double(value); else throw new NamingException( "String conversion for property type '"+ propType.getName() + "' not available"); Method setProp = pda[i].getWriteMethod(); if(setProp != null) setProp.invoke(bean, valueArray); else throw new NamingException( "Write not allowed for property: "+propName); break; } } if(i==pda.length) throw new NamingException("No set method found for property: "+propName); } return bean; } catch (java.beans.IntrospectionException ie) { throw new NamingException(ie.getMessage()); } catch (java.lang.IllegalAccessException iae) { throw new NamingException(iae.getMessage()); } catch (java.lang.InstantiationException ie2) { throw new NamingException(ie2.getMessage()); } catch (java.lang.reflect.InvocationTargetException ite) { throw new NamingException(ite.getMessage()); } } else { return null; } } }