Announcement Announcement Module
Collapse
No announcement yet.
Auto Flush not working for Spring 3.1 LocalEntityManagerFactoryBean+Hibernate 4+JTA Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Auto Flush not working for Spring 3.1 LocalEntityManagerFactoryBean+Hibernate 4+JTA

    (I am asking the same question at StackOverflow too:
    http://stackoverflow.com/questions/1...bean-hibernate )


    I have did a lot of search on the web and pages like this and this and this mostly suggested for using CMTTransactionFactory. However I am still unable to make it work (I wonder if it is because I am creating a EM using a LocalContainerEntityManagerFactoryBean instead of creating Hibernate session by LocalSessionFactoryBean)

    Here is what I have in my app ctx
    Code:
    <jee:jndi-lookup  id="dataSource" jndi-name="jdbc/fooDs" />
    
    <bean id="transactionManager"
        class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
    
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
            </bean>
        </property>
        <property name="persistenceUnitName" value="foo" />
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.foo" />
        <!--
          <property name="persistenceXmlLocation" value="classpath:/META-INF/test-persistence.xml" />
         -->
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
                <!--
                  <entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
                  <entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
                 -->
                <entry key="hibernate.transaction.factory_class" value="org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory"/>
                <entry key="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform"/>
                <entry key="hibernate.transaction.flush_before_completion"  value = "true" />
            </map>
        </property>
    </bean>
    (In jpaPropertyMap, I tried to have the two remarked entries and still the same)

    I am making use of Spring Data JPA and after the entity is retrieved, I updated the content. If I am not flushing the repository (which means session/entityManager) manually, it simply discard my changes.

    Can anyone give me some hints on what I have missed in the setting? Is there anything special to notice for using LocalContainerEntityManagerFactoryBean?

    I am using Spring 3.1.2.RELEASE, Hibernate 4.1.6.Final, Websphere 8
    Last edited by adrianshum; Oct 15th, 2012, 10:11 PM. Reason: add missing links

  • #2
    In the snippet you post there is nothing to drive your transaction... There is only a transaction manager (the what) but no where (tx:annotation-driven or some other transaction demarcation).

    Also as you are using the jta.platform property either don't configure the factory_class or make it JtaTransactionFactory...

    Comment


    • #3
      I only extract out suspicious snippet to avoid having a huge xml that no one is going to read I am using annotation-driven tx. It seems working fine if I am manually flushing the entity manager (by Spring Data JPA's JpaRepository#flush() )

      Lemme have a try for factory_class change.

      Just to clarify a bit, originally I have only
      <entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtended JTATransactionLookup" />
      <entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFac tory"/>
      in the property, and it is not working. However, is it supposed to be fine?

      Thanks

      Originally posted by Marten Deinum View Post
      In the snippet you post there is nothing to drive your transaction... There is only a transaction manager (the what) but no where (tx:annotation-driven or some other transaction demarcation).

      Also as you are using the jta.platform property either don't configure the factory_class or make it JtaTransactionFactory...

      Comment


      • #4
        Well the transaction stuff is basically deprecated in 4.x and you should have enough at only declaring a jta.platform...

        Comment


        • #5
          I am wrong on what I have told:
          Only certain combinations of properties in jpaPropertyMap give me "no-auto-flushing" behavior. Other combination simply tell me there is no transaction in progress when I flush.

          Here is the combinations I have tried in jpaPropertyMap:

          Code:
          hibernate.transaction.manager_lookup_class    org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
          no transaction is in progress




          Code:
          hibernate.transaction.manager_lookup_class    org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
          hibernate.transaction.factory_class           org.hibernate.transaction.CMTTransactionFactory
          transaction active, manual flush works, auto-flush not working




          Code:
          hibernate.transaction.manager_lookup_class    org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
          hibernate.transaction.factory_class           org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory
          transaction active, manual flush works, auto-flush not working




          Code:
          hibernate.transaction.manager_lookup_class    org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
          hibernate.transaction.factory_class           org.hibernate.transaction.JTATransactionFactory
          no transaction is in progress




          Code:
          hibernate.transaction.manager_lookup_class    org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
          hibernate.transaction.factory_class           org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory
          no transaction is in progress





          Code:
          hibernate.transaction.jta.platform            org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform
          no transaction is in progress





          Code:
          hibernate.transaction.jta.platform            org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform
          hibernate.transaction.factory_class           org.hibernate.transaction.CMTTransactionFactory
          no transaction is in progress





          Code:
          hibernate.transaction.jta.platform            org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform
          hibernate.transaction.factory_class           org.hibernate.transaction.JTATransactionFactory
          no transaction is in progress





          In short, no matter I am using jta.platform or manager_lookup_class, JPA/Hibernate seems only be able to pick up the transaction when I am using CMTTransactionFactory. However, auto-flush is still not working.


          My app service look like this:

          Code:
          @Transactional(propagation=Propagation.REQUIRES_NEW)
          public class FooServiceImpl implements FooService {
            @Inject
            private FooRepository fooRepo;
          
            public void doSomething() {
              Foo foo = fooRepo.findBySomething(...);
              foo.setBar(...);
              //fooRepo.flush();
            }
          }
          (the line fooRepo.flush() is the place I modify to try manual flushing and auto flushing)

          Repository is making use of Spring Data JPA


          I really have no clues on what else I can try

          Using Spring 3.1.2, Hibernate 4.1.6, Websphere 8

          Comment


          • #6
            We use the exact same combination without problems and we only have a JtaPlatform configured... (The other properties are deprecated). However we don't use Spring Data but plain repositories.

            The no-transaction indicates to me that your @transactional isn't working, can you post a stacktrace in the case of a non-active transaction.

            Comment


            • #7
              I have also suspected that my @Transactional is not setup correctly. However when I am using the combination with CMTTransactionFactory as factory_class (i.e. cases with transaction active, but no auto flushing), I intentionally throw an exception and it is rolled back correctly. That seems suggests to me Transaction is correctly setup. Anyway, here you go (something masked in the stacktrace)

              Code:
              com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception root cause spring-rest: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
              	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
              	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
              [.... some deleted]
              	at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
              	at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1659)
              Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
              	at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:321)
              	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:106)
              	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
              	at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
              	at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
              	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:91)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
              	at $Proxy857.flush(Unknown Source)
              	at com.foo.orderservice.app.ccy.impl.CurrencyServiceImpl.activateCurrency(CurrencyServiceImpl.java:79)
              	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
              	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
              	at java.lang.reflect.Method.invoke(Method.java:611)
              	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
              	at org.springframework.transaction.interceptor.TransactionInterceptor$1.doInTransaction(TransactionInterceptor.java:132)
              	at org.springframework.transaction.jta.WebSphereUowTransactionManager$UOWActionAdapter.run(WebSphereUowTransactionManager.java:337)
              	at com.ibm.ws.uow.EmbeddableUOWManagerImpl.runUnderNewUOW(EmbeddableUOWManagerImpl.java:786)
              	at com.ibm.ws.uow.EmbeddableUOWManagerImpl.runUnderUOW(EmbeddableUOWManagerImpl.java:365)
              	at org.springframework.transaction.jta.WebSphereUowTransactionManager.execute(WebSphereUowTransactionManager.java:281)
              	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:127)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
              	at $Proxy861.activateCurrency(Unknown Source)
              	at com.foo.orderservice.controller.impl.CurrencyControllerImpl.activateCurrency(CurrencyControllerImpl.java:76)
              	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
              	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
              	at java.lang.reflect.Method.invoke(Method.java:611)
              	at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
              	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
              	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
              	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
              	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
              	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
              	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
              	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
              	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
              	... 34 more
              Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
              	at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:983)
              [... some deleted ...]
              	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
              	at $Proxy856.flush(Unknown Source)
              	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.flush(SimpleJpaRepository.java:388)
              	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
              	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
              	at java.lang.reflect.Method.invoke(Method.java:611)
              	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334)
              	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.transaction.interceptor.TransactionInterceptor$1.doInTransaction(TransactionInterceptor.java:132)
              	at org.springframework.transaction.jta.WebSphereUowTransactionManager$UOWActionAdapter.run(WebSphereUowTransactionManager.java:337)
              	at com.ibm.ws.uow.EmbeddableUOWManagerImpl.runUnderCurrentUOW(EmbeddableUOWManagerImpl.java:971)
              	at com.ibm.ws.uow.EmbeddableUOWManagerImpl.runUnderUOW(EmbeddableUOWManagerImpl.java:369)
              	at org.springframework.transaction.jta.WebSphereUowTransactionManager.execute(WebSphereUowTransactionManager.java:281)
              	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:127)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
              	... 72 more

              Comment


              • #8
                Hmm not what I hoped to see ...

                There is a transaction interceptor and that is also working with the TransactionManager. I hoped to see no transaction-interceptor.

                Strange thing is we use the same setup (without spring-data) without any problems. All of our configuration is in persistence.xml

                Spring Configuration
                Code:
                <tx:jta-transaction-manager />
                <tx:annotation-driven proxy-target-class="true" />
                
                <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
                    <property name="persistenceUnitName" value="foobar" />
                </bean>
                That is all we have, everything else is in the persistence.xml (see below) and it works like a charm.

                Code:
                <persistence version="2.0"
                	xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
                	<persistence-unit name="foobar" transaction-type="JTA">
                 		<provider>org.hibernate.ejb.HibernatePersistence</provider>
                		<jta-data-source>jdbc/ourdatasource</jta-data-source>
                		<properties>
                 			<property name="hibernate.dialect" value="org.hibernate.dialect.DB2400Dialect" />
                			<property name="hibernate.transaction.jta.platform" value="our.custom.JtaPlatformImplementation." />
                			<property name="hibernate.current_session_context_class" value="jta"/>
                			<property name="hibernate.transaction.flush_before_completion" value="true"/>
                			<property name="hibernate.connection.release_mode" value="auto"/>
                		</properties>
                 	</persistence-unit>	
                </persistence>
                This is all we have and it works...

                Note: Our custom JtaPlatform is nothing more then a wrapper which detects on which server we run and selects the JtaPlatform to use (we have different servers on dev machines and in prod and we didn't want to change the persistence.xml files).

                Comment


                • #9
                  Just a little update: I tried to inject EntityManager to my service by @PersistenceContext, and use JPA directly instead of going through Spring Data JPA. Same things happens: Unless I flush the entity manager explicitly, Hibernate is not picking up my updated entity to issue update statement. At least we know the problem has nothing to do with Spring Data

                  The biggest difference I can see is I am doing all settings directly at LocalContainerEntityManager, while you are using persistence.xml. Can it be the cause? Lemme try to use persistence.xml tomorrow and have a look

                  By the way, what is the container you are using? I wonder if it is a possible cause of problem too
                  Last edited by adrianshum; Oct 16th, 2012, 06:35 AM.

                  Comment


                  • #10
                    What do you mean by container in this case? As mentioned before we use the exact same setup without Spring Data and everything is configured in persistence.xml... Everything else is the same (WAS8, Spring 3.1 etc.)

                    Comment


                    • #11
                      Hello adrianshum

                      1) Check the API for org.springframework.transaction.jta.WebSphereUowTr ansactionManager

                      Perhaps it require some special property to be used, since the error message is related with no transaction is in progress

                      2) Where you are making the relation between the Transaction and JPA?
                      They are declared but seems isolated between them.

                      Comment


                      • #12
                        @Marten: May I know if you are declaring all your mapped class in persistence.xml explicitly? One of the reason for me not to use persistence.xml is the newly added packageToScan feature in LocalContainerEntityManager which save me trouble in the maintenance of persistence.xml (I used to write a maven plugin for that)

                        And, in your deployment, do you simply package all those hibernate dependencies with the WAR? Or do you need to setup Websphere by putting some JARs Websphere? Are you using the default parent-first classloading strategy? (In my old day using older version of Weblogic, I need to do some pre-setup by putting hibernate related JARs under Weblogics, though I don't think it is necessary as things mostly works this time)

                        @dr_pompeii:
                        1) Have had a brief look on it, seems there is nothing special that I can set. Just to clarify, transaction is working if I am using CMTTransactionFactory (only auto-flushing is not working)

                        2) Well, I mostly follow this setting by following misc reference on the web. Though I am not really sure, but I believe it is how it work:

                        - Transaction Manager is in fact managed by container
                        - those <tx:jta-transaction-manager /> or WebSphereUowTransactionManager is in fact looking up it from container
                        - Hibernate is looking up the transaction manager from container by providing hibernate.transaction.manager_lookup_class (org.hibernate.transaction.WebSphereExtendedJTATra nsactionLookup) and hibernate.transaction.factory_class (org.hibernate.engine.transaction.internal.jta.CMT TransactionFactory) (and probably jta.platform too). All these make Hibernate lookup the same transaction manager (and hence, create its corresponding Session) as which Spring is using for transaction management.
                        Last edited by adrianshum; Oct 16th, 2012, 09:53 PM.

                        Comment


                        • #13
                          A "Good" news: Using persistence.xml, as what @Marten suggested, is working.

                          It seems that even I am having almost identical properties set directly on LocalContainerEntityManager vs in persistence.xml, it works fine only in persistence.xml

                          It seems obvious to me that is a bug of Spring 3.1. I am going to raise a bug to Spring for that after I done some more cleanup and testing on that.

                          Will adopt the persistence.xml way for the time being as workaround

                          Comment


                          • #14
                            First off all glad it worked . To anser your questions.

                            Originally posted by adrianshum
                            May I know if you are declaring all your mapped class in persistence.xml explicitly? One of the reason for me not to use persistence.xml is the newly added packageToScan feature in LocalContainerEntityManager which save me trouble in the maintenance of persistence.xml (I used to write a maven plugin for that)
                            What I posted is all we have and use so no explicit classes in persistence.xml nor packagesToScan. JPA is perfectly capably of detecting @Entity classes in the same archive as where the persistence.xml is declared.

                            Originally posted by adrianshum
                            And, in your deployment, do you simply package all those hibernate dependencies with the WAR? Or do you need to setup Websphere by putting some JARs Websphere? Are you using the default parent-first classloading strategy? (In my old day using older version of Weblogic, I need to do some pre-setup by putting hibernate related JARs under Weblogics, though I don't think it is necessary as things mostly works this time)
                            We use parent-last/application-first (IBM changes the names frequently ) classloading and everything is packed inside the war. Mainly because we want to use hibernate and we package our own JSF implementation. This requires some classloading trickery.

                            Comment


                            • #15
                              After some further trial-and-error, here is the actual problem:

                              1) I can move almost all settings from persistence.xml to Spring's config, leaving only the <persistence-unit name="foo" transaction-type"="JTA"> line in persistence.xml. It works fine.
                              2) I need to have transaction-type = "JTA" in persistence.xml. Having "RESOURCE_LOCAL" is giving the same error of "no transaction in progress". (Though it works in my previous projects with Spring 2.5 + Hibernate 3 + WebLogic)


                              (A wild guess) It seems to be that for the xml-less LocalContainerEntityManagerFactoryBean bootstrapping method, it is making the native entity manager intialized as it is having a persistence.xml with transaction-type as "LOCAL_RESOURCES" (though we haven't declare it anywhere), which caused the problem (at least for the combination of framework/system I am using this time).

                              As a workaround, I have to leave persistence.xml in my JAR. However, by doing that it left packagesToScan useless (I believe it cannot co-exists with persistence.xml). It will still be fine for me in this moment (but I will need to find some way later to make multiple JARs-with-entities possible)
                              Last edited by adrianshum; Oct 17th, 2012, 06:15 AM.

                              Comment

                              Working...
                              X