3 Replies Latest reply on Nov 8, 2011 12:29 PM by Jason Porter

    How to catch javax.faces exceptions with Seam Catch

    Markus Dahm Novice

      Hi,


      we're using the catch module in our web application on JBoss 7 and I quite satisfied so far, However there is a major problem with uncaught exceptions thrown by JSF.
      In particular we had the problem that the customer reported a problem with a


      org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.meyle.deva.model.Artikel#7]
              at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:487)
              at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:251)
              at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84)
      ....


        • 1. Re: How to catch javax.faces exceptions with Seam Catch
          Markus Dahm Novice

          There some text missing :-)



          But looking into the server log we found that the real reason was a OptimisticLockException thrown just before.
          As you can see it is wrapped within a JSF EvaluationException and that seems to be the problem.
          How can a catch the exceptions produced within a JSF call? Especially I'd like to handle the  OptimisticLockException to give the user a hint of what has happened.


          09:35:09,159 ERROR [org.jboss.as.ejb3.tx.CMTTxInterceptor] (http--0%3A0%3A0%3A0%3A0%3A0%3A0%3A0-80-8) javax.ejb.EJBTransactionRolledbackException
          
          09:35:09,159 ERROR [org.jboss.as.ejb3.tx.CMTTxInterceptor] (http--0%3A0%3A0%3A0%3A0%3A0%3A0%3A0-80-8) javax.ejb.EJBTransactionRolledbackException
          
          09:35:09,159 SCHWERWIEGEND [javax.enterprise.resource.webcontainer.jsf.application] (http--0%3A0%3A0%3A0%3A0%3A0%3A0%3A0-80-8) javax.ejb.EJBTransactionRolledbackException: javax.faces.el.EvaluationException: javax.ejb.EJBTransactionRolledbackException
                  at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
                  at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) [jsf-impl-2.0.6.jar:2.0.6-FCS]
                  at javax.faces.component.UICommand.broadcast(UICommand.java:315) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
                  at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
                  at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
                  at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) [jsf-impl-2.0.6.jar:2.0.6-FCS]
                  at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.0.6.jar:2.0.6-FCS]
                  at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.0.6.jar:2.0.6-FCS]
                  at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67) [weld-core-1.1.2.Final.jar:2011-07-26 15:02]
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:115) [prettyfaces-jsf2-3.2.0.jar:]
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:139) [jboss-as-web-7.0.2.Final.jar:7.0.2.Final]
                  at org.jboss.as.web.NamingValve.invoke(NamingValve.java:57) [jboss-as-web-7.0.2.Final.jar:7.0.2.Final]
                  at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:49) [jboss-as-jpa-7.0.2.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:154) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:667) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:952) [jbossweb-7.0.1.Final.jar:7.0.2.Final]
                  at java.lang.Thread.run(Thread.java:662) [:1.6.0_25]
          Caused by: javax.ejb.EJBTransactionRolledbackException
                  at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:133) [jboss-as-ejb3-7.0.2.Final.jar:7.0.2.Final]
                  at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:196) [jboss-as-ejb3-7.0.2.Final.jar:7.0.2.Final]
                  at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:286) [jboss-as-ejb3-7.0.2.Final.jar:7.0.2.Final]
                  at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:182) [jboss-as-ejb3-7.0.2.Final.jar:7.0.2.Final]
                  ... 104 more
          Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.meyle.deva.model.Artikel#7]
                  at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:487) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
                  at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:251) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
                  at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
                  at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:785) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
                  at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:770) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
                  at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:774) [hibernate-core-4.0.0.CR2.jar:4.0.0.CR2]
                  at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:860) [hibernate-entitymanager-4.0.0.CR2.jar:4.0.0.CR2]
                  ... 134 more


          • 2. Re: How to catch javax.faces exceptions with Seam Catch
            Markus Dahm Novice

            Our Exception handler class looks like this. As you can see there is a default handler for Throwable, thus everything should get caught and handled.




            @HandlesExceptions
            public class DevaExceptionHandler {
              @Inject
              private LogoutController _logoutController;
            
              @Inject
              private Logger _log;
            
              @Inject
              private FacesContext _facesContext;
            
              @Inject
              private Debug _debug;
            
              @PersistenceContext
              private EntityManager _entityManager;
            
              // Das ist zwar nicht ganz korrekt, aber ohne logout bleibt die Exception hängen
              public void lazyInitializationHandler(@Handles final CaughtException<LazyInitializationException> event) {
                _log.warn("Exception handled by lazyInitializationHandler", event.getException());
                redirect(DevAViewConfig.URL_VIEW_EXPIRED);
            
                setHandled(event);
                clearCache();
            
                _logoutController.logout();
              }
            
              public void transactionBugHandler(@Handles final CaughtException<IllegalStateException> event) {
                _log.warn("Exception handled by transactionBugHandler", event.getException());
            
                if (event.getException().getMessage().startsWith("BaseTransaction.checkTransactionState")) {
                  redirect(DevAViewConfig.URL_VIEW_EXPIRED);
                  setHandled(event);
                  clearCache();
                  _logoutController.logout();
                }
              }
            
              public void viewExpiredHandler(@Handles final CaughtException<ViewExpiredException> event) {
                _log.warn("Exception handled by viewExpiredHandler", event.getException());
                redirect(DevAViewConfig.URL_VIEW_EXPIRED);
            
                setHandled(event);
                clearCache();
            
                _logoutController.logout();
              }
            
              public void optimisticLockHandler(@Handles final CaughtException<OptimisticLockException> event) {
                _log.warn("Exception handled by optimisticLockHandler", event.getException());
                redirect(DevAViewConfig.URL_OPTIMISTIC_LOCK);
            
                clearCache();
                setHandled(event);
              }
            
              public void throwableHandler(@Handles final CaughtException<Throwable> event) {
                final long bugId = System.currentTimeMillis();
                final Throwable exception = event.getException();
                final String stackTrace = getStackTrace(exception);
            
                _log.error("Bug-Id:" + bugId + ": Error occured handled by throwableHandler", exception);
                _debug.setCurrentBugId(bugId);
                _debug.setStackTrace(stackTrace);
            
                redirect(DevAViewConfig.URL_ERROR);
            
                setHandled(event);
              }
            
              private String getStackTrace(final Throwable exception) {
                final StringWriter out = new StringWriter();
                ExceptionUtils.printRootCauseStackTrace(exception, new PrintWriter(out));
                final String stackTrace = out.toString();
                return stackTrace;
              }
            
              private void setHandled(final CaughtException<? extends Throwable> event) {
                event.unmute();
                event.handled();
              }
            
              private void clearCache() {
                try {
                  final Cache cache = _entityManager.getEntityManagerFactory().getCache();
                  if (cache != null) {
                    cache.evictAll();
                    _log.info("Cache cleared");
                  } else {
                    _log.warn("No cache configured!");
                  }
                } catch (final Throwable e) {
                  _log.warn("Could not clear cache", e);
                }
              }
            
              private void redirect(final String viewId) {
                try {
                  // facesContext.getExternalContext().responseReset();
                  _facesContext.getExternalContext().redirect(viewId);
                } catch (final IOException e) {
                  _log.warn("Redirect failed", e);
                }
              }
            }
            



            Cheers
               Markus

            • 3. Re: How to catch javax.faces exceptions with Seam Catch
              Jason Porter Master

              It looks like you're using AS 7.0.2, correct? Which version of Seam Faces are you using? If it's not one of the more current 3.1.0 Beta versions, please try that. Also debug CatchExceptionHandler, see if the exception goes through that, if it doesn't (even when using a more current version of Seam Faces) please create a JIRA and attach a simple war (or arquillian test) that demonstrates this error. Thanks!