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;quot;serverErrorPage&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;quot;&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.
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
[Reply]
Gift Sam Reply:
October 31st, 2009 at 12:00 pm
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!!
[Reply]
joman Reply:
November 13th, 2009 at 11:28 pm
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
[Reply]
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
… in web.xml? Any advantages of the methods described?
[Reply]
@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.
[Reply]
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
[Reply]
sorry this editor is displaying any tags
[Reply]
Kindly wrap your source code by following the link http://wordpress.org/extend/plugins/syntaxhighlighter-plus/other_notes/
[Reply]
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" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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!!
[Reply]
Thanks for u r help.its working now.
[Reply]
Gift Sam Reply:
December 9th, 2009 at 9:02 pm
You’re welcome!!
[Reply]
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
[Reply]
Gift Sam Reply:
January 17th, 2010 at 1:54 am
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.
[Reply]
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?
[Reply]
Gift Sam Reply:
February 23rd, 2010 at 10:41 pm
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.
[Reply]
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.
[Reply]
Gift Sam Reply:
February 24th, 2010 at 11:02 pm
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
[Reply]
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]
[Reply]
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
[Reply]
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
[Reply]
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!!
[Reply]
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?!
[Reply]
giftsam Reply:
March 25th, 2011 at 10:40 pm
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.
[Reply]