Hi,

I saw a lot this message in the forum : "Don't specify a SessionFactory JNDI
name, Tomcat JNDI is read-only".

That's true only for Web applications. Tomcat can initialize JNDI names
thanks to server.xml with <GlobalNamingResources>, <Resource> and
<ResourceParams>, but to configure that, we have to use a class which
implements "javax.naming.ObjectFactory". There are none class in Hibernate
that implements it. That's why we can't configure Tomcat to get a
SessionFactory with JNDI.

I create this class and after many tests, I had good results to get a
SessionFactory and to create Sessions. After I have a problem to read data
and here I need your help. ;-(

look at this link :
http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-resources-howto.html#Ad
ding%20Custom%20Resource%20Factories

See the code for the factory :

import java.io.File;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Hashtable;
import java.util.Iterator;
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;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.SimpleLog;
import org.apache.commons.logging.LogConfigurationException;

/**
 * JndiSessionFactoryImpl to configure in an API Server to initialize
 * a SessionFactory in a JNDI context.
 *
 * Tomcat Configuration in server.xml :
 *
 * <!-- Global JNDI resources -->
 * <GlobalNamingResources>
 *  ...
 *   <Resource description="SessionFactory Resource"
 *            name="HibernateSessionFactory" auth="Container"
 *            type="net.sf.hibernate.SessionFactory"/>
 *   <ResourceParams name="HibernateSessionFactory">
 *              <parameter>
 *                      <name>factory</name>
 *                      <value>JndiSessionFactoryImpl</value>
 *              </parameter>
 *              <parameter>
 *                      <name>pathname</name>
 *                      <value>conf/hibernate.cfg.xml</value>
 *              </parameter>
 *   </ResourceParams>
 * </GlobalNamingResources>
 *
 * ...
 * <!-- Define the Tomcat Stand-Alone Service -->
 * <Service name="Tomcat-Standalone">
 * <!-- Define the top level container in our container hierarchy -->
 *   <Engine name="Standalone" defaultHost="localhost" debug="0">
 *     <Host name="localhost" debug="0" appBase="webapps"
 *           unpackWARs="true" autoDeploy="true">
 *       ...
 *       <Context path="/testjndi" docBase="/testjndi.war" debug="0"
 *                reloadable="true" crossContext="true" privileged="true"
useNaming="true">
 *         <Logger className="org.apache.catalina.logger.FileLogger"
 *                 prefix="localhost_jndi_log." suffix=".txt"
 *                 timestamp="true"/>
 *         <ResourceLink name="hibernate/SessionFactory"
 *                       global="HibernateSessionFactory"
 *                      type="net.sf.hibernate.SessionFactory"/>
 *       </Context>
 *     </Host>
 *   </Engine>
 * </Service>
 *
 */
public class JndiSessionFactoryImpl implements ObjectFactory
{
public static final String PATH_NAME = "pathname";

private static SessionFactory sf = null;

private static Log log = null;

static
{
        try
        {
                log = LogFactory.getLog (JndiSessionFactoryImpl.class);
        }       catch (LogConfigurationException e)
                {
                        System.err.println ("Cannot get a LogFactory instance!");
                        log = new SimpleLog ("log");
                }
}

        public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable environment)
                throws NamingException
        {
        RefAddr addr = ((Reference)obj).get (PATH_NAME);
        String content = null;

                log.info ("Initializes a Sessionfactory instance");

                if (addr != null)
                        content = (String)addr.getContent ();
                else
                        log.error ("parameter " + PATH_NAME + " not found");

                log.debug ("pathname : " + content);

                if (System.getProperty ("api.server.home") == null)
                        log.error ("property \"api.server.home\" not found please
initialize -Dapi.server.home with API server home.");

                // Initialize Hibernate configuration with hibernate.cfg.xml :
                log.info ("Read the hibernate.cfg.xml at : " +
                        System.getProperty("api.server.home") + File.separator + 
content);
                if (sf == null)
                {
                        try
                        {
                                File file = new File 
(System.getProperty("api.server.home")
                                                        + "/" + content);

                                sf = new Configuration ().configure 
(file).buildSessionFactory ();

                                log.info ("Sessionfactory successfully initialize !!");
                        }       catch (HibernateException e)
                                {
                                        log.fatal ("Cannot get a SessionFactory 
instance", e);
                                }
                }

                return sf;
        }
}



Tomcat Configuration :

- put alls hibernate librairies in tomcat/common/lib
- This class use a new property "api.server.home" which must contain the API
server home.
  ==> Thus add     -Dapi.server.home="%CATALINA_HOME%"      in the file
catalina.bat (or cataline.sh).

- put hibernate.cfg.xml in tomcat/conf.
- put all mappings and JAVA BEANs and the factory
"JndiSessionFactoryImpl.class" in tomcat/common/classes

- finally modify tomcat/conf/server.xml :

  <!-- Global JNDI resources -->
  <GlobalNamingResources>

        ...
        <Resource description="SessionFactory Resource"
            name="HibernateSessionFactory" auth="Container"
            type="net.sf.hibernate.SessionFactory"
     />
        <ResourceParams name="HibernateSessionFactory">
                <parameter>
                        <name>factory</name>
                        <value>JndiSessionFactoryImpl</value>
                </parameter>
                <parameter>
                        <name>pathname</name>
                        <value>conf/hibernate.cfg.xml</value>
                </parameter>
        </ResourceParams>
  </GlobalNamingResources>


  ...

        <Context path="/testjndi" docBase="/testjndi.war" debug="0"
                 reloadable="true" crossContext="true" privileged="true"
useNaming="true">
          <Logger className="org.apache.catalina.logger.FileLogger"
                     prefix="localhost_jndi_log." suffix=".txt"
                  timestamp="true"/>
          <ResourceLink name="hibernate/SessionFactory"
                    global="HibernateSessionFactory"
                    type="net.sf.hibernate.SessionFactory"/>
        </Context>


Note : I send to you a full example with the factory, my server.xml,
catalina.bat, and a servlet.


- First initialize Tomcat and run it : If the configuration is good, you
should have some informations when the factory initialize the SessionFactory
at startup.

- After that execute the servlet.



When I execute the servlet, I have this result in the browser :

> sf = [EMAIL PROTECTED]
> session : [EMAIL PROTECTED]

> Cannot read data

> net.sf.hibernate.MappingException: No persister for: bo.Reception at
net.sf.hibernate.impl.SessionFactoryImpl.getPersister(SessionFactoryImpl.jav
a:444) at
net.sf.hibernate.impl.SessionImpl.getPersister(SessionImpl.java:2249) at
net.sf.hibernate.impl.SessionImpl.doLoadByClass(SessionImpl.java:1739) at
net.sf.hibernate.impl.SessionImpl.load(SessionImpl.java:1674) at
TestJndi.doPost(TestJndi.java:63) at TestJndi.doGet(TestJndi.java:31) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Application
FilterChain.java:247) at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterCh
ain.java:193) at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.ja
va:260) at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643) at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.ja
va:191) at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643) at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at
org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180
) at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643) at
org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.
java:170) at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:641) at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172
) at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:641) at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java
:174) at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643) at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at
org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223) at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:432)
at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConne
ction(Http11Protocol.java:386) at
org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:534)
at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.jav
a:530) at java.lang.Thread.run(Thread.java:536)


Do you have any idees about this problem ?
Can you help me to resolve it ?

Best regards,

Attachment: Jndi Tomcat.zip
Description: Zip compressed data

Reply via email to