7 Replies Latest reply on Sep 3, 2008 4:40 PM by alin.heyoulin.qq.com

    Problem integrating Seam 2 into Spring 2.5 application

    marvm

      Hello,


      I try to integrate Seam into my Spring 2.5 based project.


      I am using the latest JBosss but due to some time issues I do not want to reprogram my DAOs to some session beans, so the database access should be covered still by my DAOs.


      As persistence provider I chose Hibernate 3.2. After programming some pages with jsf and seam components I ran into the problem of getting LazyInitializationExceptions. I figured out that the problem is caused by spring. I tried to make an entity available during a long running conversation. After retrieving it from the database and rendering the first page the instance is detached, because the spring transaction finished, which is normal.
      Now I get the exception when I request the next page which refers to a lazy-loaded set of my object from the conversation scope.
      I thought ok, let's see what seam is offering me as a solution and found the magic seam managed persistence context! And now I am totally frustrated getting this into my application... ;)


      Ok, maybe my current, not working configuration says more:


      components.xml:


          <core:manager conversation-timeout="120000" 
                        concurrent-request-timeout="500" 
                        conversation-id-parameter="cid"/>
      
          <persistence:managed-persistence-context name="entityManager"
                                            auto-create="true" 
                                            entity-manager-factory="#{entityManagerFactory}" />
          
          <!-- Configuration of Hibernate Session -->
          <persistence:hibernate-session-factory></persistence:hibernate-session-factory>
          <persistence:managed-hibernate-session name="hibernateSession" auto-create="true" />
           
          <core:init debug="true"/>
          
           <spring:context-loader config-locations="/WEB-INF/applicationContext.xml"/>
          
          <!-- Install the SpringDispatcher as default -->
          <spring:task-executor-dispatcher schedule-dispatcher="#{threadPoolDispatcher}" task-executor="#{springThreadPoolTaskExecutor}"/>
          
          <spring:spring-transaction platform-transaction-manager="#{transactionManager}"/>
      </components>
      




      application-context.xml


      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName"><value>${dataSource.driverClassName}</value></property>
                <property name="url"><value>${dataSource.url}</value></property>
              <property name="username"><value>${dataSource.username}</value></property>
              <property name="password"><value>${dataSource.password}</value></property>
          </bean>    
          
           <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                <property name="dataSource" ref="dataSource"/>
                <property name="persistenceUnitName" value="myDb"/>
           </bean>
      
           <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                <property name="sessionFactory">
                     <ref bean="sessionFactory"/>
                </property>
           </bean>
            
           <tx:annotation-driven proxy-target-class="true" />
           
           
           <!-- EMF that wraps a Seam Managed EM instance for use in Spring -->
           <bean id="seamEntityManagerFactory" class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
                <!-- The Seam managed-persistence-context component name. -->
                <property name="persistenceContextName" value="entityManager" />
                <!-- Optionally provide a unit name.  If not specified the default would be the persistenceContextName -->
                <property name="persistenceUnitName" value="myDb"/>
           </bean>
      
           <bean id="sessionFactory" class="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean">
                <property name="sessionName" value="hibernateSession"/>
           </bean>





      hibernate.cfg.xml


      <hibernate-configuration>
           <session-factory name="java:/hibernateSessionFactory">
      
                <property name="dataSource">java:/PofProjectDbDS</property>
      
                <property name="hibernate.dialect">
                     org.hibernate.dialect.SQLServerDialect
                </property>
                <property name="transaction.flush_before_completion">
                     true
                </property>
                <property name="connection.release_mode">
                     after_statement
                </property>
                <property name="transaction.manager_lookup_class">
                     org.hibernate.transaction.JBossTransactionManagerLookup
                </property>
                <property name="transaction.factory_class">
                     org.hibernate.transaction.JTATransactionFactory
                </property>
      
                <mapping package="com.project.model" />
                <mapping class="com.project.model.Person" />




      well, I tried everything to make it work, so some options are doubled now...
      persistence.xml



      <persistence version="1.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_1_0.xsd">
         <persistence-unit name="myDb" transaction-type="RESOURCE_LOCAL"> 
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <jta-data-source>java:/MyProjectDS</jta-data-source> 
            <properties> 
               <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
               <property name="transaction.flush_before_completion" value="true" />
               <property name="connection.release_mode" value="after_statement" />
               <property name="transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
               <property name="transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
            </properties> 
         </persistence-unit>



      My application starts normally, everything seems to be mapped correctly, but when I send the first request to the application I get the following exception:


      Caused by: java.lang.IllegalAccessException: Class org.jboss.seam.util.Reflections can not access a member of class org.springframework.beans.factory.config.AbstractFactoryBean with modifiers "protected"
           at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
           at java.lang.reflect.Method.invoke(Method.java:588)
           at org.jboss.seam.util.Reflections.invoke(Reflections.java:21)
           at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
           at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:31)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:42)
           at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
           at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:106)
           at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:155)
           at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:91)
           at org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean_$$_javassist_0.getEarlySingletonInterfaces(SeamManagedSessionFactoryBean_$$_javassist_0.java)
           at org.springframework.beans.factory.config.AbstractFactoryBean.getEarlySingletonInstance(AbstractFactoryBean.java:145)
           at org.springframework.beans.factory.config.AbstractFactoryBean.getObject(AbstractFactoryBean.java:133)
           at org.springframework.beans.factory.support.AbstractBeanFactory$3.run(AbstractBeanFactory.java:1304)
           ... 201 more




      When I try to solve that problem by making my sessionFactory a seam component I get another exception:


      java.lang.IllegalStateException: Seam application context not available and cannot be started.  Seam Managed Persistence Context not available.  Try placing the spring bean call inside of a spring transaction or try making the spring bean a Seam Component using <seam:component/>.
           at org.jboss.seam.ioc.spring.SeamLifecycleUtils.beginTransactionalSeamCall(SeamLifecycleUtils.java:44)
           at org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean$SeamManagedSessionFactoryHandler.getSession(SeamManagedSessionFactoryBean.java:129)
           at org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean$SeamManagedSessionFactoryHandler.getRawSessionFactory(SeamManagedSessionFactoryBean.java:122)
           at org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean$SeamManagedSessionFactoryHandler.invoke(SeamManagedSessionFactoryBean.java:145)
      




           <bean id="sessionFactory" class="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean">
                <property name="sessionName" value="hibernateSession"/>
                <seam:component />
           </bean>




      Does anybody have some help?
      Thanks in advance...

        • 1. Re: Problem integrating Seam 2 into Spring 2.5 application
          youngm

          A couple of comments.


          1. You've got a confusing mixture of both Hibernate and JPA.  Is there a reason why you have both?  I'd recommend getting rid of one of the other.  They are 2 separate things try to use only one or the other.


          2. Delete the persistenceUnitName from your seamEntityManagerFactory.  Having 2 EMFs with the same UnitName might be confusing to Spring.


          3. Make sure you use a TX manager that matches the persistence you're using use the HibernateTransactionManager if using Hibernate or JPATransactionManager is using JPA and set the entityManagerFactory to seamEntityManagerFactory.


          4. Reread the documentation on Spring persistence and transaction integration and make sure you understand what is going on there.  There are a few levels of indirection going on so try to make a good effort to understand what this integration is doing.


          5. Don't make any of these SeamManaged things seam:components.  That error you got is probably more because your transaction managers were mixed up.


          Mike

          • 2. Re: Problem integrating Seam 2 into Spring 2.5 application
            marvm

            Ok, thanks for the advice.


            1. I removed the mixture and migrated the HibernateDAOs to JpaDAOs, so I just use JPA.


            2. Now it looks more like the example in the docs.


                 <bean id="entityManagerFactory"
                      class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
                      <property name="persistenceUnitName" value="projectDb" />
                 </bean>
                 <bean id="seamEntityManagerFactory"
                      class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
                      <property name="persistenceContextName" value="entityManager" />
                      <property name="persistenceUnitName" value="projectDb:extended"/>
            
                 </bean>
                 <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
                      <property name="defaultPersistenceUnitName" value="projectDb:extended" />
                 </bean>



            All my DAOs get the emf injected like this:


            <property name="entityManagerFactory" ref="seamEntityManagerFactory" />



            3. I removed the Spring TX manager.


            ...well after reading and trying out a bit more, I came to another blocking point:
            I make a request to a page, the Spring controller calls a method of a DAO and gets an object which is already detached from the session when the DAO method finishes.
            Now I supposed seam to have some feature for me to keep this object attached until the end of the rendering of the page.


            I'm not sure whether this is a Seam or Spring issue. Should I try to use some of Springs TX features or did I miss something in my Seam configuration that would solve my problem?


            • 3. Re: Problem integrating Seam 2 into Spring 2.5 application
              marvm

              I read the documentation now a third time and have some additional questions:


              From chapter 23 of the seam docs



              provides a Seam managed replacement for Spring's OpenEntityManagerInViewFilter and OpenSessionInViewFilter


              One of the most powerful features of Seam is its conversation scope and the ability to have an EntityManager open for the life of a conversation.

              This implies to me I could get rid of the LIE if I just give a scope (seam.CONVERSATION ?) to all my DAOs and controllers or am I  wrong?




               

              • 4. Re: Problem integrating Seam 2 into Spring 2.5 application
                superfis

                Hi, I'm curious to know if you used Spring DAOs with Seam in long running conversations finally?

                • 5. Re: Problem integrating Seam 2 into Spring 2.5 application
                  rmcdonough

                  I'm not quite sure what you mean by getting rid of the LIE but my project is making use of a Spring DAO layer that uses a Seam-managed Session factory. In this set up, only the action/controller class should need to be Conversation-scoped if you want long running conversations. For example:


                  Seam Component: CustomerRegistrationAction : Scope.Conversation


                  Spring Bean: CustomerDAO : uses Autowired SessionFactory


                  In our design, we don't add any Seam specific configuration, other than the Seam-managed Session factory, to the Spring beans.


                  Ryan-



                  • 6. Re: Problem integrating Seam 2 into Spring 2.5 application
                    alin.heyoulin.qq.com
                    just try
                    
                    <spring:spring-transaction platform-transaction-manager-name="transactionManager" join-transaction="true"/>
                    
                    
                    and remove
                    <!-- EMF that wraps a Seam Managed EM instance for use in Spring -->
                         <bean id="seamEntityManagerFactory" class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
                              <!-- The Seam managed-persistence-context component name. -->
                              <property name="persistenceContextName" value="entityManager" />
                              <!-- Optionally provide a unit name.  If not specified the default would be the persistenceContextName -->
                              <property name="persistenceUnitName" value="myDb"/>
                         </bean>
                    
                         <bean id="sessionFactory" class="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean">
                              <property name="sessionName" value="hibernateSession"/>
                         </bean>
                    
                    In you seam compenent inject spring Dao like this
                    @In("#{springdao}")
                       private SpringDao yws;
                    
                    

                    • 7. Re: Problem integrating Seam 2 into Spring 2.5 application
                      alin.heyoulin.qq.com

                      and you'd better use JTA



                      transaction-type="JTA"


                      config your JTA transactionManager