9 Replies Latest reply on Jan 17, 2011 2:49 AM by zzzz8.zzzz8.netzero.net

    Separate db flush within Long Running Conversation

    torakuma

      Hi-


      I have a LRC that edits some entity being backed by an EntityHome that spans multiple pages in a workflow.  It is using manual flushmode and only persists to the db at then end... works just fine.  On one of my pages the user can change some user settings (via an AJAX request) and I want those to actually persist to the db at that time (but not the editing entity).  I have it working using the code below but wanted to check with others in case there was a better way to do this



         // Invoked via AJAX 
          public void updateUserSettings() {
              // Leave the current conversation
              Conversation currentConversation = Conversation.instance();
              String currentConversationId = currentConversation.getId();
              currentConversation.leave();
      
              // Perform the user settings update
              ((UserSettingsHome) Component.getInstance(UserSettingsHome.class, true))
                      .updateUserSettings(userSettings);
      
              // Switch back to the current conversation...
              Manager.instance().switchConversation(currentConversationId);
          }




      I tried using a nested conversation initially but when I called updateUserSettings, changes to my entity in the LRC were also persisted.


      Is this the right way to do this?


      Thanks!


      D

        • 1. Re: Separate db flush within Long Running Conversation
          stephen

          Another option that comes to my mind is to use a second EntityManager just for the settings objects.
          That will of course only work if the settings objects do not have any relation to the business entity.

          • 2. Re: Separate db flush within Long Running Conversation
            stefanotravelli

            How did you implemented your nested conversation approach?


            I wrap methods called by ajax in a nested conversation and it works fine:




            @Transactional
            @Begin(nested = true)
            @End
            public void updateUserSettigns()
            {
            
            ...
            }
            
            


            In some cases I need to flush manually, so:



            @Transactional
            @Begin(nested = true, flushMode = FlushModeType.MANUAL)
            @End
            public void updateUserSettings()
            {
            ...
            
               getPersistenceContext().flush();
            }
            



            The nested conversation starts when the method is invoked and end when it ends. The LRC entity manager remains untouched and nested one flushes.


            • 3. Re: Separate db flush within Long Running Conversation
              torakuma

              Thanks so much for your response!


              I tried using the nested approach as you suggested but it still flushes changes in the LRC.



                  @Transactional
                  @Begin(nested = true, flushMode = FlushModeType.MANUAL)
                  @End    
                  public void updateUserSettings() {
                      ((UserSettingsHome) Component.getInstance(UserSettingsHome.class, true))
                              .updateUserSettings(userSettings);
                  }



              This was the approach that we took initially and I was pretty surprised to see the the LRC changes hit the db.  Perhaps there is something special I need to do so that the nested conversation gets a separate entityManger?

              • 4. Re: Separate db flush within Long Running Conversation
                torakuma

                Got it working.  I added a second entityManager in components.xml:



                   <persistence:managed-persistence-context name="entityManager2"
                                                     auto-create="true"
                                      persistence-unit-jndi-name="java:/someEntityManagerFactory"/> 



                And then changed UserSettingsHome to use that entityManager:



                    @Override
                    protected String getPersistenceContextName()
                    {
                       return "entityManager2";
                    } 



                Then the following worked:



                    @Transactional
                    @Begin(nested = true, flushMode = FlushModeType.MANUAL)
                    @End    
                    public void updateUserSettings() {
                        ((UserSettingsHome) Component.getInstance(UserSettingsHome.class, true))
                                .updateUserSettings(userSettings);
                    }



                Thanks!


                D



                • 5. Re: Separate db flush within Long Running Conversation
                  torakuma

                  Adding a second entityManager combined with the suggestions below worked great.


                  Thanks!


                  D

                  • 6. Re: Separate db flush within Long Running Conversation
                    stefanotravelli

                    Now that I double check, my LRC entity manager get flushed as well.


                    In fact, my code is pretty silly. @Begin starts the conversation after method invocation and not before. So starting and ending a conversation in the same method makes no sense.


                    I need to rethink about this. You make me point out a possible bug in my app. Thanks.

                    • 7. Re: Separate db flush within Long Running Conversation
                      torakuma

                      Ya, actually if I take out:



                          @Transactional
                          @Begin(nested = true, flushMode = FlushModeType.MANUAL)
                          @End  



                      It still works fine.  The key was making the second entity manager I think.

                      • 8. Re: Separate db flush within Long Running Conversation
                        thomrohd

                        Hi David,


                        what is your conclusion of using a second EntityManager instance? Were there any other problems or side effects or would you recommend this solution?


                        Your first idea with leaving the current conversation doesn't work for me. What makes your program within updateUserSettings(userSettings)?


                        Regards,
                        Thomas

                        • 9. Re: Separate db flush within Long Running Conversation
                          zzzz8.zzzz8.netzero.net

                          I couldn't configure my app to work with a second entity manager.  Could you provide instructions on how to do this?  When I add a second entity manager in my components.xml file (see snippet):


                          <persistence:managed-persistence-context name="entityManager" auto-create="true" persistence-unit-jndi-name="@puJndiName@" />
                               
                          <persistence:managed-persistence-context name="entityManager2" auto-create="true" persistence-unit-jndi-name="@puJndiName@" />
                          
                          <transaction:entity-transaction entity-manager="#{entityManager}" />
                                    
                          <transaction:entity-transaction entity-manager="#{entityManager2}" />



                          I get the following error:


                          Caused by: java.lang.IllegalStateException: Two components with the same name and precedence - component name: org.jboss.seam.transaction.transaction, component classes: org.jboss.seam.transaction.EntityTransaction, org.jboss.seam.transaction.EntityTransaction
                               at org.jboss.seam.init.Initialization.addComponentDescriptor(Initialization.java:601)
                               at org.jboss.seam.init.Initialization.installComponentFromXmlElement(Initialization.java:500)
                               at org.jboss.seam.init.Initialization.installComponentsFromXmlElements(Initialization.java:369)
                               at org.jboss.seam.init.Initialization.initComponentsFromXmlDocument(Initialization.java:228)
                               ... 60 more



                          Am I not supposed to define the transaction:entity-transaction component twice?  Could you show your components.xml and persistence.xml file?  Thanks!