10 Replies Latest reply on Aug 16, 2007 11:15 AM by youngm

    TransactionalSeamPhaseListener + Spring @Transactional

    dapeng

      Hi,

      can anyone explain me the effect, when I combine Seam TransactionalSeamPhaseListener with Spring @Transctional annotation in my service layer?

      regards
      dapeng

        • 1. Re: TransactionalSeamPhaseListener + Spring @Transactional
          youngm

           

          can anyone explain me the effect, when I combine Seam TransactionalSeamPhaseListener with Spring @Transctional annotation in my service layer?


          Well, first of all you need to make sure that they're configured to use the same JTA TransactionManager. With Seam 2.0.0 CR1 you will be able to configure Seam to use a Spring PlatformTransactionManager.

          So, assuming you have Spring and Seam set up to use the same JTA TM then the TransactionalSeamPhaseListener will manage transaction begin and commit semantics for a faces request. If you call a method annotated with spring's @Transactional then by default Spring will join that transaction since the default spring propagation rule is "REQUIRED". You could use the spring TM to gain more fine grained control over you transaction with with Spring's transaction suspension support and nested support.

          If the service method is called outside of a Faces Request (e.g. @Asynchronous call) then @Transactional would start a transaction since TransactionalSeamPhaseListener would not be available.

          So in the end if in a faces request using @Transactional will have no effect unless you're using Spring's transaction suspension or nested transactions. If not in a faces request then @Transactional can be used to start and commit transactions when interacting with your service layer.

          Does that answer your question?

          Mike

          • 2. Re: TransactionalSeamPhaseListener + Spring @Transactional
            dapeng

            Hi,

            thanks for your answer. It is the first answer I get for my posts in the seam forum. Maybe I have been asking odd questions. Some points are still not quite clear:
            1. I am not able to locate the class TransactionalSeamPhaseListener in Seam 2.0? Has it been replaced by the general SeamPhaseListener?
            2. Where can I download the 2.0.0. CR1? (you mean RC1?)
            3. I want to deploy my application in Tomcat, where no UserTransaction is available in JNDI? I encountered some problem in the class org.jboss.seam.transaction.Transaction, which always exists the method getUserTransaction with a runtime exception: I am forced to disable the seam tx management in components.xml with <core:init debug="true" transaction-management-enabled="false"/> to get rid of the problem. But I think I am then only relying on the spring tx management and might get LazyInitilizationException. Is my understanding right?

            <core:manager conversation-timeout="120000"
             concurrent-request-timeout="500"
             conversation-id-parameter="cid"/>
            
             <core:init debug="true" transaction-management-enabled="false"/>
            
             <spring:context-loader/>
            


            <bean id="transactionManager"
             class="org.springframework.orm.jpa.JpaTransactionManager">
             <property name="entityManagerFactory"
             ref="entityManagerFactory" />
             <property name="dataSource" ref="dataSource" />
             </bean>
            
             <!--
             <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
             <property name="persistenceUnitName" value="userDB"/>
             </bean>
             -->
            
             <bean id="entityManagerFactory"
             class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
             <property name="dataSource" ref="dataSource" />
             <property name="jpaVendorAdapter">
             <bean
             class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
             <property name="showSql" value="true" />
             <property name="generateDdl" value="false" />
             <property name="database" value="MYSQL" />
             </bean>
             </property>
            
             <property name="loadTimeWeaver">
             <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
             </property>
            
             </bean>
            
            
             <!-- Seam entity manager facrtory
             <bean id="entityManagerFactory"
             class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
             <property name="persistenceContextName" value="entityManager" />
             </bean>
             -->
            
             <tx:annotation-driven proxy-target-class="true" />
            
             <bean
             class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
            
             <bean
             class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
            
             <bean id="userDao"
             class="com.suzuki.asap.startup.dao.jpa.JpaUserDao" />
            
             <bean id="userService"
             class="com.suzuki.asap.startup.service.UserService">
             <property name="dao" ref="userDao"></property>
             <!-- seam:component/-->
             </bean>
            
             <bean id="dataSource"
             class="org.apache.commons.dbcp.BasicDataSource"
             destroy-method="close">
             <property name="driverClassName" value="com.mysql.jdbc.Driver" />
             <property name="url" value="jdbc:mysql://localhost:3308/asap" />
             <property name="username" value="root" />
             <property name="password" value="sa" />
             <property name="initialSize" value="2" />
             <property name="maxActive" value="50" />
             </bean>
            
             <seam:configure-scopes />
            </beans>



            Thank you for your help.


            • 3. Re: TransactionalSeamPhaseListener + Spring @Transactional
              youngm

               

              1. I am not able to locate the class TransactionalSeamPhaseListener in Seam 2.0? Has it been replaced by the general SeamPhaseListener?


              Ya, it was removed in 2.0 beta and was replaced by the "transaction-management-enabled" attribute

              2. Where can I download the 2.0.0. CR1? (you mean RC1?)

              Unfortunately it is not out yet. Feel free to checkout the latest from CVS and build your own snapshot though.

              3. I want to deploy my application in Tomcat, where no UserTransaction is available in JNDI? I encountered some problem in the class org.jboss.seam.transaction.Transaction, which always exists the method getUserTransaction with a runtime exception: I am forced to disable the seam tx management in components.xml with <core:init debug="true" transaction-management-enabled="false"/> to get rid of the problem. But I think I am then only relying on the spring tx management and might get LazyInitilizationException. Is my understanding right?

              So first of all in 2.0.0 CR1 you will be able to use a spring TM as a Seam TM and will be able to enable "transaction-management-enabled". For now though who is doing the transaction management has nothing to do with getting LazyInitializationExceptions. What "transaction-management-enabled" disabled will mean is that when you wish to flush() your conversation scoped PC it will be best to do it inside of a Service call with @Transactional.

              Otherwise your configuration looks fine otherwise. A couple of points:

              1. You don't need to inject a dataSource into your JpaTransactionManager. I'm not sure if it will mess things up or not but I know it is not necessary.

              2. Make sure your components.xml has your entityManager definition:

               <persistence:managed-persistence-context name="entityManager"
               auto-create="true"
              entity-manager-factory="#{entityManagerFactory}"/>


              And uncomment and rename your SeamManagedEntityManagerFactoryBean to something like:
               <bean id="seamEntityManagerFactory"
               class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
               <property name="persistenceContextName" value="entityManager" />
               </bean>


              And make sure that you use your seamEntityManagerFactory with your JpaTransactionManager like:
               <bean id="transactionManager"
               class="org.springframework.orm.jpa.JpaTransactionManager">
               <property name="entityManagerFactory"
               ref="seamEntityManagerFactory" />
               </bean>
              


              Otherwise read over more closely the Seam+Spring docs regarding Persistence contexts.

              Mike

              • 4. Re: TransactionalSeamPhaseListener + Spring @Transactional
                pmuir

                N.B. CVS snapshots (built) are available at http://hudson.jboss.org/hudson/job/JBossSeam/

                • 5. Re: TransactionalSeamPhaseListener + Spring @Transactional
                  dapeng

                  Hi,

                  thank you for your helpful answer. I plan to have a seam independent persistence and service layer using spring + JPA and only use seam in the web layer because of its powerful JSF enhancements.

                  Do I understand it right:
                  1. It is possible to use spring manged the local transaction instead of JTA, but I need the RC1 or the SNAPSHOT of Seam. It is not possible with the Beta1. It is important for me, because the application must run both on JBoss and Tomcat. I want to know whether it is necessary to install the embedded-jboss in Tomcat, so that I can use JTA.
                  2. Can I use JpaTransactionManager together with RESOURCE_LOCAL tx in persistence.xml. I managed to have a working version with embedded-jboss and JTA. I would like to see it also working with local tx.
                  3. Do I have to use seamEntityManagerFactory,or can I also use Spring LocalContainerEntityManagerFactoryBean? What is the main job of seamEntityManagerFactory?
                  4. The same question applies to persistence context. Does it need to be managed by seam or can it also be managed by Spring?


                  Thanx a lot.

                  • 6. Re: TransactionalSeamPhaseListener + Spring @Transactional
                    youngm

                     

                    Hi,

                    thank you for your helpful answer. I plan to have a seam independent persistence and service layer using spring + JPA and only use seam in the web layer because of its powerful JSF enhancements.

                    Do I understand it right:
                    1. It is possible to use spring manged the local transaction instead of JTA, but I need the RC1 or the SNAPSHOT of Seam. It is not possible with the Beta1. It is important for me, because the application must run both on JBoss and Tomcat. I want to know whether it is necessary to install the embedded-jboss in Tomcat, so that I can use JTA.

                    You only need RC1 or snapshot if you wish to use spring managed local transactions that are automatically created and committed by seam in a faces request. Of if you want to use Seam's @Transactional annotation.

                    2. Can I use JpaTransactionManager together with RESOURCE_LOCAL tx in persistence.xml. I managed to have a working version with embedded-jboss and JTA. I would like to see it also working with local tx.

                    Yes you can use JpaTransactionManager and do transaction management in spring and not have to use the embedded-jboss and jta.


                    3. Do I have to use seamEntityManagerFactory,or can I also use Spring LocalContainerEntityManagerFactoryBean? What is the main job of seamEntityManagerFactory?

                    If you configure it the way I described above you will be using the Spring LocalContainerEntityManagerFactoryBean. It will be configured such that spring provides the EntityManagerFactory. Seam provides it's conversation scoped EntityManager and then SeamManagedEntityManagerFactoryBean takes the Seam conversation scoped EntityManager and exposes it as another EntityManagerFactoryBean that can then be used by JpaTransactionManager to start and stop transactions and used by PersistenceAnnotationBeanPostProcessor to inject the Seam conversation scoped EntityManager into your spring beans. Which reminds me you will also need to update your PersistenceAnnotationBeanPostProcessor to:

                    <bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
                     <property name="defaultPersistenceUnitName" value="seamEntityManagerFactory"/>
                     </bean>
                    


                    So that Spring will know that @PersistenceContext should inject the seam entitymanager instance instead of creating a new spring managed one.

                    4. The same question applies to persistence context. Does it need to be managed by seam or can it also be managed by Spring?


                    Configured the way I told you the PersistenceContext will be managed by Seam. If you want to take advantage of Seam's Conversation scoped PersistenceContexts then that is the way it will need to be. This in no way limits your ability to execute code asynchronously or outside of a Seam request though. Take a look at the spring-seam example. In there I was actually executing a spring configured timer task on a bean that used a Seam managed persistenceContext.

                    There is nothing that says you cannot use a Spring managed Entitymanager it just means you won't be able to take advantage of a Conversation scoped EntityManager.

                    Is there a particular reason why you would want to use a Spring managed EntityManager?


                    • 7. Re: TransactionalSeamPhaseListener + Spring @Transactional
                      youngm

                      Sorry my quotes got alittle messed up. :)

                      Hi,

                      thank you for your helpful answer. I plan to have a seam independent persistence and service layer using spring + JPA and only use seam in the web layer because of its powerful JSF enhancements.

                      Do I understand it right:
                      1. It is possible to use spring manged the local transaction instead of JTA, but I need the RC1 or the SNAPSHOT of Seam. It is not possible with the Beta1. It is important for me, because the application must run both on JBoss and Tomcat. I want to know whether it is necessary to install the embedded-jboss in Tomcat, so that I can use JTA.

                      You only need RC1 or snapshot if you wish to use spring managed local transactions that are automatically created and committed by seam in a faces request. Of if you want to use Seam's @Transactional annotation.

                      2. Can I use JpaTransactionManager together with RESOURCE_LOCAL tx in persistence.xml. I managed to have a working version with embedded-jboss and JTA. I would like to see it also working with local tx.


                      Yes you can use JpaTransactionManager and do transaction management in spring and not have to use the embedded-jboss and jta.


                      3. Do I have to use seamEntityManagerFactory,or can I also use Spring LocalContainerEntityManagerFactoryBean? What is the main job of seamEntityManagerFactory?

                      If you configure it the way I described above you will be using the Spring LocalContainerEntityManagerFactoryBean. It will be configured such that spring provides the EntityManagerFactory. Seam provides it's conversation scoped EntityManager and then SeamManagedEntityManagerFactoryBean takes the Seam conversation scoped EntityManager and exposes it as another EntityManagerFactoryBean that can then be used by JpaTransactionManager to start and stop transactions and used by PersistenceAnnotationBeanPostProcessor to inject the Seam conversation scoped EntityManager into your spring beans. Which reminds me you will also need to update your PersistenceAnnotationBeanPostProcessor to:

                      <bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
                       <property name="defaultPersistenceUnitName" value="seamEntityManagerFactory"/>
                       </bean>
                      


                      So that Spring will know that @PersistenceContext should inject the seam entitymanager instance instead of creating a new spring managed one.

                      4. The same question applies to persistence context. Does it need to be managed by seam or can it also be managed by Spring?


                      Configured the way I told you the PersistenceContext will be managed by Seam. If you want to take advantage of Seam's Conversation scoped PersistenceContexts then that is the way it will need to be. This in no way limits your ability to execute code asynchronously or outside of a Seam request though. Take a look at the spring-seam example. In there I was actually executing a spring configured timer task on a bean that used a Seam managed persistenceContext.

                      There is nothing that says you cannot use a Spring managed Entitymanager it just means you won't be able to take advantage of a Conversation scoped EntityManager.

                      Is there a particular reason why you would want to use a Spring managed EntityManager?


                      • 8. Re: TransactionalSeamPhaseListener + Spring @Transactional
                        dapeng

                         

                        You only need RC1 or snapshot if you wish to use spring managed local transactions that are automatically created and committed by seam in a faces request. Of if you want to use Seam's @Transactional annotation.


                        Is there a configuration example for using spring managed local tx? By talking "automatically created and committed by seam in a faces request", do you mean the code started by the seam filter (listener)? Is it correct, that Seam will start 2 txs (using spring tx manager) for each jsf request and all methods marked with spring @Transactional will just take part in the tx silently?

                        Yes you can use JpaTransactionManager and do transaction management in spring and not have to use the embedded-jboss and jta.


                        In tomcat6 the method getUserTransaction always exists with a NamingException(can not create resource) , if I haven't installed the embedded-jboss. Only NameNotFoundException is caught, no general NamingException. It results in a endless redirect loop. With Beta1 I only manage to get a running version with JTA and embedded-jboss.


                        <bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
                         <property name="defaultPersistenceUnitName" value="seamEntityManagerFactory"/>
                         </bean>
                        


                        Are you sure the vlaue of defaultPersistenceUnitName should be seamEntityManagerFactory instead of something like customer-persistence-unit?


                        Configured the way I told you the PersistenceContext will be managed by Seam. If you want to take advantage of Seam's Conversation scoped PersistenceContexts then that is the way it will need to be. This in no way limits your ability to execute code asynchronously or outside of a Seam request though. Take a look at the spring-seam example. In there I was actually executing a spring configured timer task on a bean that used a Seam managed persistenceContext.

                        There is nothing that says you cannot use a Spring managed Entitymanager it just means you won't be able to take advantage of a Conversation scoped EntityManager.

                        Is there a particular reason why you would want to use a Spring managed EntityManager?


                        That was exact my question. I was not sure, whether the seam entity manager is available, if the request is not a JSF one, which runs through the seam filter (listener), but e.g. a WS-call, which is directed directly to Spring. If I understand you right, the entity manager is still available.

                        Anyway, your advice has been very valuable. Thanks a lot.

                        • 9. Re: TransactionalSeamPhaseListener + Spring @Transactional
                          dapeng

                          It will be really great if you have working example which uses spring managed local tx for non-JTA environment. A couple of anippets from components.xml, applicationContext.xml and persistence.xml will also be helpful.

                          • 10. Re: TransactionalSeamPhaseListener + Spring @Transactional
                            youngm

                            The spring example in the 2.0.0.cr1 nighly builds are configured exactly the way you are looking to use Seam + Spring. Using a spring configured EMF. A Seam conversation scoped EM. that is made available in spring using the SeamManagedEntityManagerFactoryBean. Have a look at the example in the nightly and let me know if you have any other questions.