0
votes

I have searched all StackOverflow site and Google, and 99.9% of questions are about web application, but I've not found any solution for a Java standalone application (runs in Linux terminal "java -jar myApp.jar") for the classic exception "org.hibernate.LazyInitializationException: could not initialize proxy - no Session"

My project is using Spring 4.0.7 + Hibernate 4.3.6.Final + Log4J 1.2.17 + BoneCP 0.8.0

I have tried the following solutions:

  1. @Service and @Transactional annotation in Client class, and in the classes that Client class calls;
  2. @Service and @Transactional(propagation = Propagation.REQUIRED) annotation in Client class, and in the classes that Client class;
  3. Switched from @Service to @Component and retried items 1 and 2 above;
  4. Tried using TransactionTemplate and executing client.start() method inside the TransactionCallback.doInTransaction() method;
  5. I have tried removing @Service and @Transactional from Client class and removing from classes called by Client class.

I've tried all this and I am still getting org.hibernate.LazyInitializationException: could not initialize proxy - no Session

The comments in code is what I have tried too.

Important note: The project uses a Facade class, that contains all methods used by application.

Spring configuration is loaded by the following XML:


    <beans>
        <context:annotation-config />
        <context:component-scan base-package="com.mycompany" />
        <context:property-placeholder location="classpath:persistence.properties" />
        <tx:annotation-driven transaction-manager="transactionManager" />

        <!-- BoneCP -->
        <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
            <property name="driverClass" value="${jdbc.driverClassName}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
            <property name="idleConnectionTestPeriodInMinutes" value="60"/>
            <property name="idleMaxAgeInMinutes" value="240"/>
            <property name="maxConnectionsPerPartition" value="30"/>
            <property name="minConnectionsPerPartition" value="10"/>
            <property name="partitionCount" value="3"/>
            <property name="acquireIncrement" value="5"/>
            <property name="statementsCacheSize" value="100"/>
            <property name="releaseHelperThreads" value="3"/>
        </bean>

        <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan" value="com.mycompany.domain.entity" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.default_schema">${hibernate.default_schema}</prop>
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                    <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
                    <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                    <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
                    <!-- I have tried setting "current_session_context_class", but still getting "org.hibernate.LazyInitializationException: could not initialize proxy - no Session" -->
                    <!-- <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop> -->
                </props>
            </property>
       </bean>

       <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
          <property name="sessionFactory" ref="sessionFactory" />
          <property name="dataSource" ref="dataSource" />
       </bean>

        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"/>
        </bean>

       <bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

        <bean id="client" class="com.mycompany.console.Client" />
    </beans>

Project main class:



    package com.mycompany.console;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;

    @Service
    @Transactional(propagation = Propagation.REQUIRED)
    public class Client {
        private static final Logger logger = Logger.getLogger(Client.class);

        public static void main(String args[]) {
            ApplicationContext applicationContext = null;

            // Load Spring application context
            try {
                applicationContext = new ClassPathXmlApplicationContext("springHibernateConfig.xml");

                final Client client = applicationContext.getBean("client"); // Or applicationContext.getBean(Client.class)

    // Already tried using TransactionTemplate, but still getting "org.hibernate.LazyInitializationException: could not initialize proxy - no Session"
    //          TransactionTemplate transactionTemplate = (TransactionTemplate) applicationContext.getBean("transactionTemplate");
    //          transactionTemplate.execute(new TransactionCallback() {
    //              @Override
    //              public Object doInTransaction(TransactionStatus status) {
    //                  client.start(args);
    //                  return null;
    //              }
    //          });
                client.start(args);

            } catch (Exception e) {
                System.err.println("Error loading Spring application context: " + e.getMessage());
                e.printStackTrace();
                System.exit(1);
            }
        }

        private void start(String args[]) {
            // List, Save, Update, Delete entities
            // 
            // Calls Facade.instance().getUserById(1L), for example
            // 
            // [...]
        }
    }


Facade class (ABDomain):



    package com.mycompany.domain.facade;

    @Service
    @Transactional(propagation = Propagation.REQUIRED)
    public class ABDomain {

        public static ABDomain instance() {
            // SpringUtil implements ApplicationContextAware
            return SpringUtil.getApplicationContext().getBean(ABDomain.class);
        }

        public User getUserById(Long id) {
            /*
                UsuarioDao is an interface, and its 
                implementation UsuarioDaoImpl extends AbstractHibernateDao
            */
            return Registry.getUserDao().findById(id);
        }
    }


Registry class:



    package com.mycompany.domain.registry;

    @Component
    @Transactional
    public class Registry {

        private static ApplicationContext applicationContext;

        @Autowired(required = true)
        public Registry(ApplicationContext appContext) {
            applicationContext = appContext;
        }

        public static UserDao getUserDao() {
            return applicationContext.getBean(UserDao.class);
        }
    }


EDIT:

Adding stack trace for better understanding.

Note:

  • ABDomain is the application Facade (mentioned above).
  • Inbox is another class that is called by Client class
org.springframework.orm.hibernate4.HibernateSystemException: could not initialize proxy - no Session; nested exception is org.hibernate.LazyInitializationException: could 
not initialize proxy - no Session
        at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:216)
        at org.springframework.orm.hibernate4.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:57)
        at org.springframework.orm.hibernate4.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:44)
        at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
        at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
        at com.sun.proxy.$Proxy120.findLastPosition(Unknown Source)
        at com.mycompany.domain.facade.ABDomain.findLastPosition(ABDomain.java:832)
        at com.mycompany.domain.facade.ABDomain$$FastClassBySpringCGLIB$$f56e1d49.invoke()
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
        at com.mycompany.domain.facade.ABDomain$$EnhancerBySpringCGLIB$$4c071cee.findLastPosition()
        at com.mycompany.cpr.client.Inbox.updateLastPosition(Inbox.java:714)
        at com.mycompany.cpr.client.Inbox.processMessage(Inbox.java:604)
        at com.mycompany.cpr.client.Inbox$3.run(Inbox.java:934)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
        at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
        at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
        at com.mycompany.domain.entity.Vehicle_$$_jvst374_1e.getId(Vehicle_$$_jvst374_1e.java)
        at com.mycompany.domain.dao.impl.LastPositionDaoImpl.findLastPosition(LastPositionDaoImpl.java:34)
        at sun.reflect.GeneratedMethodAccessor1487.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)

EDIT 2:

Inbox is a class that is called by Client class (the main class). Inbox has no annotation, but I already tried @Service @Transactional or @Component @Transactional annotations. I'm looking for a solution like OpenSessionInViewFilter commonly used in web projects.

1
In which point do you get the hibernate exception? Please post the relevant code to replicate the problem in form of SSCCE and the related stacktrace.Luiggi Mendoza
@LuiggiMendoza I have edited the question and included the stack trace. The relevant code is in Client class. Inbox class has @Service and @Transactional(propagation = Propagation.REQUIRED) annotations. But it isn't working with and without those annotations.shimatai
Your stacktrace states that the exception arises in com.mycompany.cpr.client.Inbox.updateLastPosition methid which you haven't posted nor either how you call this method.Luiggi Mendoza
I get the Vehicle (it's an entity) in DaoImpl (that is annotated with @Repository), but I try to access a @ManyToOne field (for example vehicle.getOwner()) in another class (Inbox class, that has no annotation, but I already tried @Service @Transactional and @Component @Transactional annotations). The problem is when Spring + Hibernate creates a proxy and then I try to access @ManyToOne fields, I get that error org.hibernate.LazyInitializationException: could not initialize proxy - no Session. I'm looking for a solution like OpenSessionInViewFilter commonly used in web projects.shimatai
I'm against that kind of solution because it means that a database connection should be opened per request, and not all requests need to connect to database e.g. file download. Basically, the problem is caused by an entity that was obtained through a session and this entity was returned and is out of this session, then you try to access to a field loaded lazily but the session was closed. So, you have two choices: 1) use the same connection/session along all the application (which we cannot read from your given code), 2) use refresh method to synchronize the object to the level 1 cache.Luiggi Mendoza

1 Answers

0
votes

After analyzing your stack trace, I see the TransactionInterceptor is called, so the only possible explication is if you try to initiale an eneityt that was loaded in a diffreent Session than the current one:

So, this method you call: at com.mycompany.domain.dao.impl.LastPositionDaoImpl.findLastPosition(LastPositionDaoImpl.java:34)

Is the Vehicle entity loaded in a different Thread/Transaction/Session and then sent in a message that you intercept with:

at com.mycompany.cpr.client.Inbox.processMessage(Inbox.java:604)

If this is the case, you need to initialize all wanted associations in the Producer transaction (the one that fetches the Vehicle and the sends it).