Tech Brainwave

A Road Map for Innovative Technologies

Exception Handling in JSF

Posted by giftsam Posted on Sep - 21 - 2009

Introduction:
We the developers, exert much effort to write perfect code. Regrettably, some times we may met with an exception or error conditions. While surfing the net, So many questions pointed out, how to handle the exceptions in JSF by showing a custom page instead of Java Stack trace. This article is consecrated for the peoples who wants to handle the exceptions perfectly in their application.

Other frameworks like Struts, provides a better way to handle exceptions by configuring <global-exceptions> in struts-config.xml. Like Struts, JSF 1.2 and below does not provide the notion of a global exception. Now JSF 2.0 have the features of handling exceptions. But this article is all about handling exceptions in JSF1.2.

Better way to handle exception:
Surrounding all the Java beans by try/catch can handle all kinds of exceptions this technique is called checked exceptions. but no coders wants all of their java bean methods to be surrounded by try/catch. Instead there is a alternate technique to handle exceptions called Unchecked exceptions. You want to implement any one of the two approaches, if not a default handler is found and  process the exception, resulting the web page in a stack trace.

Unchecked Exceptions:
The goal of this technique is to give you control to catch all the exceptions and let you navigate to an appropriate custom JSP page to generate the error response. To invoke this technique, create a new class that implements javax.faces.event.ActionListener interface.

Note: It is important that your class is a subclass of this class.

public class ExceptionHandlingActionListener extends ActionListenerImpl

implements ActionListener{..}

Then, implement the public void method handleBeanAction(ActionEvent event). This method should invoke the “normal” inherited processAction(ActionEvent event) method, which catches any exceptions and return the navigational string “exceptionOccured”.


public void handleBeanAction(ActionEvent event)
{
try
{
super.processAction(event);
}
catch (Exception exception)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
Application application = facesContext.getApplication();
NavigationHandler navigationHandler =  application.getNavigationHandler();
navigationHandler.handleNavigation( facesContext, null,“exceptionOccured”);
facesContext.renderResponse();
}
}

So by using the above method, when an exception occured, it will be caught in the catch block and the error occured page will be navigated to a custom jsp page.

Configration in faces-config:

<application>
<action-listener>
com.mypackagename.ExceptionHandlingActionListener
</action-listener>
</application>

Then implement the navigation rule ,

<navigation-rule>
<navigation-case>
<from-outcome>
exceptionCaught
</from-outcome>
<to-view-id>/mypages/exceptionPage.jsp</to-view-id>
</navigation-case>
</navigation-rule>

Then create a custom exception page in JSP (exceptionPage.jsp). So that when the navigation string “exceptionCaught” occured, the page will be navigated to the desired custom JSP page.

HTTP Status Code Exceptions:
In order to handle HTTP Status code errors like 404 and 500, configure in your web.xml

<error-page>
<error-code>404</error-code>
<location>/mypages/404.html</location>
</error-page>

Likewise State 500 in the error code, to handle HTTP Status code error 500

Note:

In this handling the response page must be an HTML page. So that we can avoid reentrant error in processing the response.

Delegating FacesServlet:
An other way to handle exception is to delegating FacesServlet. To say simple, wrapping the FacesServlet by implementing our own custom FacesServlet. Delegating FacesServlet will work only for the JSF1.1.01 and above. Thanks for the resources provided in the site jroller.

FacesServletWrapper.java


package com.mypackage;
import java.io.IOException;
import javax.faces.webapp.FacesServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FacesServletWrapper extends HttpServlet
{
private FacesServlet facesServletDelegate;
private static final String ERROR_PAGE = &amp;amp;quot;serverErrorPage&amp;amp;quot;;
private String serverErrorPage;
public void init(ServletConfig servletConfig) throws ServletException
{
facesServletDelegate= new FacesServlet();
facesServletDelegate.init(servletConfig);
serverErrorPage = servletConfig.getInitParameter(ERROR_PAGE);
}
public void destroy()
{
facesServletDelegate.destroy();
}
public ServletConfig getServletConfig()
{
return facesServletDelegate.getServletConfig();
}
public String getServletInfo()
{
return facesServletDelegate.getServletInfo();
}
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
try
{
facesServletDelegate.service(request,response);
}
catch(Throwable e)
{
redirectToServerErrorPage((HttpServletRequest) request,
(HttpServletResponse) response);
}
}
private void redirectToServerErrorPage(HttpServletRequest request,
HttpServletResponse response) throws IOException
{
if (!serverErrorPage.equals(&amp;amp;quot;&amp;amp;quot;))
{
response.sendRedirect(request.getContextPath() + serverErrorPage);
}
}

Configuration in web.xml:

Note: As stated below, replace the FacesServlet servlet description with the FacesServletWrapper

<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>com.mypackage.FacesServletWrapper</servlet-class>
<init-param>
<param-name>serverErrorPage</param-name>
<param-value>/faces/mypages/serverErrorPage.jsp</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Once replacing the FacesServlet servlet description with the FacesServletWrapper, dont forget to specify the servlet-mapping description as stated below

<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>

The preceding code, wrapping the FacesServlet works perfectly with Tomcat. But if anyone uses Glassfish(Sun Java System Application Server). You may get an exception some thing like the below.

java.lang.RuntimeException:  Exception in handleBeforeEvent.

If you met with the same kind of exception. Here is the solution to resolve this error, implement servlet interface instead of extending HttpServlet. So I hope this article clearly explains, the several ways to handle exceptions in JSF. If you find this article is quite useful, Dont forget to share with me by your valuable comments. Have a joyous code day.

Categories: Java, Java EE, JSF, Servlets

23 Responses so far.

  1. joman says:

    Hi,
    we use Jboss 5.1.0GA and everything works fine apart from the “Delegating FacesServlet”. I receive the following error after executing the init-Method
    facesServletDelegate.init(servletConfig);
    of FacesServletWrapper.java

    java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
    at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
    at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)

    Any help appreciated.

    Thanx

    Thumb up 1 Thumb down 0

    [Reply]

    Gift Sam Reply:

    To avoid this exception you need to configure in your web.xml like the below,
    [sourcecode language="css"]
    <!– Standard FacesServlet–>
    <servlet>
    <servlet-name>FacesServlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <!– CustomFacesServlet–>
    <servlet>
    <servlet-name>FacesServletWrapper</servlet-name>
    <servlet-class>com.mypackage.FacesServletWrapper</servlet-class>
    <init-param>
    <param-name>serverErrorPage</param-name>
    <param-value>/faces/mypages/serverErrorPage.jsp</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
    </servlet>[/sourcecode]
    In the above configuration the loading order of servlets is specified. Servlets with lower values are loaded before servlets with higher values. Also ensure that you had implemented servlet interface instead of extending HttpServlet in FacesServletWrapper servlet. Hope this one helps!!

    Thumb up 1 Thumb down 0

    [Reply]

    joman Reply:

    Hi Gift Sam,
    thank you very much for your answer. In the meantime I solved my problem with a JSP-Errorhandler, web.xml:

    java.lang.Exception
    /pages/error/fehlerglobal.jsp

    Your solutions works, thank you very much.

    cu Josef

    Thumb up 0 Thumb down 0

    [Reply]

  2. DK says:

    Hi,

    I’m developing error handling with JSF 1.2. What I don’t understand is the reasoning behind developing a custom ActionListener or delegating servlet. Why not just do

    
      java.lang.Throwable
      /errorPage.jsp
    
    

    … in web.xml? Any advantages of the methods described?

    Thumb up 0 Thumb down 0

    [Reply]

  3. Gift Sam says:

    @DK
    Hi DK,

    A very nice question and thanks for your comments!! I reckon you are using Servlet Error Page Mechanism inorder to handle your exception. If not please brief me, what approach you are following to handle the exceptions. Also kindly have a look on the below link

    http://wiki.apache.org/myfaces/Handling_Server_Errors
    http://softwareengineeringsolutions.com/thoughts/frameworks/JSF.Techniques-Error.Handling.htm

    As stated there, that’s not an elegant solution and have some problems while you are using f:subview tag instead of f:view tag.

    Thumb up 0 Thumb down 0

    [Reply]

  4. Ram says:

    hi,
    i am using the facelets.I cant implement both of these solutions.i configured as you told but it is no navigating to errorpage.

    this is my web.xml

    javax.faces.STATE_SAVING_METHOD
    server

    com.icesoft.faces.uploadDirectory
    upload

    com.icesoft.faces.uploadMaxFileSize
    4048576

    javax.faces.DEFAULT_SUFFIX
    .jspx

    com.icesoft.faces.concurrentDOMViews
    true

    com.icesoft.faces.util.event.servlet.ContextEventRepeater

    Faces Servlet
    javax.faces.webapp.FacesServlet
    1

    FacesServletWrapper
    com.synv.managedbean.FacesServletWrapper

    serverErrorPage
    /main/errorPage.jsp

    2

    Persistent Faces Servlet
    com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet
    0

    Blocking Servlet
    com.icesoft.faces.webapp.xmlhttp.BlockingServlet
    0

    uploadServlet
    com.icesoft.faces.component.inputfile.FileUploadServlet
    0

    FacesServletWrapper
    /*

    Persistent Faces Servlet
    /*

    Persistent Faces Servlet
    *.jspx

    Persistent Faces Servlet
    *.iface

    Persistent Faces Servlet
    /xmlhttp/*

    Blocking Servlet
    /block/*

    uploadServlet
    /uploadHtml

    imageServlet
    com.synv.managedbean.ImageRenderer

    imageServlet
    /imagerenderer

    graphServlet
    com.synv.managedbean.GraphRenderer

    graphServlet
    /graphrenderer

    timerServlet
    com.synv.managedbean.TimerStratupServlet
    0

    timerServlet
    /timerServletr

    index.jsp

    BASIC

    15

    when actually that handleBeanAction() will be invoked.its not getting invoked.
    plz help

    thanks

    Thumb up 0 Thumb down 0

    [Reply]

  5. Ram says:

    sorry this editor is displaying any tags

    Thumb up 0 Thumb down 0

    [Reply]

  6. Gift Sam says:

    This is how I construct my web.xml for a facelet project(With Richfaces).

    [sourcecode language="css"]
    <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&gt;

    <context-param>
    <param-name>com.sun.faces.verifyObjects</param-name>
    <param-value>true</param-value>
    </context-param>
    <context-param>
    <param-name>com.sun.faces.validateXml</param-name>
    <param-value>true</param-value>
    </context-param>
    <context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xhtml</param-value>
    </context-param>
    <context-param>
    <param-name>facelets.DEVELOPMENT</param-name>
    <param-value>false</param-value>
    </context-param>
    <context-param>
    <param-name>facelets.SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
    </context-param>
    <!– Richfaces Configuration–>
    <context-param>
    <param-name>org.richfaces.SKIN</param-name>
    <param-value>wine</param-value>
    </context-param>
    <context-param>
    <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
    <param-value>com.sun.facelets.FaceletViewHandler</param-value>
    </context-param>
    <filter>
    <display-name>RichFaces Filter</display-name>
    <filter-name>richfaces</filter-name>
    <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>richfaces</filter-name>
    <servlet-name>FacesServletWrapper</servlet-name>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <!– Standard FacesServlet–>
    <servlet>
    <servlet-name>FacesServlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <!– CustomFacesServlet–>
    <servlet>
    <servlet-name>FacesServletWrapper</servlet-name>
    <servlet-class>com.mypackage.FacesServletWrapper</servlet-class>
    <init-param>
    <param-name>serverErrorPage</param-name>
    <param-value>/faces/mypages/serverErrorPage.jsp</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>FacesServletWrapper</servlet-name>
    <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <session-config>
    <session-timeout>
    30
    </session-timeout>
    </session-config>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    </web-app>
    [/sourcecode]
    I just stated the servlet loading order and also have a look at the servlet mapping and Filter mapping, I had mapped with the “FacesServletWrapper” instead of “FacesServlet”. I hope this one helps!!

    Thumb up 0 Thumb down 0

    [Reply]

  7. ram says:

    Thanks for u r help.its working now.

    Thumb up 0 Thumb down 0

    [Reply]

    Gift Sam Reply:

    You’re welcome!!

    Thumb up 0 Thumb down 0

    [Reply]

  8. thang says:

    Hi,

    i use tomcat 6.0 and get the following exception after executing the init method:
    java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
    at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:263)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:142)
    at de.dominic.weblib.jsf.error.FacesServletWrapper.init(FacesServletWrapper.java:40).
    Here ist mein web configuration:

    facesDummy
    javax.faces.webapp.FacesServlet
    1

    faces
    de.dominic.weblib.jsf.error.FacesServletWrapper

    serverErrorPage
    /faces/pages/error.jsf

    2

    faces
    *.jsf

    Thanks in advance for your help

    Thumb up 0 Thumb down 0

    [Reply]

    Gift Sam Reply:

    Kindly have a look at the #2 comment. In that I had specified the steps to configure the web.xml inorder to avoid this error.

    Thumb up 0 Thumb down 0

    [Reply]

  9. marc says:

    I was just looking over this solution and thought I’d give it a shot within Primefaces. I’ve been looking for a solution to handle exceptions thrown in backingbean methods from ajax requests. It seems that you cannot navigate when it’s from an ajax call, so it didn’t work for me. Any ideas there?

    Thumb up 0 Thumb down 0

    [Reply]

    Gift Sam Reply:

    Hi marc,
    Thanks for your comments!!We can handle the ajax exception. Kindly brief me, whether you are using a h:outputlink or using a h:commandlink with f:subview to render your JSF page?? This code should work for the ajax request. Either use one of the following two ways

    1.If you want to involve the server-side validators and navigate to the next page only if the Validation phase is passed successfully, you can replace h:commandButton with a4j:commandButton and point to the action method that navigates to the next page. If Validation process fails, the partial page update will occur and you will see an error message. Otherwize, the application proceeds to the next page. Make sure, you define redirect tag option for the navigation rule to avoid memory leaks.
    2. other wise use a4j:include component. This is a typical scenario for Wizard like behavior. The new content is rendered inside the a4j:include area.

    Please come back to me, Still if you cannot resolve the problem.

    Thumb up 0 Thumb down 0

    [Reply]

  10. marc says:

    I’m using the Primefaces p:commandButton async=”false” update”xxx” action=”backingbean.method”>

    When the button is hit it calls the action method and does a partialpagesubmit. Even though this action method returns a string for navigation they have short circuited the lifecycle so navigation doesn’t happen. This is fine if the action method is successful, but if something goes wrong and runtime exceptions occur I want to kick them back to the error page and eventually the main menu.

    The only solution I found that works is to hide a button on the page that navigates to the error page. In my action method I catch the exceptions and then set an http status of 500. The p:commandButton has an onerror that catches the http status and then fires a javascript function that I do a button.click on the hidden button to go to the error page. It seems like a bit of a hack and I have to code in all the action methods for it. I was hoping to find a cleaner solution.

    Thumb up 0 Thumb down 0

    [Reply]

    Gift Sam Reply:

    Hi Marc,
    I reckon this can solve your problem. If you specified Async means, ajax requests without queue. Inorder to make non-ajax requests with button, set ajax to false. I had given you a sample code below. Hope it would be useful to you.

    [sourcecode language="css"]
    <p:commandButton id="sampButtonId" value="#{messages['modifier.alert']}" action="#{SampleBean.navigateAction}" ajax="false" />
    [/sourcecode]
    Also kindly have a look on the forum, http://primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=996
    Thanks – Gift Sam

    Thumb up 0 Thumb down 0

    [Reply]

  11. Mariano says:

    I’m having the same problem Ram used to have. I’m currently using richfaces. The custom servlet is being initialized since I added a log line in the init() method and it’s being printed in the log:

    15:03:33,366 INFO [ExceptionHandlerServlet] ——> init!!

    However the app does not seem to be using it but the dummy servlet.

    This is what I have:

    [sourcecode language="css"]

    <filter>
    <display-name>Ajax4jsf Filter</display-name>
    <filter-name>ajax4jsf</filter-name>
    <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>ajax4jsf</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <context-param>
    <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
    <param-value>com.sun.facelets.FaceletViewHandler</param-value>
    </context-param>
    <servlet>
    <servlet-name>Dummy Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>path.ExceptionHandlerServlet</servlet-class>
    <init-param>
    <param-name>errorPage</param-name>
    <param-value>/pages/error/generalError.jsf</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>


    [/sourcecode]

    Thumb up 0 Thumb down 0

    [Reply]

  12. Leo says:

    Hi Sam,

    I’ve tried to use the first example in my application but it didn’t work.

    In an example application all works fine, but the method handleBeanAction() isn’t being called when the exception occur in my real application.

    I’m using facelets in my application and I didn’t use it in the example. Do you think that it has something with the problem i’m facing?

    Thanks in advance and sorry for the bad English! =D

    Thumb up 0 Thumb down 0

    [Reply]

  13. Tommaso says:

    Hi Sam,

    same problem: the first example does not work at all.

    I’m working with IBM RAD. When trying to deploy th application I get an error (wrong configuration).

    E com.ibm.ws.webcontainer.webapp.WebApp notifyServletContextCreated SRVE0283E: Eccezione rilevata in fase di inizializzazione del contesto: {0}
    com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! null
    at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:213)
    at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:196)
    at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1678)

    I use Richfaces.

    This is a part of my faces config. If I remove the action lister the application starts properly.

    my.jsf.actionlistener.ExceptionHandlingActionListener
    com.sun.facelets.FaceletViewHandler

    it
    it

    my.messageresource.language.LanguageResources

    Any idea?

    Many thanks

    Thumb up 1 Thumb down 0

    [Reply]

  14. giftsam says:

    I guess you got this exception since the element is located at the wrong position. It should be within the application element like the below,
    application
    action-listener
    com.mypackagename.ExceptionHandlingActionListener
    /action-listener
    /application
    Still if you got this problem, Please come back to me. I will try my best to solve this problem. Also I would like to tell you that I had implemented this code in the jboss application and Sun glassfish server. But I had never tried this in IBM RAD. Thanks!!

    Thumb up 0 Thumb down 0

    [Reply]

  15. hala says:

    Hi Sam, the handleBeanAction is not called also in my code:
    public class OBSExceptionHandler extends ActionListenerImpl implements
    ActionListener {

    public void handleBeanAction(ActionEvent event) {

    although I defined the action-listener inside the application tag.
    I think there is something missing, how should this method be called, while it’s normal action listener, shouldn’t it be used inside a component to be called?

    how to cal it dynamically and with all actions?!

    Thumb up 0 Thumb down 0

    [Reply]

    giftsam Reply:

    Hala,
    Specify the JSF version and the application sever you use, I have tested this on JSF1.2 and it works both in Tomcat and Glassfish server.

    Thumb up 0 Thumb down 0

    [Reply]