10 Replies Latest reply on Dec 23, 2009 10:03 AM by giunad

    EntityHome: No transaction is in progress

    asriel

      Hi everybody,
      I'm trying to make a page that allows the user to select an entity from a DataTable and to edit the entity that has been selected through a form.


      For persistence I'm using the EntityHome class generated by seam-gen (the entity is Sperimentazione and the class I use for managing the persistence is SperimentazioneHome).


      Here is how I do that:


      - When the user selects a row on the table, the selection listener is fired and it links the selected entity to the EntityHome instance via .setInstance()


      - When the user then clicks the button to make an update, the action listener is fired and it calls the EntityHome method .update()


      but then the exception javax.faces.el.EvaluationException: javax.persistence.TransactionRequiredException: no transaction is in progress is raised.


      Here is the view:



      <ice:panelGroup>
              <ice:form>
                      <ice:dataTable var="_sperimentazione" value="#{sperimentazioneList.dataModel}">
                              <ice:column>
                                      <ice:rowSelector value="#{_sperimentazione.selected}"
                                              selectionListener="#{testTableSelection.selectionListener}"/>
                                      <f:facet name="header"><ice:outputText value="id"/></f:facet>
                                      <ice:outputText value="#{_sperimentazione.id}"/>
                              </ice:column>
                              <ice:column>
                                      <f:facet name="header"><ice:outputText value="idAmministrativo"/></f:facet>
                                      <ice:outputText value="#{_sperimentazione.idAmministrativo}"/>
                              </ice:column>
                              <ice:column>
                                      <f:facet name="header"><ice:outputText value="Tipo di sperimentazione"/></f:facet>
                                      <ice:outputText value="#{_sperimentazione.clsSperimentazione.tipo}"/>
                              </ice:column>
                              <ice:column>
                                      <f:facet name="header"><ice:outputText value="Descrizione"/></f:facet>
                                      <ice:outputText value="#{_sperimentazione.descrizione}"/>
                              </ice:column>
                      </ice:dataTable>
              </ice:form>
      </ice:panelGroup>
      
      <ice:panelGroup>
              <ice:form>
                      <ice:outputLabel for="sperimId" value="id:"/>
                      <ice:outputLabel id="sperimId" value="#{sperimentazioneHome.instance.id}"/> 
                      <h:message for="sperimId"/> <br />
                      
                      <ice:outputLabel for="sperimIdAmministr" value="id Amministrativo:"/>
                      <ice:inputText id="sperimIdAmministr" value="#{sperimentazioneHome.instance.idAmministrativo}"/> 
                      <h:message for="sperimIdAmministr"/> <br />
               
                      <ice:outputLabel for="sperimTipo" value="Tipo di sperimentazione:"/>
                      <ice:selectOneMenu id="sperimTipo" value="#{sperimentazioneHome.instance.clsSperimentazione}"> 
                              <s:selectItems value="#{clsSperimentazioneList.resultList}" itemValue="#{_tipoSperimentazione}"
                                      var="_tipoSperimentazione" label="#{_tipoSperimentazione.tipo}"/>
                              <s:convertEntity />
                      </ice:selectOneMenu> <h:message for="sperimTipo"/> <br />
      
                      <ice:outputLabel for="sperimDescriz" value="Descrizione:"/>
                      <ice:inputText id="sperimDescriz" value="#{sperimentazioneHome.instance.descrizione}"/>
      
                      <h:message for="sperimDescriz"/> <br />
                      
                      <ice:commandButton value="Modifica" action="#{sperimentazioneHome.update}"/>
              </ice:form>
      </ice:panelGroup>




      And here is the controller that hosts the listeners:


      @Name("testTableSelection")
      public class TestTableSelectionAct {
              
              @In(value = "sperimentazioneList")
              private SperimentazioneList sperimList;
      
              @In
              private SperimentazioneHome sperimentazioneHome;
      
              public TestTableSelectionAct() {
              }
              
              public void selectionListener(RowSelectorEvent rsevt) {
                      sperimentazioneHome.setInstance(sperimList.getDataModelSelection());            
              }
              
              @TransactionAttribute
              public void updateCommandListener(ActionEvent acevt) {
                      sperimentazioneHome.update();
              }
      
              public SperimentazioneHome getSperimHome() {
                      return sperimentazioneHome;
              }
      
              public void setSperimHome(SperimentazioneHome sperimHome) {
                      this.sperimentazioneHome = sperimHome;
              }
      }
      



      The SEAM component SperimentazioneHome has been set with a Page scope.
      Do you have any idea of how to fix this?
      (The @TransactionAttribute annotation is a last minute attempt to make things working, but it changed nothing)


      Thank you.

        • 1. Re: EntityHome: No transaction is in progress
          gus888

          In your update method, try to add super.joinTransaction();

          • 2. Re: EntityHome: No transaction is in progress
            asriel

            The update() method of the EntityHome class, from which SperimentazioneHome derives, already makes a call to joinTransaction()


               @Transactional
               public String update()
               {
                  joinTransaction();
                  getEntityManager().flush();
                  updatedMessage();
                  raiseAfterTransactionSuccessEvent();
                  return "updated";
               }
            


            • 3. Re: EntityHome: No transaction is in progress
              gus888

              Looks like @TransactionAttribute is for ejb bean. For java bean, it is @Transactional.

              • 4. Re: EntityHome: No transaction is in progress
                jguglielmin

                would you not want to use a conversation scope where the conversation begins when you select the id and create the instance of the EntityHome?  The conversation would then end when you either have updated successfully or cancelled the update, correct? YOu can track through your page-scoped bean, but I don't see how it will maintain the tx for you through it all.

                • 5. Re: EntityHome: No transaction is in progress
                  asriel

                  Thank you for your reply. I've tried even with @Transactional: I got the same result.


                  Here is the stack trace:


                  19:23:49,496 SEVERE [event] Received 'javax.persistence.TransactionRequiredException' when invoking action listener '#{testTableUpdate.updateCommandListener}' for component 'j_id52'
                  19:23:49,500 SEVERE [event] javax.persistence.TransactionRequiredException: no transaction is in progress
                       at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:301)
                       at org.jboss.seam.persistence.EntityManagerProxy.flush(EntityManagerProxy.java:92)
                       at org.jboss.seam.framework.EntityHome.update(EntityHome.java:64)
                       at it.scandix.assc.action.TestTableUpdateAct.updateCommandListener(TestTableUpdateAct.java:21)
                       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                       at java.lang.reflect.Method.invoke(Method.java:592)
                       at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
                       at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32)
                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
                       at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                       at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:77)
                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                       at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:97)
                       at org.jboss.seam.util.Work.workInTransaction(Work.java:47)
                       at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91)
                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                       at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                       at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
                       at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185)
                       at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103)
                       at it.scandix.assc.action.TestTableUpdateAct_$$_javassist_seam_11.updateCommandListener(TestTableUpdateAct_$$_javassist_seam_11.java)
                       ...
                       at java.lang.Thread.run(Thread.java:613)
                  



                  Any other ideas?

                  • 6. Re: EntityHome: No transaction is in progress

                    Did you try:




                    @Name("testTableSelection")
                    @TransactionAttribute(REQUIRES_NEW)
                    public class TestTableSelectionAct {
                    



                    • 7. Re: EntityHome: No transaction is in progress
                      asriel


                      Hi Chris,


                      I tried your suggestion but it didn't work. Thanks anyway.




                      Hi Judy,


                      thank you for your reply. Do you think that even if the component has a scope of PAGE or SESSION, the transaction could last shorter? Notice in the code block I reported previously that in EntityHome (code automatically generated by seam-gen) the method update() is annotated as @Transactional: that should mean that the method must be executed with an active transaction and, by default, if one does not exist then it is created.

                      • 8. Re: EntityHome: No transaction is in progress
                        asriel

                        It seems that Judy was right (thank you... again!): a conversation is needed to preserve the EntityManager through the consecutive calls to the listeners.


                        Now I've made a step forward, but I still receive an error:



                        03:21:41,883 SEVERE [event] Received 'java.lang.NullPointerException' when invoking action listener '#{testTableUpdate.updateCommandListener}' for component 'j_id52'
                        03:21:41,885 SEVERE [event] java.lang.NullPointerException
                             at org.jboss.seam.framework.Controller.debug(Controller.java:197)
                             at org.jboss.seam.framework.Home.updatedMessage(Home.java:54)
                             at org.jboss.seam.framework.EntityHome.update(EntityHome.java:65)
                             at it.scandix.assc.action.TestTableUpdateAct.updateCommandListener(TestTableUpdateAct.java:39)
                             ...
                             at it.scandix.assc.action.TestTableUpdateAct_$$_javassist_seam_11.updateCommandListener(TestTableUpdateAct_$$_javassist_seam_11.java)
                             ...
                             at java.lang.Thread.run(Thread.java:613)
                        



                        It seems that the call inside the .update() method of EntityHome fails. More in depth, I've seen that the failure is caused by a logging routine that doesn't receive the logger pointer and in turn calls a method on a null object (hence the NullPointerException).


                        Here is the call trace between classes:



                         
                        *** CLASS SperimentazioneHome (derives from EntityHome)
                        
                        *** CLASS EntityHome (derives from Home)
                           @Transactional
                           public String update()
                           {
                              joinTransaction();
                              getEntityManager().flush();
                        -->   updatedMessage();
                              raiseAfterTransactionSuccessEvent();
                              return "updated";
                           }
                        
                        *** CLASS Home (derives from Controller)
                          protected void updatedMessage()
                           {
                        -->   debug("updated entity #0 #1", getEntityClass().getName(), getId());
                              getStatusMessages().addFromResourceBundleOrDefault( INFO, getUpdatedMessageKey(), getUpdatedMessage().getExpressionString() );
                           }
                        
                        *** CLASS Controller
                        public abstract class Controller implements Serializable
                        {
                           @Logger Log log;
                        
                           ...
                           protected void debug(Object object, Object... params)
                           {
                        -->   log.debug(object, params);
                           }
                        }
                        



                        Any ideas on this?

                        • 9. Re: EntityHome: No transaction is in progress
                          asriel

                          Nevermind, I solved it. While experimenting with the code I decoupled the two listeners and created two separate classes; in this process I added a line inside the first listener that created a new EntityHome with the new command, rather than using the @In(create = true).




                          if (sperimentazioneHome == null) {
                             sperimentazioneHome = new SperimentazioneHome();
                          }
                          



                          VS


                          @In(create = true)
                          SperimentazioneHome sperimentazioneHome;
                          





                          It seems that SEAM doesn't like instances of components created with new...


                          Don't know why (if someone could explain me this, I'll be grateful), but at least now it works...


                          Thanks to everyone who dropped an answer.

                          • 10. Re: EntityHome: No transaction is in progress
                            giunad

                            May be because with new SperimentazioneHome there is no magic injection.


                            Injection brings transaction and all needed stuffs.


                            See you