Exception handling guidelines to be followed while writing JSF Portlets

0 comments



Now a days everyone understands the need to have more pleasant error screen than a “Portlet is currently unavailable” displayed to user. Also error message and error stack trace is important information for the administrator for investigating the cause of problem.

JSF combined with JSR168/286 is a powerful framework for developing Portlets. But JSF framework doesn’t provide a cohesive support for handling uncaught exception arising in jsp/jsf and getter/setter methods.

This article analyses the pitfalls and suggests solution to overcome the above stated problem. The solution is tested in IBM WebSphere Portal 6.x

Handle unexpected exception in JSR JSF Portlet

Unexpected exceptions occurring during action phase could be caught and handled gracefully using navigation rule like below in faces-config.xml
<navigation-case>
<from-outcome>Error</from-outcome>
<to-view-id>/errors.jsp</to-view-id>
</navigation-case>

To handle the exception in jsf pages and getter/setter methods, developer has to come up with a solution. There are a number of approaches which could be followed for the same

a) General exception handling for servlet/jsp based applications
b) Extending FacePortlet
c) Writing custom lifecycle and NavigationHandler.

Will discuss these approaches in detail below:

General exception handling for servlet/jsp based applications

In this approach, declare either an error page definition or error-code definition in web.xml for uncaught exceptions. Multiple exception class with same or multiple error pages could be created for handling different class of exceptions. Any exceptions while rendering the jsp page will be handled by this declaration.
<error-page>
<exception-class>java.lang.Throwable</exception-class>
<location>/error/errors.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/errors.jsp</location>
</error-page>

By declaring the error.jsp as error page (set attribute isErrorPage=”true”), you will have access to implicit exception object. The exception message and stack trace are kept in request in the two attributes, javax.servlet.jsp.jspException and javax.servlet.error.exception respectively.

For reasons unknown, this doesn’t work in the Portlet environment.

First, it doesn’t forward to the error page. This problem could be fixed by setting the “errorPage” attribute of the jsp page to “errors.jsp”. Note this is in addition to the error page declaration in web.xml.

Secondly, error page renders a blank page. This could be overcome by injecting a forward page before error Page and modifying the web.xml and jsp to point to new forward page

// web.xml
<error-page>
<exception-class>java.lang.Throwable</exception-class>
<location>/error/errorForward.jsp</location>
</error-page>

// In Jsp
<%@page errorPage=”errorForward.jsp” %>

// errorForward.jsp

<%@page import="javax.faces.context.FacesContext"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" isErrorPage="true" pageEncoding="ISO-8859-1" %>

<%try {
FacesContext.getCurrentInstance().getExternalContext().
dispatch("/ErrorMessage.jsp");
}catch(Exception er){System.out.println("error message slash");er.printStackTrace();}
%>

Points to consider here

The errors.jsp should be a plain html without JSF view. JSF view tag is not supported if page is declared as error page while Subview tag renders an empty page. Subview could be used; unfortunately the action methods of the managed beans cannot be invoked from Subview.


Extending Faces Portlet class

In the normal JSF application, most sophisticated and complete approach could be to extending FacesServlet and catch any exception, log and forward to a custom error page. This is not a straight forward as FacesServlet is declared final in JSF specification. Another way is to delegate FacesServlet when an exception occurs. With the custom error page you can print the stack trace, list the values of session & request scoped managed-beans and email all of the data to the system admin for further debugging. This solution works (1.1_01) with latest JSF implementation. Previous releases (like 1.0) don't support this solution.

For further reading refer to http://www.jroller.com/mert/entry/handling_errors_with_an_errror by mert

This approach cannot be deployed in the Portal environment as the FacesServlet is not exposed. In Portal world, Generic Portlet is base class which incorporates all generic features required for a Portlet. FacesPortlet which extends GenericPortlet class is controller class for all JSF-JSR168 Portlet. The FacesPortlet could be extended to handle the unexpected exception and forward to custom error page. Don’t forget to register the new FacesPortlet in Portlet.xml.

Portlet

Custom FacesPortlet class which overrides doRender method to handle exception during rendering phase is listed below. Notice that exception is caught and stored in the session scope to be available in error page. See below the new FacePortlet class.

Portlet

In the custom error page, exception is retrieved from session, processed and appropriate error message is displayed to User. If required, this exception could be sent to the administrator in a mail.

Portlet

Writing custom life-cycle and Navigation Handler.

JSF framework is very flexible in accommodating custom developed components, handler etc.

A custom Lifecycle and NavigationHandler could be written to handle the uncaught exceptions. The Lifecycle is to be modified to skip phases till the invoke application phase when catching an exception. Modify the NavigationHandler to forward it to the preconfigured error page.

In combination with Portlet, this could be bit tricky. Since most of the error handling requirement could be achieved by extending faces Portlet. This approach should only be evaluated if a strong business case exists.

Note: These approaches were experimented using RAD 7.0 and WebSphere Portal 6.0.

Evaluating these options:

These options could be evaluated based on additional code, maintainability, easy of understanding and modification. Keeping these in mind and looking at available options, 2nd option which is extending the FacePortlet Class is the preferred one for most of the application. Key points which tilt decision in this favour are

  • Changes are very controlled as exception handling happens in one place.
  • Easy to maintain or perform modifications.
  • It is simple to code. Extending FacePortlet and overriding doRender method.
  • No error intermediate forward page
  • Doesn’t require any change in jsp/jsf ’s or in web.xml.
  • Could be easily extended to log the error in a separate log file or mail to administrator

1.1 Enhancements to 2nd option

1.1.1 Logging exception.

These exceptions could be easily logged into separate error file. As the access to request and response object is available, logs could be marked with user information and Portlet information.

1.1.2 Emailing exception to Administrator

In addition to logging errors to error file, an email could be sent to administrator detailing the exception.

1.1.3 More configurations

The Error page name and the Error message key need not be hard coded in the code. These items could be easily configured in Portlet.xml and referred back in customer FacePortlet and error page.

1.1.4 Manipulating Exceptions

In some scenario it will be appropriate to show meaningful message to user. This will help user to approach correct person and solve the issue quickly. For example, if user doesn’t have necessary permission to business resource say a file, throwing just permission denied exception won’t help user to solve the issue. Rather, catch these exception and throw more customized error message like “Dear User, You won’t have access to Annual Report.xls. If you require access to this file, please contact reporting team. Thanks”.

One way of doing it to create a custom exception like below and throw this custom exception instead of standard java exception.

Portlet

In the managed bean, catch the standard exception and throw the custom exception with the message.

Portlet

Modify the error page to retrieve this custom message like

Portlet

No comments:

Post a Comment

Recent Posts

Popular Posts

© 2011-2019 Web Portal Club