0 Replies Latest reply on Aug 30, 2006 6:27 PM by gverner

    Problem with myfaces-1.1.3 exceptions not returned to Browse

    gverner

      I have a problem where under some conditions, uncaught application exceptions are not returned to the browser when using myfaces-1.1.3. To best describe the problem I have created a simple example.

      The example is a page with a dataTable that has an slink on each row. When this link is pressed it calls a method that throws a RuntimeException. I copied the exception-test into the Seam Hibernate Example application which uses myfaces-1.1.1 and everything works as expected, meaning I receive an exception page after pressing the buttons.

      Then I upgrade the Hibernate example to myfaces-1.1.3 by adding myfaces-impl-1.1.3.jar to the war and setting myFacesLifecycleBug=false in components.xml. After which pressing the slink button on a table row doesn?t return the exception page, it only logs the error.

      Now a second more serious problem occurs if you are using Jbpm. After pressing the button on the table row a couple of times you receive the error (java.lang.IllegalStateException: No active conversation context). What makes this more serious is that it is usually impossible to get the application to recover no matter what page you go to, without closing your session. To test this with the Hibernate example add Jpbm by coping the jbpm.jar into the war file and enabing Jbpm in components.xml. no need to create any page flows.

      What follows is the example code with more details on making the changes to the Seam Hibernate example.

      Install the test page into the Seam Hibernate Example

      Create exception-test.xhtml in examples/hibernate/view
      exception-test.xhtml

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib">
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
      <title>Conversation Test</title>
      <link href="css/screen.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
      
      <div id="document">
      <div id="header">
      <div id="title">Exception Test</div>
      <div id="status"></div>
      <div id="pagetitle" styleClass="pagetitle"><ui:insert name="pagetitle">Exception Test</ui:insert></div>
      </div>
      <div id="container">
      <div id="sidebar"><ui:insert name="sidebar">
      </ui:insert></div>
      
      <div id="content"><ui:insert name="content">
       <h:form>
       <h:dataTable value="#{exceptionTestList}" var="exp">
       <h:column>
       <f:facet name="header">Name</f:facet>#{exp.name}</h:column>
       <h:column>
       <f:facet name="header">Value</f:facet>#{exp.value}</h:column>
       <h:column>
       <s:link id="tdlink" action="#{exceptionTest.throwException}" value="Throw Exception in phase RENDER_RESPONSE(6) BeforeRender">
       </s:link>
       </h:column>
       </h:dataTable>
       <h:commandButton id="tx1" action="#{exceptionTest.throwException}" value="Throw Exception in phase INVOKE_APPLICATION(5)" styleClass="button" />
       </h:form>
      </ui:insert></div>
      </div>
      <div id="footer">Created with JBoss Hibernate, Seam, MyFaces, and Facelets</div>
      </div>
      </body>
      </html>
      

      Create exceptionTestAction.java in examples\hibernate\src\org\jboss\seam\example\hibernate
      exceptionTestAction.java
      package org.jboss.seam.example.hibernate;
      
      import java.io.Serializable;
      import java.util.ArrayList;
      import java.util.List;
      
      import javax.interceptor.Interceptors;
      
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.Factory;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Scope;
      import org.jboss.seam.annotations.datamodel.DataModel;
      import org.jboss.seam.annotations.datamodel.DataModelSelection;
      import org.jboss.seam.ejb.SeamInterceptor;
      
      @Name("exceptionTest")
      @Scope(ScopeType.CONVERSATION)
      @Interceptors(SeamInterceptor.class)
      public class ExceptionTestAction implements Serializable {
       private static final long serialVersionUID = 1730978625993910679L;
      
       @DataModel
       private List<ExceptionTestItem> exceptionTestList;
      
       @DataModelSelection("exceptionTestList")
       private ExceptionTestItem selectedExceptionTest;
      
       @Factory("exceptionTestList")
       public void createList() {
       // create some data for the screen
       exceptionTestList = new ArrayList<ExceptionTestItem>();
       exceptionTestList.add(new ExceptionTestItem("1", "one"));
       exceptionTestList.add(new ExceptionTestItem("2", "two"));
       }
      
       /**
       * Throw Exception to see how does Seam and myFaces handle it.
       *
       * @throws Exception
       *
       */
       public void throwException() {
       if (1 == 1)
       throw new RuntimeException("Test Throw Exception from ExceptionTextAction.throwException");
       }
      }
      

      Create exceptionTestItem.java in examples\hibernate\src\org\jboss\seam\example\hibernate
      exceptionTest.java
      package org.jboss.seam.example.hibernate;
      
      public class ExceptionTestItem {
       private String name;
       private String value;
       public ExceptionTestItem(String name, String value) {
       this.name = name;
       this.value = value;
       }
       public String getName() {
       return name;
       }
       public void setName(String name) {
       this.name = name;
       }
       public String getValue() {
       return value;
       }
       public void setValue(String value) {
       this.value = value;
       }
      }
      

      Deploy the Seam Hibernate example and run the new page http://localhost:8080/seam-hibernate/exception-test.jsf. Try the datatable button ?Throw Exception in phase RENDER_RESPONSE(6) BeforeRender? a few times. Your still running myfaces-1.1.1 and should receive an Exception Page each time. Try the command button "(Throw Exception in phase INVOKE_APPLICATION(5) )", This button will display the exceptions page and works correctly with both versions of myfaces but is handled during a different phase.

      Upgrade the Hibernate example to use myfaces-1.1.3
      Add myfaces-impl-1.1.3.jar to the jboss-seam-hibernate.war file. I did this by modifying the examples/hibernate/build.xml file as follows.

      Add a zipfileset, this should be placed in the file near the other zipfilesets.
      <!-- Myfaces 1.1.3 -->
       <zipfileset id="example.war.webinf.lib.myfaces"
       prefix="WEB-INF/lib"
       dir="../../lib">
       <include name="myfaces-impl*.jar"/>
       </zipfileset>
      

      Find the following section and add the refid for example.war.webinf.lib.myfaces.
       <jar destfile="${build.dir}/${example.name}.war">
       <zipfileset refid="example.war.docroot"/>
       <zipfileset refid="example.war.webinf.lib"/>
       <zipfileset refid="example.war.webinf.lib.myfaces"/>
       <zipfileset refid="example.war.webinf.lib.extra"/>
       <zipfileset refid="example.tomcat.seam.jar"/>
       <zipfileset dir="${build.dir}/resources">
       <include name="WEB-INF/**/*.*"/>
       </zipfileset>
       <zipfileset dir="${build.dir}" prefix="WEB-INF/lib">
       <include name="${example.name}.jar"/>
       </zipfileset>
       </jar>
      

      Modify examples\hibernate\resources\WEB-INF\components.xml and set myFacesLifecycleBug=false.
       <component name="org.jboss.seam.core.init">
       <property name="myFacesLifecycleBug">false</property>
       <property name="debug">true</property>
       </component>
      


      Deploy the Seam Hibernate example again and run the page http://localhost:8080/seam-hibernate/exception-test.jsf. Try the datatable button ?Throw Exception in phase RENDER_RESPONSE(6) BeforeRender? a few times. Your now running myfaces-1.1.3 and will NOT receive an Exception Page each time but it will be logged. The command button "(Throw Exception in phase INVOKE_APPLICATION(5) ), will work correctly and display the exception page.


      Enable Jbpm in the Hibernate example
      Add jbpm-3.1.1.jar to the jboss-seam-hibernate.war file. I did this by modifying the examples/hibernate/build.xml file, adding the line to the zipfileset added above.
      <!-- Myfaces 1.1.3 -->
       <zipfileset id="example.war.webinf.lib.myfaces"
       prefix="WEB-INF/lib"
       dir="../../lib">
       <include name="myfaces-impl*.jar"/>
       <include name="jbpm*.jar"/>
       </zipfileset>
      


      To enable jbpm add the following section to examples\hibernate\resources\WEB-INF\components.xml . Note no page flows are required.
       <component class="org.jboss.seam.core.Jbpm">
       </component>
      


      Deploy the Seam Hibernate example again and run the page http://localhost:8080/seam-hibernate/exception-test.jsf. Try the datatable button ?Throw Exception in phase RENDER_RESPONSE(6) BeforeRender? a few times. Your now have Jbpm enable and will receive java.lang.IllegalStateException: No active conversation context.

      any help will be appreciated
      Thanks
      Glenn