3 Replies Latest reply on Jul 12, 2008 4:59 PM by rhodyfan

    EXCEPTION when using Seam, Spring, and Transactions

    rhodyfan

      I'm following much of Dan's work in Seam in Action for integrating Spring and Seam (hoping maybe Dan can help with this) but i've been struggling for a few days now with my application. The first thing i did was follow the setup of using Seam's managed persistent context. This worked fine for all most everything until i ran our web service tests and i noticed them failing. The exception was originally that the Seam application context wasn't available and to wrap it in spring transaction or use seam:component tag, so i did the  latter. I have two spring beans that handle the web services:


      <!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies -->
      <bean id="UserMgmtServiceWS" class="com.xxx.coreservice.um.webservice.UserMgmtServiceWS">
              <seam:component/>
              <property name="userMgmtModel" ref="UserMgmtModel"/>
              <property name="transformer2" ref="Transformer2"/>
              <property name="attrModel" ref="AttributeModel"/>
              <property name="aclModel" ref="AclModel"/>
              <property name="proxy" ref="UserMgmtServiceWSProxy"/>
      </bean>
      
      <bean id="UserMgmtServiceWSProxy" class="com.xxx.coreservice.um.webservice.UserMgmtServiceWSProxyImpl">
           <seam:component/>
           <property name="userMgmtModel" ref="UserMgmtModel"/>
           <property name="attrModel" ref="AttributeModel"/>
           <property name="transformer" ref="Transformer2"/>
      </bean>



      the *Models (userMgmtModel, attrModel, etc..) beans that i pass in to the beans above contain all the business logic and have the seam managed persistent context injected into using the PersistenceAnnotationBeanPostProcessor and the @PersistentContext annotation.


      So the exception I'm getting has to do with transactions, and here  is the exception:


      org.apache.axis2.AxisFault: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Transaction already active; nested exception is: 
           org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Transaction already active
           at org.apache.axis2.AxisFault.makeFault(AxisFault.java:321)
      



      Here is my setup for transactions, also following much of Dan's work:


      <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
           <property name="entityManagerFactory" ref="entityManagerFactory"/>
      </bean>     
      
      <!-- Transaction aspect for web service proxy -->
      <aop:config proxy-target-class="true">
           <aop:pointcut id="wsProxyMethods" expression="execution(* com.xxx.coreservice.um.webservice.UserMgmtServiceWSProxy.*(..))"/>
           <aop:advisor advice-ref="txWSProxyAdvice" pointcut-ref="wsProxyMethods"/>
      </aop:config>
           
      <!-- Transaction aspect for the Web Service layer -->
      <aop:config proxy-target-class="true">
           <aop:pointcut id="userMgmtServiceWSMethods" expression="execution(* com.xxx.coreservice.um.webservice.gen.UserMgmtServiceSkeletonInterface.*(..))"/>
           <aop:advisor advice-ref="txUserModelAdvice" pointcut-ref="userMgmtServiceWSMethods"/>
      </aop:config>
      
      <tx:advice id="txUserModelAdvice" transaction-manager="transactionManager">
           <tx:attributes>          
           <tx:method propagation="REQUIRED" name="get*" read-only="true" no-rollback-for="com.xxx.coreservice.um.domain.exceptions.ObjectNotFoundException, com.xxx.coreservice.um.domain.exceptions.AttributeSetNotFoundException, javax.persistence.NoResultException"/>
              <tx:method propagation="REQUIRED" name="*" no-rollback-for="com.xxx.coreservice.um.domain.exceptions.ProceedableExceptionsContainerException" rollback-for="com.xxx.coreservice.um.webservice.gen.UserManagementExceptionMessageException"/>
              </tx:attributes>
      </tx:advice>
           
      <tx:advice id="txWSProxyAdvice" transaction-manager="transactionManager">
           <tx:attributes>
           <tx:method propagation="REQUIRED" name="get*" read-only="true" no-rollback-for="com.xxx.coreservice.um.domain.exceptions.ObjectNotFoundException,     com.xxx.coreservice.um.domain.exceptions.AttributeSetNotFoundException, javax.persistence.NoResultException"/>
           <tx:method propagation="REQUIRES_NEW" name="*" rollback-for="com.xxx.coreservice.um.webservice.gen.UserManagementExceptionMessageException"/>
           </tx:attributes>
      </tx:advice>
      



      The major thing of difference here is the REQUIRES_NEW propagation setting for the UserMgmtServiceWSProxy bean for all methods other than gets. All web service calls come thru the first bean UserMgmtServiceWS so this is the outer transaction and is set to REQUIRED. I pass in the UserMgmtServiceWSProxy into the UserMgmtServiceWS bean as seen above:


      ...<property name="proxy" ref="UserMgmtServiceWSProxy"/>...



      This proxy is called by certain methods that take in a list of users to perform an action on and we want each action on a user to be its own transaction so that if any one fails it continue for each user. So that is why we created this intermediate layer containing methods that handle lists of users with the REQUIRES_NEW propagation advice. So this inner transaction is REQUIRES_NEW.


      this all worked fine before introducing the Seam managed persistent context integration.


      Any help would be greatly appreciated!!!!


      thanks,
      Dennis


      just as a note here is my components.xml:


      <?xml version="1.0" encoding="UTF-8"?>
      <components xmlns="http://jboss.com/products/seam/components" 
                  xmlns:core="http://jboss.com/products/seam/core" 
                  xmlns:persistence="http://jboss.com/products/seam/persistence" 
                  xmlns:security="http://jboss.com/products/seam/security" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                  xmlns:transaction="http://jboss.com/products/seam/transaction" 
                  xmlns:spring="http://jboss.com/products/seam/spring" 
                  xsi:schemaLocation=
                      "http://jboss.com/products/seam/core 
                       http://jboss.com/products/seam/core-2.0.xsd 
                       http://jboss.com/products/seam/persistence 
                       http://jboss.com/products/seam/persistence-2.0.xsd 
                       http://jboss.com/products/seam/security 
                       http://jboss.com/products/seam/security-2.0.xsd 
                       http://jboss.com/products/seam/components 
                       http://jboss.com/products/seam/components-2.0.xsd 
                       http://jboss.com/products/seam/transaction 
                       http://jboss.com/products/seam/transaction-2.0.xsd 
                       http://jboss.com/products/seam/spring 
                           http://jboss.com/products/seam/spring-2.0.xsd">
      
          <core:init transaction-management-enabled="true" debug="true"/>
      
          <spring:spring-transaction platform-transaction-manager="#{transactionManager}"/>
           
          <spring:context-loader config-locations="/WEB-INF/spring-seam-config.xml"></spring:context-loader>
      
          <core:manager conversation-timeout="120000" 
                        concurrent-request-timeout="500"
                        conversation-id-parameter="cid"/>
      
          <core:resource-loader>
               <core:bundle-names>
                <value>upmui</value>
               </core:bundle-names>
          </core:resource-loader>
      
          <persistence:managed-persistence-context 
                name="entityManager" 
                auto-create="true"
           entity-manager-factory="#{entityManagerFactorySpring}">
          </persistence:managed-persistence-context>
      
      </components>