Search code examples
javahibernatewebspherewebsphere-8

javax.naming.Reference incompatible with org.hibernate.SessionFactory


I am using hibernate-core-4.2.21.Final on Websphere 8.5.5.4.

The Hibernate configuration is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory name="mySessionFactory">

    <property name="hibernate.hbm2ddl.auto">update</property>
    <property name="hibernate.show_sql">false</property>
    <property name="hibernate.format_sql">true</property>
    <property name="hibernate.connection.datasource">MyDS</property>
    <property name="hibernate.default_schema">dbo</property>
    <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
    <property name="hibernate.connection.autocommit">false</property>
    <property name="hibernate.jndi.class">com.ibm.websphere.naming.WsnInitialContextFactory</property>


    <property name="hibernate.jndi.url">corbaloc::myapp-prod-fnicn1.my.com:2809,:myapp-prod-FNICN2.my.com:2809,:myapp-prod-fnicn1.my.com:2811,:myapp-prod-FNICN2.my.com:2811,:myapp-prod-fnicn1.my.com:2812,:myapp-prod-FNICN2.my.com:2812</property> 

    <property name="hibernate.transaction.auto_close_session">true</property>
    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
    <property name="hibernate.transaction.flush_before_completion">true</property>

    <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property>

    <property name="hibernate.current_session_context_class">jta</property>
    <property name="jta.UserTransaction">java:comp/UserTransaction</property>

  <mapping resource="gov/mci/efada/entities/User.hbm.xml"/>

 </session-factory>
</hibernate-configuration>

How I configure Hibernate:

Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                .buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);

How I get the session factory:

sessionFactory = (SessionFactory) new InitialContext().lookup("mySessionFactory");

Sometimes, the lookup for SessionFactory throws :

javax.naming.Reference incompatible with org.hibernate.SessionFactory

Solution

  • I solved the issue by making a singleton class as follows :

    public class EntityHome {
    
        protected static final Log log = LogFactory.getLog(EntityHome.class);
        protected SessionFactory sessionFactory;
        private static ServiceRegistry serviceRegistry;
        private static EntityHome entityHome;
    
        public static EntityHome getInstance() {
            if (entityHome == null) {
                try {
                    entityHome = new EntityHome();
                } catch (Exception e) {
                    AppLogger.log("########### unable to configure hibernate,exception is: " + e.getMessage());
                    entityHome = null;
                }
            }
            return entityHome;
        }
    
        private EntityHome() throws Exception {
            try {
                configureHibernate();
            } catch (Exception e) {
                throw e;
            }
        }
    
        private void configureHibernate() throws HibernateException {
    
            Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                    .buildServiceRegistry();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        }
    
        public SessionFactory getSessionFactory() throws NamingException {
            if (sessionFactory == null || sessionFactory.isClosed()) {
                configureHibernate();
            }
            return sessionFactory;
        }
    
        public UserTransaction getTransaction() {
    
            UserTransaction transaction = null;
    
            try {
                Object o = new InitialContext().lookup("java:comp/UserTransaction");
                transaction = (UserTransaction) o;
                return transaction;
            } catch (Exception e) {
                throw new IllegalStateException("Could not locate java:comp/UserTransaction in JNDI");
            }
        }
    
        public static <T> List<T> fromSetToList(Set<T> set) {
            List<T> list = new ArrayList<T>();
            for (T o : set) {
                list.add(o);
            }
            return list;
        }
    }
    

    And in each DAO class I call the singleton class as follows :

    public class CarCategoryHome {
    
            private final SessionFactory sessionFactory = getSessionFactory();
    
            protected SessionFactory getSessionFactory() {
                try {
                    return EntityHome.getInstance().getSessionFactory();
                } catch (NamingException e) {
                    AppLogger.Log(e);
                    return null;
                }
            }
    
            public CarCategory findById(Integer id) {
                try {
                    CarCategory instance = (CarCategory) sessionFactory.getCurrentSession()
                            .get("com.myapp.data.CarCategory", id);
                    return instance;
                } catch (RuntimeException re) {
                    throw re;
                }
            }
    
        }