java.lang.IllegalStateException: Could not locate SessionFactory in JNDI

后端 未结 2 1456
鱼传尺愫
鱼传尺愫 2021-01-29 00:15

Good evening, i get the above exception when using Hibernate with JSF, i saw it many times in the past and the root cause was that like this

相关标签:
2条回答
  • 2021-01-29 00:39

    Sorry to necro this, but I thought that since this wasn't marked as answered perhaps it would be OK. Others may have fallen victim to the same pitfall as I.

    I recently ran into similar problems after merging some HBM's. Subsequently, I had issues regarding JNDI and sessionFactory look-up failures due to duplicate class mappings in the HBM files causing the JNDI/SessionFactory service to be unable to start up..

    So, as a start - make sure you are not declaring duplicate classes in your mapping files :)

    This may or may not be what someone looking at this question needs, but it was my issue :)

    0 讨论(0)
  • 2021-01-29 00:45

    You could manually add the SessionFactory to the Context. Although it looks like a lot of code it is really only these 5 lines. The rest is just handeling the NamingException which InitialContext seems to love throwing.

    A better approach would be to use a ContextListener to automatically add the session during start up

    InitialContext initialContext = new InitialContext();
    SessionFactory sf = (SessionFactory)  initialContext.lookup("SessionFactory");
    Configuration cfg = new Configuration();
    cfg.configure();
    sf = cfg.buildSessionFactory();
    initialContext.bind("SessionFactory", sf);
    

    Here is the full Servlet goGet method

        protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        Account acc;
        InitialContext initialContext = null;
        acc = new Account("asdf" + String.valueOf(new Date().getTime()), "asdf");
        AccountHome home;
        Transaction tx = null;
        SessionFactory sf;
    
                // Create an instance of the InitialContext
                // So that we can lookup the SessionFactory property
                // or add it if it does not yet exist
        try {
    
            initialContext = new InitialContext();
    
        } catch (NamingException e) {
            throw new ServletException("Unable to create InitalContext", e);
        }
    
                // Since SessionFactories are very expensive to create 
                // first attempt to lookup a cached instance of the SessionFactory
        try {
            sf = (SessionFactory) initialContext.lookup("SessionFactory");
        } catch (NamingException e) {
                        // There is currently no session factory bound to this context
                        // Manually create it and bind it
            Configuration cfg;
            cfg = new Configuration();
            cfg.configure();
            sf = cfg.buildSessionFactory();
    
            try {
                initialContext.bind("SessionFactory", sf);
            } catch (NamingException e1) {
                throw new ServletException(
                        "Unable to bind the SessionFactory to the Inital Context");
            }
        }
    
                // Start the transaction and perform work
        tx = sf.getCurrentSession().beginTransaction();
        try {
            home = new AccountHome();
            home.persist(acc);
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            throw new ServletException("Work failed", e);
        }
    
    }
    

    EDIT: Added ContextListener

    package ch.yaawi.platform;
    
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class SessionFactoryListener implements ServletContextListener {
    
    private SessionFactory mSessionFactory;
    
    public void contextDestroyed(ServletContextEvent event) {
    
        if (mSessionFactory != null && !mSessionFactory.isClosed()) {
            mSessionFactory.close();
        }
    
    }
    
    public void contextInitialized(ServletContextEvent event) {
        InitialContext initialContext = null;
        try {
    
            initialContext = new InitialContext();
    
        } catch (NamingException e) {
            throw new RuntimeException("Unable to create InitalContext", e);
        }
    
        try {
            mSessionFactory = (SessionFactory) initialContext
                    .lookup("SessionFactory");
        } catch (NamingException e) {
            Configuration cfg;
            cfg = new Configuration();
            cfg.configure();
            mSessionFactory = cfg.buildSessionFactory();
    
            try {
                initialContext.bind("SessionFactory", mSessionFactory);
            } catch (NamingException e1) {
                throw new RuntimeException(
                        "Unable to bind the SessionFactory to the Inital Context");
            }
        }
    
    }
    
    }
    

    Then in your web.xml

    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
    <display-name>Archetype Created Web Application</display-name>
    
    <listener>
        <listener-class>ch.yaawi.platform.SessionFactoryListener</listener-class>
    </listener>
    
    </web-app>
    

    Of causing changing the namespace to your own.

    Hope this helps someone

    0 讨论(0)
提交回复
热议问题