4 Replies Latest reply on Sep 19, 2012 9:40 AM by Mauricio Salatino

    Spring Seam : ManagedPersistentContext and Injection (Spring -> CDI)

    gonzalad Apprentice

      Hello,


      I create a sample app with spring some time ago.


      I've managed pretty easily to :



      1. inject spring bean into CDI

      2. configure Seam 3 ManagedPersistentContext from Spring (à la Seam 2)



      Here's what I did (perhaps it can help someone) :





      I - Injecting Spring beans into CDI components





      2 choices for now :
      use the Spring CDI bridge (Rick Hightower)
      create a Producer yourself




      Approach 1 : Using Spring / CDI Bridge





      See http://rick-hightower.blogspot.com/2011/04/cdi-and-spring-living-in-harmony.html


      With this approach you just need to use :


      @Inject @Spring(name="fooBar") 
      FooSpringBean springBean;
      



      Personnaly, I don't like having to use @Spring special annotation.


      Would have prefered to just @Inject and if bean is a Spring bean, then Spring bean is injected, otherwhise
      just classic CDI bean.




      Approach 2 - Create Producer yourself





      @ApplicationScoped
      public class SpringServices {
              
              @Produces
              @RequestScoped
              public FooSpringBean getFooSpringBean() {
                      return (FooSpringBean) ContextLoader.getCurrentWebApplicationContext().getBean(FooSpringBean.class);
              }
      }
      



      And then you just need to use :


      @Inject
      FooSpringBean springBean;
      



      II - Seam-managed persistence context Configured in Spring





      <bean id="entityManagerFactory" class="tmp.pag.proto.seam3.ioc.spring.SeamManagedEntityManagerFactoryBean">
         <property name="persistenceContextName" value="entityManager" /> 
      </bean>
      <bean id="springEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaVendorAdapter">
          <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaPropertyMap">
          <map>
            <entry key="hibernate.cache.use_second_level_cache" value="true"/>
            <entry key="hibernate.cache.use_query_cache" value="true"/>
            <entry key="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>
            <entry key="hibernate.show_sql" value="false" />
            <entry key="hibernate.use_sql_comments" value="false" />
            <entry key="hibernate.format_sql" value="false" />
            <entry key="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
            <entry key="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
          </map>
        </property>
        <property name="dataSource" ref="dataSource"/>
      </bean>
      



      --------------------------------------------------------
      package tmp.pag.proto.seam3.jpa;
      
      import javax.enterprise.context.ConversationScoped;
      import javax.enterprise.inject.Default;
      import javax.enterprise.inject.Produces;
      import javax.persistence.EntityManagerFactory;
      
      import org.jboss.seam.solder.core.ExtensionManaged;
      import org.springframework.web.context.ContextLoader;
      
      public class ManagedPersistenceContext {
              
              /**
               * Inspired from http://docs.jboss.org/seam/3/persistence/latest/reference/en-US/html/persistence.html#d0e211
               * But uses Spring bean named 'springEntityManagerFactory'
               */
              @ExtensionManaged
              @Produces
              @ConversationScoped
              @Default
              public EntityManagerFactory getEntityManagerFactory() {
                      return ContextLoader.getCurrentWebApplicationContext().getBean("springEntityManagerFactory", EntityManagerFactory.class);
              }
      }
      
      --------------------------------------------------------
      
      package tmp.pag.proto.seam3.ioc.spring;
      
      import javax.enterprise.inject.spi.BeanManager;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      import javax.persistence.EntityManagerFactory;
      import javax.persistence.PersistenceException;
      
      import org.jboss.seam.faces.util.BeanManagerUtils;
      import org.jboss.seam.solder.core.Veto;
      import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
      
      @Veto
      public class SeamManagedEntityManagerFactoryBean extends
                      AbstractEntityManagerFactoryBean {
              private EntityManagerFactory entityManagerFactory;
              private String persistenceContextName;
      
              @Override
              protected EntityManagerFactory createNativeEntityManagerFactory()
                              throws PersistenceException {
                      return getDelegate();
              }
      
              @Override
              public String getPersistenceUnitName() {
                      String persistenceUnitName = super.getPersistenceUnitName();
                      if (persistenceUnitName == null || "".equals(persistenceUnitName)) {
                              return persistenceContextName;
                      }
                      return persistenceUnitName;
              }
      
              public void setPersistenceContextName(String persistenceContextName) {
                      this.persistenceContextName = persistenceContextName;
              }
      
              private EntityManagerFactory getDelegate() {
                      if (entityManagerFactory == null) {
                              initEntityManagerFactory();
                      }
                      return entityManagerFactory;
              }
      
              private void initEntityManagerFactory() {
                      InitialContext lContext;
                      try {
                              lContext = new InitialContext();
                              BeanManager lBeanManager = (BeanManager) lContext
                                              .lookup("java:comp/env/BeanManager");
                              entityManagerFactory = BeanManagerUtils.getContextualInstance(
                                              lBeanManager, EntityManagerFactory.class);
                      } catch (NamingException e) {
                              throw new RuntimeException(e);
                      }
              }
      }
      



        • 1. Re: Spring Seam : ManagedPersistentContext and Injection (Spring -> CDI)
          hantsy bai Master

          Good post.


          This post resolved how to inject spring bean in seam 3, but how to inject seam bean in Spring?


          And how to use them(Seam3, Spring)and make interoperability looks smoothly in a mixed ecosystem.

          • 2. Re: Spring Seam : ManagedPersistentContext and Injection (Spring -> CDI)
            gonzalad Apprentice

            Thanks !




            Injecting Spring beans into CDI components






            This post resolved how to inject spring bean in seam 3, but how to inject seam bean in Spring?

            If you need this feature you'll be interested in Rick Hightower's Spring CDI Bridge, his bridge does :



            1. CDI to Spring injection

            2. Spring to CDI Injection.



            Look here : http://rick-hightower.blogspot.com/2011/04/cdi-and-spring-living-in-harmony.html, section 'Bridging from the CDI World into Spring' :


            You'll need to declare a CdiBeanFactoryPostProcessor and a CdiFactoryBean per CDI bean to inject.


            <bean class="org.cdisource.springintegration.CdiBeanFactoryPostProcessor" />
            
            <bean class="org.cdisource.springintegration.CdiFactoryBean" name="taskRespository" >
               <property name="beanClass" value="org.cdisource.springapp.TaskRepository"/>
            </bean>
            




            • 3. Re: Spring Seam : ManagedPersistentContext and Injection (Spring -> CDI)
              Marius Bogoevici Newbie

              Adrian,


              Great update. I'll add for the record that, as discussed in the Seam meeting of yesterday for the 3.1 release of Seam, we intend to provide a Seam 3 Spring module which should provide the same functionality as Seam 2, including integration with Seam Persistence and others.


              Marius

              • 4. Re: Spring Seam : ManagedPersistentContext and Injection (Spring -> CDI)
                Mauricio Salatino Master

                Hi guys, I manage to get this working with CDI and Spring, but now I have a big problem related with transactions propagations between spring and CDI.

                In my case I have an application that was using spring, and I don't want to migrate to CDI completely, but the application needs to use a new module which is based on CDI.

                Both applications now can share the EMF configured in spring, but my spring app is using:

                 

                <bean id="TxManager" class="org.springframework.orm.jpa.JpaTransactionManager">

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

                        <property name="nestedTransactionAllowed" value="false"/>

                    </bean>

                 

                Is there any way to make CDI aware of the transactions created by the JpaTransactionManager?

                I'm in a SE environment and I'm using inside my beans.xml file the following configuration:

                 

                <interceptors>

                        <class>org.jboss.seam.transaction.TransactionInterceptor</class>

                    </interceptors>

                   

                    <t:SeSynchronizations>

                        <s:modifies/>

                    </t:SeSynchronizations>

                 

                 

                    <t:EntityTransaction>

                        <s:modifies />

                    </t:EntityTransaction>

                 

                After thinking for a while I was expecting to find TransactionInterceptor which can be aware of the Spring spawned transactions.

                Any pointers are highly appreciated

                Cheers