14 Replies Latest reply on Sep 6, 2010 2:17 PM by deanhiller2000

    Persistence: @PersistenceContext and @In

    israel.bgf

      Can I use the CMT AND the Seam managed-peristence-context at the same time? Not in the same bean i mean, but in an application that mix POJOS with EJBs, some EJBs using the @PersistenceContext and POJOs using @In to inject the seam managed-entityManager. Is it possible? Thks


      Israel

        • 1. Re: Persistence: @PersistenceContext and @In
          asookazian

          Just try it.


          Short answer: most likely yes.  And then ask yourself why do you need or want to do that?  Typically we use @In to inject SMPC and use Hibernate manual flush to achieve atomic conversations.  I guess you would want to use @PersistenceContext if you wanted tx-scoped or component-scoped PC.  But describe a use case that requires this functionality.


          The @PersistenceContext injection is an EJB container-managed PC used typically with SFSB/SLSB or MDB components.


          I just tested an EntityManager injection using @PersistenceContext on a JavaBean and got this on deployment:


          Caused by: java.lang.IllegalArgumentException: @PersistenceContext may only be used on session bean or message driven bean components: testPCinject



          code:


          @Name("testPCinject")
          @Startup
          @Scope(ScopeType.SESSION)
          public class TestPCinject {
               
               @PersistenceContext 
               private EntityManager entityManager;
               
               @Logger 
               private Log log;
               
               @Create
               public void init(){
                    log.info("in init() for TestPCinject");
               }
               
          }



          SiA:



          Technically, the Java EE container handles injecting the EntityManager into a property annotated with @PersistenceContext


          Keep in mind that this annotation is only relevant for Java EE managed components (e.g., JSF managed beans or EJB session beans).


          The Seam-managed persistence context is scoped to the conversation, which
          means you tune its lifetime using the conversation propagation controls you learned
          about in chapter 7. What sets the Seam-managed persistence context apart from its
          container-managed counterpart is that it’s stored directly in the conversation, making
          it a first-class citizen of the application, rather than being bound to the lifetime of a
          single component. Consider that if an SFSB hosting an extended persistence context is
          removed, the persistence context goes along with it. In contrast, a Seam-managed persistence
          context remains available as long as the conversation is active, regardless of
          which components come and go. The best part is that you can share the persistence
          context between Java EE and non–Java EE components alike without having to worry
          about complex (and tricky) propagation rules.
          Although the extended persistence
          context in EJB 3 is a good start, Seam is better at handling this task.
          • 2. Re: Persistence: @PersistenceContext and @In
            israel.bgf

            Actually i was just wondering about it, nothing really serious. Well it really looks like that SMPC is always better than the EJB PC, unless that stuff like two-phase-commit is being used i think (i never used this, and probably i will never use, but how seam would handle this?).


            The fact is: for almost all applications that I'm currently developing Seam solves all the problems, i don't even know when i should use an EJB. And well, is it normal, or am i missing something from the EJBs?


            And thks Arbi, you are always answering my questions. :)

            • 3. Re: Persistence: @PersistenceContext and @In
              asookazian

              2PC/XA datasource is required when the tx manager is managing more than one resource manager.  An example is when you have a distributed tx that involves two databases (and thus two datasource configs for your Seam app).  Another one is when you have a distributed tx that involves one database and one JMS session (i.e. two resources). 


              With most typical CRUD applications, 2PC/XA protocol is not a concern.  But that is one of the advantages of using EJB, it handles 2PC/XA for you.


              There are many other advantages/features with EJB 3.0, such as interceptors, EJB timers, method level security, exposing web methods as web services, more fine-grained transaction demarcation semantics than what Seam's @Transactional provides.


              The local interface will not be required in EJB 3.1, which is a plus.


              Oh, you should typically use a SFSB to model a conversational use case as the backing bean for your JSF page.  Be aware that SFSB's do not exist in a session bean pool in the EJB container like SLSB's do.  So that means each client gets their own SFSB per conversation (or possibly more than one, depending on your use case and implementation) and that the EJB container will passivate (i.e. typically serialize to disk) the state of your SFSB to save JVM memory when the user is idle and has not accessed the SFSB for x min's and then the EJB container activates (i.e. deserializes from disk) to JVM memory when a business method on that particular SFSB instance is executed.  This means that you need to make sure that all instance variables either implement java.io.Serializable or are marked transient.


              This is probably something you don't need to worry about if you use conversation-scoped JavaBean components as backing beans for your JSF pages.  Although someone should verify this.  If there is no passivation and you have thousands of simultaneous users per minute or hour, for example, it's possible your JVM will run out of heap space memory unless your have a robust JBoss AS cluster setup to handle high loads.

              • 4. Re: Persistence: @PersistenceContext and @In
                kapitanpetko

                Yes, you can use both. As for the use case, a SMPC does not make sense for asynchronous methods and JMS. It doesn't support REQUIRES_NEW either, which is quite useful for background jobs (update 10000 records, but do not rollback if one update fails, etc). The SMPC could cache quite a few things, and if you want to make sure you are not getting stale data, you are better off using a transaction-scoped PC (so you don't have to worry about evict-ing entities and clear-ing the PC.


                HTH


                • 5. Re: Persistence: @PersistenceContext and @In
                  asookazian

                  Nikolay Elenkov wrote on Jul 25, 2009 06:06:


                  Yes, you can use both. As for the use case, a SMPC does not make sense for asynchronous methods and JMS. It doesn't support REQUIRES_NEW either, which is quite useful for background jobs (update 10000 records, but do not rollback if one update fails, etc). The SMPC could cache quite a few things, and if you want to make sure you are not getting stale data, you are better off using a transaction-scoped PC (so you don't have to worry about evict-ing entities and clear-ing the PC.

                  HTH




                  All very good points!

                  • 6. Re: Persistence: @PersistenceContext and @In
                    israel.bgf
                    Well, I tried to configure both of them and I got the infamous error when trying to use the SMPC:

                    "java.lang.IllegalStateException: JTA EntityManager cannot access a transactions"

                    The component.xml:

                         <core:init jndi-pattern="template/#{ejbName}/local" debug="true" distributable="false" transaction-management-enabled="false"/>
                       
                         <transaction:ejb-transaction/>

                        <transaction:entity-transaction entity-manager="#{em}"/>
                                     
                        <persistence:entity-manager-factory name="template" installed="true"/>

                        <!-- If Seam loads the persistence unit (JBoss 4.x), the EntityManagerFactory will be resolved from #{bookingDatabase}.
                             On JBoss AS 5, the EntityManagerFactory is retrieved from JNDI (the binding occurs during application deployment). -->
                        <persistence:managed-persistence-context name="em" auto-create="true"
                           entity-manager-factory="#{template}"/>
                          
                        <core:manager conversation-timeout="120000"
                                      concurrent-request-timeout="500"
                                      conversation-id-parameter="cid"/>
                         
                        <web:character-encoding-filter encoding="ISO-8859-1" override-client="true" url-pattern="*.seam" />
                       
                            <!-- Configurações de Segurança do Seam -->
                         <security:identity authenticate-method="#{authenticator.authenticate}" />
                       
                        <core:resource-loader>     
                             <core:bundle-names>     
                                 <value>seam</value>
                                 <value>label</value>     
                                 <value>messages</value>                   
                             </core:bundle-names>     
                         </core:resource-loader>

                    I have only one data-source, with only one persistence-unit. Maybe that's why the problem is happening. What did i do wrong?
                    • 7. Re: Persistence: @PersistenceContext and @In
                      asookazian

                      I'm not sure if it's ok to use


                      <transaction:ejb-transaction/>



                      and


                      <transaction:entity-transaction entity-manager="#{em}"/>



                      According to SiA:


                      Seam’s transaction managers are mutually exclusive. Seam uses applicationmanaged
                      JTA, retrieved from the JNDI registry, in non–EJB environments. If you’d
                      rather have Seam use resource-local transactions, perhaps because JTA isn’t available,
                      you configure the one that corresponds with the persistence API you’re using.
                      To use the resource-local transaction manager with JPA, define the following component
                      configuration:
                      <tx:entity-transaction entity-manager="#{em}"/>
                      You activate the resource-local transaction manager from Hibernate as follows:
                      <tx:hibernate-transaction session="#{hibernateSession}"/>



                      Table 9.3 in SiA is helpful as well.


                      Read the API docs regarding the following classes in the org.jboss.seam.transaction package:


                      UTtransaction, EntityTransaction, HibernateTransaction, CMTTransaction, NoTransaction


                      You're either operating in an EJB or non-EJB environment.  Which means JTA (Java EE and JBoss AS) or RESOURCE_LOCAL (for Java SE - remember, JPA can be used outside of an EE environment).


                      Bottom line: don't mix and match (or prove me wrong :)


                      Also, when you do this:


                      <core:init transaction-management-enabled="false"/>



                      you are essentially turning off Seam container's global transaction support.


                      from SiA:



                      As a word of warning, taking away Seam-managed transactions leaves the view rendering without a transaction.
                      • 8. Re: Persistence: @PersistenceContext and @In
                        israel.bgf

                        Hmm, so all of this means: I cant mix CMT with SMPC. So if I develop an application using SMPC and one day it needs a distributed tx, i would have to do a little refactoring to change the SMPC, to CMT, right? Or did i miss something?


                        Thks for the patience, i'm still learning the ways of Seam. :)

                        • 9. Re: Persistence: @PersistenceContext and @In
                          asookazian

                          This part of Seam (transactions and persistence) is the most complicated and most frustrating.  Application transactions, atomic conversations, global transactions, distributed transactions, etc. can be very confusing.  One of the reasons Seam has such a steep learning curve in addition to conversations, jBPM integration with business processes, bijection, interceptors, design patterns, remoting, a4j/RF, conversational web services, etc.


                          The answer is no.  You can use and should usually use CMT with SMPC if you are using EJB components.  If you need to access more than one database (or other resource like a JMS session) in the same tx, then you will need XA datasources.


                          Persistence contexts, entity managers and transactions are related but not the same.  Read Mike Keith's JPA book, it's a very good alternative to the standard JPA/Hibernate by CBauer/GKing.


                          And keep reading SiA and asking questions.  It took me almost 2 years to learn what I now know, the JBoss dev stack with EE 5 is intimidating.

                          • 10. Re: Persistence: @PersistenceContext and @In
                            jeanluc

                            So if I develop an application using SMPC and one day it needs a distributed tx, i would have to do a little refactoring to change the SMPC, to CMT, right?

                            This is not a 'little refactoring' but a significant design change. It's not about replacing @PersistenceContext with @In, but that that means. Tread carefully :-)

                            • 11. Re: Persistence: @PersistenceContext and @In
                              asookazian

                              Jean Luc wrote on Jul 30, 2009 18:28:


                              So if I develop an application using SMPC and one day it needs a distributed tx, i would have to do a little refactoring to change the SMPC, to CMT, right?

                              This is not a 'little refactoring' but a significant design change. It's not about replacing @PersistenceContext with @In, but that that means. Tread carefully :-)


                              Ok, so I'm confused.  Is it not possible to use XA datasources with SMPC?  AFAIK, you can use XA with @PersistenceContext (container-managed PC) or @In (SMPC). You can use BMT with SMPC, you can use CMT with SMPC (as long as you're using an EJB component) or you can use SMT (Seam-managed tx's via @Transactional) with SMPC.  Please correct me if I'm wrong.

                              • 12. Re: Persistence: @PersistenceContext and @In
                                israel.bgf

                                Well, thks for all the answers, i think that i will have to take some time thinking about all of this before asking anything new. :)

                                • 13. Re: Persistence: @PersistenceContext and @In
                                  asookazian

                                  The basic ideas are the following:


                                  An EntityManager manages a PersistenceContext whether it's PC (EJB-container managed) or SMPC (Seam managed).  The PC is tx- or component-scoped.  The SMPC is conversation-scoped.  This keeps the EntityManager open until the LRC ends and thus prevents LazyInitializationExceptions and forcing us to use Open Session In View pattern like in Spring/Hibernate apps.  Look at org.jboss.seam.persistence.ManagedPersistenceContext for the details on how this works, it's pretty interesting.  The EntityManager interface instance is returned via manager component pattern (@Unwrap).


                                  When you're executing an API call using EntityManager, you can use transactions if you want to.  With an EJB component, you have the option of BMT or CMT.  With CMT, by default, a tx is REQUIRED.  There are tx propagation semantics to be aware of as well, like when EJB 1 calls EJB 2, is the tx propagated or not, etc.  There are also tx isolation levels to be aware of (e.g. read committed, repeatable read, serializable, etc.) and the defaults are different for each db vendor.  The isolation level you use will affect data integrity as well as performance.


                                  I recommend reading the Mike Keith JPA book first, then reading the SiA chapter 9 as well as the transactions section in JPA/Hibernate book.


                                  This is really too much information to take in simultaneously and is one of the biggest problems with this stack in terms of generating a massive learning curve.


                                  The pic below from SiA was very helpful to me:


                                  • 14. Re: Persistence: @PersistenceContext and @In
                                    deanhiller2000

                                    I have had non JTA with seam pojo's working for 1 year now in production(2 years in dev).  unfortunately, we are in jboss and our entity layer is loaded twice...once for JTA for the EJB's we have and once nonJTA for seam.


                                    Ideally, I would really like to use JTA with seam pojo's so the entity layer is loaded once not twice.  Also, I do NOT want seam to have to use any EJB's but the entities as well(I hate having an interface for every seam bean....too much overhead for no benefit as of yet).


                                    Currently, I have this persistence.xml and components.xml which is failing


                                    NOTE: The only thing different in components.xml is I changed the jndi name to java:/xcoreEntityManagerFactory and the entityManager name from xcore3NonJta to xcore3....everything else is still the same(but should it be?)


                                    <?xml version="1.0" encoding="UTF-8"?>
                                    <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="xcore" transaction-type="JTA">
                                              <jta-data-source>java:/OracleDS</jta-data-source>
                                              <properties>
                                                   <property name="hibernate.dialect"
                                                        value="org.hibernate.dialect.Oracle10gDialect" />
                                                   <!--         <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> -->
                                    
                                                   <property name="hibernate.hbm2ddl.auto" value="validate" />
                                                   <property name="hibernate.default_schema" value="VOICELOG" />
                                                   
                                                   <property name="jboss.entity.manager.jndi.name" value="java:/xcoreEntityManager"/>               
                                                   <property name="jboss.entity.manager.factory.jndi.name" value="java:/xcoreEntityManagerFactory" />
                                                   
                                              </properties>
                                         </persistence-unit>
                                    </persistence>
                                    
                                    





                                    <?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:transaction="http://jboss.com/products/seam/transaction"
                                                xmlns:security="http://jboss.com/products/seam/security"
                                                xmlns:resteasy="http://jboss.com/products/seam/resteasy"
                                                xmlns:remoting="http://jboss.com/products/seam/remoting"
                                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                                xmlns:web="http://jboss.com/products/seam/web" 
                                                xmlns:mail="http://jboss.com/products/seam/mail"
                                                   xmlns:navigation="http://jboss.com/products/seam/navigation"
                                                xsi:schemaLocation=
                                                    "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd 
                                                     http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.1.xsd 
                                                     http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.1.xsd 
                                                     http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.1.xsd
                                                     http://jboss.com/products/seam/resteasy http://jboss.com/products/seam/resteasy-2.2.xsd
                                                     http://jboss.com/products/seam/remoting http://jboss.com/products/seam/remoting-2.1.xsd
                                                     http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.1.xsd
                                                     http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd
                                                     http://jboss.com/products/seam/web http://jboss.com/products/seam/web-2.1.xsd
                                                     http://jboss.com/products/seam/navigation http://jboss.com/products/seam/navigation-2.0.xsd">
                                    
                                    
                                         <core:init debug="false" distributable="false"/>
                                        <core:manager conversation-timeout="900000" 
                                                      concurrent-request-timeout="30000"
                                                      conversation-id-parameter="cid"/>
                                                  
                                        <web:rewrite-filter view-mapping="*.xhtml" />
                                         
                                         <web:cache-control-filter name="imageCacheControlFilter"
                                                              regex-url-pattern=".*(\.gif|\.png|\.jpg|\.jpeg)"
                                                              value="max-age=86400"/>
                                          
                                         <web:cache-control-filter name="textCacheControlFilter"
                                                              regex-url-pattern=".*(\.css|\.js)"
                                                              value="max-age=86400"/>
                                         
                                        <transaction:entity-transaction entity-manager="#{entityManager}"/>
                                                      
                                        <persistence:entity-manager-factory name="xcore" installed="false"/>
                                    
                                        <!-- If Seam loads the persistence unit (JBoss 4.x), the EntityManagerFactory will be resolved from #{bookingDatabase}.
                                             On JBoss AS 5, the EntityManagerFactory is retrieved from JNDI (the binding occurs during application deployment). -->
                                        <persistence:managed-persistence-context name="entityManager" auto-create="true"
                                           entity-manager-factory="#{xcore}" persistence-unit-jndi-name="java:/xcoreEntityManagerFactory"/>
                                    
                                         <mail:mail-session ssl="false" tls="false" host="#{smtpServer}" port="#{smtpPort}" username="#{smtpUserName}" password="#{smtpPasswd}" />            
                                                        
                                        <security:identity authenticate-method="#{login.authenticate}"/>  
                                     
                                         <remoting:remoting debug="false"/>
                                        <resteasy:application resource-path-prefix="/restv1"/>  
                                        
                                        <event type="org.jboss.seam.security.notLoggedIn">
                                             <action execute="#{redirect.captureCurrentView}"/>
                                             <action execute="#{identity.tryLogin()}"/>
                                           </event>
                                    
                                           <event type="org.jboss.seam.security.loginSuccessful">
                                             <action execute="#{redirect.returnToCapturedView}"/>
                                         </event>
                                         
                                         <navigation:pages>
                                              <navigation:resources>
                                                   <value>/WEB-INF/pages.global.xml</value>
                                                   <value>/WEB-INF/pages.callinfo.xml</value>
                                                   <value>/WEB-INF/pages.archived.xml</value>               
                                                   <value>/WEB-INF/pages.dataloader.xml</value>
                                                   <value>/WEB-INF/pages.datapost.xml</value>
                                                   <value>/WEB-INF/pages.ondemand.xml</value>
                                                   <value>/WEB-INF/pages.admin.xml</value>
                                                   <value>/WEB-INF/pages.scripter.xml</value>
                                                   <value>/WEB-INF/pages.reviewer.xml</value>
                                              </navigation:resources>
                                         </navigation:pages>
                                    </components>