3 Replies Latest reply on Apr 6, 2010 7:46 PM by Jonathan Tougas

    endless loop in exception handling during commit

    Denis Forveille Novice

      We have problems trying to handle correctly exceptions that occur during tx commit, e.g.
      This occurs ONLY when an exception is raised during the commit while in a long running conversation. When not in a long running conversation everything works fine


      The factory that creates a list of Entities displayed in the page:


      @Factory(value = "listeDevises", scope = ScopeType.CONVERSATION)
       public List<Devise> obtenirListeDevises() {
        Query query = em.createQuery("select d from Devise d order by d.codeDevise ");
        return query.getResultList();
       }



      In pages.xml :


      <exception>
          <end-conversation/>
          <redirect view-id="/erreur_exception.xhtml" />
      </exception>
      <page view-id="*" >
         <navigation>
            <rule if-outcome="modifierDevises">
               <begin-conversation/>
               <redirect view-id="/pagesAdmin/devises.xhtml" />
            </rule>
         </navigation>
      </page>
      
      <page view-id="/pages/devises.xhtml"
                conversation-required="true" 
                no-conversation-view-id="/pages/accueil.xhtml">
      </page>
      



      Extract from the facelets page :



      <rich:dataTable id="rdt_devises" value="#{listeDevises}" var="item">
         <rich:column>
            #{item.codeDevise}
         </rich:column>
      ...
         <rich:column>
            <h:inputText id="ii_montantConversion" value="#{item.montantConversion}"  required="true" maxlength="11" />
         </rich:column>
      ...
         <h:commandButton id="cb_modifier" value="Modifier" action="#{devisesCtrl.modifier}" />
      



      The SFSB :


      @Name("devisesCtrl")
      @Stateful
      public class DevisesControleurImpl extends AbstractControleur implements DevisesControleur {
      ...
         @End
          public String modifier() {
             facesMessages.addFromResourceBundle(StatusMessage.Severity.INFO, "modifier.ok", new Object[] {});
             return Constantes.OUTCOME_MODIFIER_DEVISES;
          }
      


      The scenario:


      - 2 users display the xhtml page by using the "modifierDevises" outcome. A long running conversation is started thanks to the "begin-conversation" tag in pages.xml


      - the first user modifies a value, clicks on the button that executes the modifier method, the object is updated in the database. perfect.


      - the second user modifies the same value on the page, clicks on the button, execute the modifier method but receives a OptimisticLockingException exception during the commit (this is very important! ). Seams sees that the exception is handled thanks to the clause in page.xml and initiates a redirect to the "erreur_exception.xhtml" page.


      - at this point the long running conversation is still active, and dirty objects are still present in the context


      - during the processing of the "erreur_exception.xhtml" page, during the RESTORE_VIEW phase, hibernate detects that there are dirty objects, attempt to flush them and hits (again) the same OptimisticLockingException that triggers the exception handling that tries to redirect to the "erreur_exception.xhtml" page etc...causing the endless loop


      Note that:
      - if we add a em.flush() before the end of the method, it works!. The exception is thrown during the flushand seam is able to handle it as it does not occur durin the commit, the SeamPhaseListener.afterPhase method(... The user is redirect to the erreur_exception.xhtml.page


      - if we are not in a long running conversation, it works too!


      Q:


      - are other people seen the same behaviour?


      - what is the correct way to handle exceptions (like OptimisticLockingException) that arise during the transaction commit?