Insights into Java Server Faces

2009/07/20

using a custom Lifecycle implementation to handle Exceptions in JSF 1.2

Filed under: JSF — Tags: — Hanspeter @ 22:48

Real application need to handle unexpected Exceptions in a save way by e.g. render an error page and behave according to the type of exception (some exceptions might allow to show a message and continue with the application, other might need to terminate the session). JSF 2.0 will provide exception handling support, but you can also handle exceptions before JSF 2.0 using a custom lifecycle as shown below.

JSF processes all requests in 6 phases along a defined lifecycle – exceptions might be thrown from any of these phases. With a custom Lifecycle we can wrap the standard Lifecycle to intercept these Exceptions and handle them as wanted.

One method to add a custom Lifecycle implementation is to provide a custom LifecycleFactory wrapping the standard LifecycleFactory(Impl) which will add a custom lifecycle that wraps the standard Lifecycle(Impl). That way we only have to add our additional logic and don’t have to implement the factory and lifecycle from scratch.

In the CustomLifecycleFactory we use again the delegating factory constructor (see previous post about FactoryFinder and delegating constructor) to instantiate the factory and get a reference of the standard LifecyleFactory from the JSF runtime. In the factory constructor we do (see the numbered comments):

  1. get an instance of the default lifecycle to pass it to our InterceptingLifecycle.
  2. register an instance of our lifecycle within the standard LifecycleFactory.
  package ch.dueni.jsf12.lifecycle;

  import java.util.Iterator;

  import javax.faces.lifecycle.Lifecycle;
  import javax.faces.lifecycle.LifecycleFactory;
  import javax.faces.webapp.FacesServlet;

  /**
   * <code>CustomLifecycleFactory</code> enhances the standard JSF
   * <code>LifecycleFactory</code> with additional Lifecyle implementations that
   * can be activated with the <code>FacesServlet</code> init-param
   * {@value FacesServlet#LIFECYCLE_ID_ATTR}.
   * <p>
   * You can activate s specific Lifecycle implementation by configuring this
   * lifecycle id to be used by FacesServlet:
   * </p>
   * <ul>
   * <li>{@value #INTERCEPTING_LIFECYCLE_ID}</li>
   * </ul>
   *
   */
  public class CustomLifecycleFactory extends LifecycleFactory {

    /**
     * The id of the intercepting lifecycle.
     */
    public static final String INTERCEPTING_LIFECYCLE_ID = "InterceptingLifecycle";

    /**
     * LifecycleFactory delegate.
     */
    private LifecycleFactory delegate;

    /**
     * Delegate injecting constructor.
     *
     * @param defaultFactory
     *          the injected delegate LifecycleFactory.
     */
    public CustomLifecycleFactory(LifecycleFactory defaultFactory) {
      delegate = defaultFactory;

      // 1. get default lifecycle to be wrapped by our lifecycle
      Lifecycle defaultLifecycle = delegate.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

      // 2. register intercepting lifecycle implementation.
      addLifecycle(INTERCEPTING_LIFECYCLE_ID, new InterceptingLifecycle(defaultLifecycle));
    }

    @Override
    public void addLifecycle(String lifecycleId, Lifecycle lifecycle) {
      delegate.addLifecycle(lifecycleId, lifecycle);
    }

    @Override
    public Lifecycle getLifecycle(String lifecycleId) {
      return delegate.getLifecycle(lifecycleId);
    }

    @Override
    public Iterator<String> getLifecycleIds() {
      return delegate.getLifecycleIds();
    }

  }

And here is how to let JSF use the custom LifecycleFactory – configure it in a faces-config.xml:

 <factory>
   <lifecycle-factory>ch.dueni.jsf12.lifecycle.CustomLifecycleFactory</lifecycle-factory>
 </factory>

The implementation of the InterceptingLifecycle is also pretty simple (see below). Well, it’s not doing much beside intercept and print exceptions thrown from Lifecycle.execute() or Lifecycle.render(). But looking at this we have one central point where we can attach exception handling logic – within a custom lifecycle implementation. I will show a possible implementation in later post, but let’s finish this first.

  package ch.dueni.jsf12.lifecycle;

  import javax.faces.FacesException;
  import javax.faces.context.FacesContext;
  import javax.faces.event.PhaseListener;
  import javax.faces.lifecycle.Lifecycle;

  public class InterceptingLifecycle extends Lifecycle {

    private Lifecycle wrapped;

    public InterceptingLifecycle(Lifecycle standardLifecycle) {
      wrapped = standardLifecycle;
    }

    Lifecycle getWrapped() {
      return wrapped;
    }

    @Override
    public void addPhaseListener(PhaseListener listener) {
      System.out.println("addPhaseListener(" + listener + ")");
      getWrapped().addPhaseListener(listener);
    }

    @Override
    public void execute(FacesContext context) throws FacesException {
      try {
        System.out.println("execute(...)");
        getWrapped().execute(context);
      } catch (FacesException intercepted) {
        System.out.println("===>>> Intercepted Throwable from execute()");
        intercepted.printStackTrace();
        FacesContext.getCurrentInstance().renderResponse();
        throw intercepted;
      }
    }

    @Override
    public PhaseListener[] getPhaseListeners() {
      return getWrapped().getPhaseListeners();
    }

    @Override
    public void removePhaseListener(PhaseListener listener) {
      getWrapped().removePhaseListener(listener);
    }

    @Override
    public void render(FacesContext context) throws FacesException {
      try {
        System.out.println("render(...)");
        getWrapped().render(context);
      } catch (FacesException intercepted) {
        System.out.println("===>>> Intercepted Throwable from render()");
        intercepted.printStackTrace();
        throw intercepted;
      }
    }

  }

Now, what we got so far is to let JSF initiate our CustomLifecycleFactory, which registers an instance of InterceptingLifecycle using the id “InterceptingLifecycle”. But how can we make use of our lifecycle implementation? Well, FacesServlet supports an init-param named “javax.faces.LIFECYCLE_ID” to allow configuring the id of the lifecycle that FacesServlet should use. For that you need to change the FacesServlet config in your web.xml like this:

 <servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <init-param>
   <param-name>javax.faces.LIFECYCLE_ID</param-name>
   <param-value>InterceptingLifecycle</param-value>
  </init-param>
 </servlet>

The sources for these examples are available on https://github.com/dueni/faces-ext/tree/master/exception-handling-lifecycle .

Advertisements

36 Comments »

  1. Hi, it was so useful but how can I redirect user to some page lick error page .
    where i must wrote the redirect line.
    thank you.

    Comment by shayegh — 2009/07/23 @ 04:17

    • Hi,
      there are several options like just create a new ViewRoot on the error page and let it render. But that seemed to static so we use a different approach. We use the exceptions class name (and it’s cause and the parent class names) to find a JSF navigation rule that forwards to the fitting error page. For that it is then necessary to define navigation rules that use exception class name as “outcome” to define the target page based on exception type.
      I will soon do another blog post showing such an implementation.

      Comment by Hanspeter — 2009/07/23 @ 07:37

      • hi hanspeter
        i would like to implement lifecycle class in my project. we need to move our logic from phaselistener to lifecycle. Could you plz tell how to do it.
        in my application we do some logic in phaselistener at RESTORE_VIEW. how can we do like this in lifecycle?

        Comment by shaikh — 2010/02/11 @ 13:04

      • Sorry for the delay – is that question still relevant or did you solve that in between?

        Actually I think the Lifecycle wrapping thing is something that should rather be done in a framework (as you work for CS you should use CS JSF that does do that) than do it in the application itself. Also if something works fine using a PhaseListener I do not see the need to migrate that to Lifecyle – PhaseListener work more finegraned. Using f:phaseListener tag also allows to instrument PhaseListener’s on a per page basis.

        If you still have question about that, please contact me on the CS internal mail.

        regards
        Hanspeter

        Comment by Hanspeter — 2010/04/06 @ 10:56

  2. Hi,
    thank you for your answer ,can you give me an example

    Comment by shayegh — 2009/07/25 @ 04:38

  3. Hi,
    Thanks for the nice article, I have a question on exception handling in render response phase, suppose I have some database access logic in a JSF datatable getter() method and if it throws an exception, JSF skips renderering the rest of the components, per my understanding the soution that was suggested here catches the exception in the render() method here but it would not proceed to render the rest of the componets, Is there a way can this be handled.

    Comment by spal — 2010/09/01 @ 00:05

    • Hi Spal.
      Well, if you want te rendering continued you must make sure your method to fetch the data does not throw any exception – you must catch it and might add a FacesMessage on your page.
      The generic Exception handling implemented as a custom Lifecycle can only handle the case where a thrown exception exits the currently processed phase. The exception handling would then switch ViewRoot to same error page and let this page render as response.

      regards
      Hanspeter

      Comment by Hanspeter — 2010/09/01 @ 10:57

  4. Hi Hanspeter,

    First off great article!

    I am trying your method in order to get a better handle on any exceptions that get thrown. Unfortunately I am really struggling with getting it to work.

    At first I was doing exactly what you have illustrated in your example. I was getting an error with something about the custom lifecycle ID was already in use. I soon realized I am actually also overriding the “MyFacesServlet”, thus I needed to extend the org.apache.myfaces.lifecycle.LifecycleFactoryImpl and org.apache.myfaces.lifecycle.LifecycleImpl rather than the standard JSF classes.

    I am getting a nullPointer in my Factory at the addLifecycle(lifecycleId, lifecycle) method. The lifecycleId’s value is “DEFAULT”, though the lifecycle’s _phaseListenerList is size 0 and it’s _phaseListenerArray is null.

    I hope that my rambling above makes sense. Any help/guidance you could provide would be more than appreciated!

    Thanks in advance,

    Mick

    Comment by Mick — 2010/09/26 @ 06:58

    • Sorry,

      Forgot to mention, I am actually using JSF 1.1. And to add, in my web.xml I tried your method by using:

      javax.faces.LIFECYCLE_ID
      InterceptingLifecycle

      …however, through my desparate plees to Google for help 🙂 I found someone using the following outside of the tags and (assuming) placing it inside the tags. “http://web.archiveorange.com/archive/v/MgEigtEBVer6dUH3OWjl”
      (little bit below the middle of the referenced page)

      javax.faces.LIFECYCLE_ID
      Mick

      Don’t know if any of this helps, just wanted to mention it in case it did.

      Thanks again,

      Mick

      Comment by Mick — 2010/09/26 @ 07:10

    • Hi Mick,
      well I never tried with MyFaces of JSF 1.1 – luckily we started directly with JSF 1.2 and I really recommend to go for JSF 2.0 soon and not fiddle too much with JSF 1.1 based code ;-), but that was not the question.

      Initially we also extended FacesServlet, but that’s an ugly solution. Therefore we went for the custom Lifecyle implementation.

      Why do you need to override/extend MyFacesServlet? FacesServlet itself is actually final to prevent extending it, that is also why MyFacesServlet uses it as delegate.

      You should never extend an Impl class – but implement or extend API classes only. If you create your own LifecycleFactory you will get the standard Lifecyclefactory(Impl) passed in to your constructor and can then add YourLifecycleImpl to the list of installed Lifecycles (the standard LifecycleImpl has a map for all the registered Lifecyle(Impls). All this is done while the ServletContainer is initialized and before FacesServlet gets initialized.

      FacesServlet.init() will then get the Lifecyle(Impl) to be used from that map.

      Hope that helps somehow to understand initialization of (custom) Lifecycle.
      If you still have problem with NPE, try debug/trace LifecycleFactory and FacesServlet initialization to understand how it works, thern compare what you did and where you broke the process.

      regards
      Hanspeter

      Comment by Hanspeter — 2010/09/27 @ 14:43

      • Thank you for your quick reply. I can’t tell you how aprecieated that is!!!

        I agree with the JSF 2.0 suggestion. Upgrading the application is actually our next project as soon as I complete this one.

        To answer why override/extend MyFacesServlet. The whole purpose of me wanting to any of this is for custom error handling. I was only able to get the custom error page to show up after I extend the MyFacesServlet. I wanted a “user friendly” page to be displayed regardless of the error. To handle this, I initially tried the standard tags in the web.xml (pasted below is the condensed version):

        500
        /error.jsf

        java.lang.Throwable
        /error.jsf

        This never did show my custom error page, I figure it is due to using MyFaces. The only error page I could ever get was the standard Tomcat error page. I later found a way to “catch” errors by simply wrapping the MyFacesServlet, and delegating all functionality to it. I only catch the exceptions, and provide a response.sendRedirect() to my custom error page.

        That works fine, however, my objective is to not only forward the user to a friendly error page, but on the back end, email pertinent individuals information about the error. I would like to also provide information about the user whom received the error in this email for customer server purposes. Sounds simple right? Well I’m running into interesting problems. I don’t have access to the user information at my MyFacesServlet level, because at that point the FacesContext is null (this object holds all info about request, session, and application variables, as you’re aware).
        So I tried simply implementing a PhaseListener, however, this approach doesn’t work because, though I have a handle on the FacesContext, I don’t have information regarding the exception that has thrown in either the afterPhase() or beforePhase() methods. This is why I am now trying to implement a wrapper around the Lifecycle.

        Comment by Mick — 2010/09/27 @ 16:03

      • Hi Mick.

        Well, with custom Lifecycle you will be able to catch exceptions as you want and render a nice error page all within the current request processing and FacesContext will still be there – only thing to make sure, your nice error-page made up as a JSf page must not throw any exception again. But to try that you should first configure web.xml to use teh standard FacesServlet or in case of MyFaces the MyFacesServlet.
        Yes, PhaseListener is not of any use for ExceptionHandling – but with custom Lifecycle you can catch exceptions from all phase processing including the render phase.

        From my example with the InterceptingLifecycle you are able to catch the exceptions from execute() and render(). Put the exception to requestMap so you can check in render() if an exception was thrown somewhere in execute() – if yes, skip normal render() and directly go for exception handling.

        We added exception page handling at the end of the InterceptingLifecycle.render() method – like if a caught exception is present on the requestMap, we use e.g. the exception class name on JSF NavigatinHanlder to find the error page to be used – that makes it possible to use different error pages for different exceptions. Only tricky thing here is which classname to use, the name of teh exception-class itself or it’s parent-class, or … – but if you start with exactly one error-page, simplest way to get that view is add a navigation-rule and use FacesContext.getCurrentInstance().getApplication().getNavigationHandler() to adjust the ViewRoot to the error page – then simply call delegate.render() in your custom LifecyleImpl again (works also if exception happened in render phase as long as nothing was written to the HttpServletResponse).
        As we maintain some company internal framework, we actually use navigation-rules baed on exception class names to navigate to different error pages depending on the thrown exception and we also use the class hierarchy there to try navigation until viewRoot has changed.

        regards
        Hanspeter

        Comment by Hanspeter — 2010/09/27 @ 16:37

  5. Hi hanspeter, great article, i have exactly the same scenario you described, the only difference is that i don’t want to navigate to any error page, i just want to stand in the current page and show a message with information of the error to the user.
    For example the user click a button that execute an action on the server, in that method i invoke a bean that doesn’t exist, it throw a “HTTP Status 500 error” by default, now what i want is that JSF don’t show the ugly page for that error and instead stand in the current page, render all the elements in some way and show in a message tag information about the error.
    Is that possible with the approach you describe in your article?

    Comment by Maykell — 2011/01/28 @ 05:47

    • Hi Maykell,
      I think that is possible. To stay on the same page your exception handling simply should add FacesMessage(s) to be displayed (hope you have h:messages on the page) and not perform navigation to an error page in your exception handler.

      But maybe your exception handling lifecycle should distinguish between errors happening during execute (phases 1-5) and exception happening while rendering – when an exception happens while rendering the page that might affect the page or imagin you have h:messages on the top of the page and one of the last parts of the page cause the exception – then you don’t have any chance to sho the message (h:messages was already rendered).

      The same problem if you choose to use the same page as th error page: exception happens while rendereing, so exception handling adds the message and uses the same view to be rendered as the error page – now it’s very likely the same exception will happen again.

      Conclusion: if an exception from render phase must be handled its saver to navigate to an error page that for sure will not cause another exception while beeing rendered.

      Regards
      Hanspeter

      Comment by Hanspeter — 2011/01/28 @ 08:43

      • Hi Hanspeter, thank you for your quick response it was very useful, now the only question i have is:
        do i have the ability to distinguish if the error happened in the execute phase or in the render phase?
        Or it is just a matter of put the code to redirect to an error page in the render() method of the interceptingLifeCycle and put the code to add faces messages in the execute() method?

        Thank you very much,
        Maykell.

        Comment by Maykell — 2011/01/28 @ 14:42

      • Exception are caught in the custom LifecycleWrapper execute() or render() method. So I think that is the only information you have in which of the phases the exception was thrown. I guess that pretty much answers your question. I don’t have a complete solution for that – but with that information you should be able to handle your case.

        Comment by Hanspeter — 2011/01/28 @ 15:26

  6. Thanks you very much again Hanspeter your answers had been of great value.
    My best Regards,
    Maykell.

    Comment by Maykell — 2011/01/28 @ 16:30

  7. I tried your example – thanks for posting this. It *mostly* works however, for some reason after calling getWrapped().render() – if an exception is thrown within the wrapped render call, it is not rethrown and therefore I can never catch it and redirect (navigate) to a standard error page. I am trying to eliminate the generated Faces error page on the Restore_view phase where if there is some error that occurs during the building of the component tree, I can display a standard error page. I can NOT upgrade to JSF 2.0 – any help would be appreciated!!

    Comment by Nena — 2011/02/04 @ 21:36

    • It depends from where that Exception is thrown in render Phase. I know about some situations where JSF RI 1.2 logs exceptions without throwing them. Then of course nobody is able to catch such exceptions. We caught these exceptions by adding a custom LogHandler to record such logged-and-not-thrown exceptions into some request scoped bean and check this bean also after the wrapped render phase. Then we are able to catch also these -non-thrown exceptions.

      But all really thrown exceptions from render phase can be caught as shown in the basic example.

      If an exception occurs in the render phase and you must switch to display an error page that for shure has no errors on the page – otherwise you will get another exception wile rendering the error on the page. If the error-page is broken – then the only chance is to display the Facelets generated errorpage. But this then should only happen while developing the error-free errorpage.

      Comment by Hanspeter — 2011/02/07 @ 09:55

      • That’s interesting – how did you configure the LogHandler – is it somewhere in the faces-config or web.xml? Do you have some examples? Thanks!

        Comment by Nena — 2011/02/08 @ 21:01

      • Probably that would be worth another post 😉 It’s deep internal use of JDK logging infrastructure – if you know the logger name one can register additional Handler class on these loggers and intercept the log message to extract the exception. Collect such exceptions e.g. on a list stored on FacesContext.getAttributes() allows to handle them later too.

        Comment by Hanspeter — 2011/02/08 @ 22:55

      • Hi Hanspeter –

        I figured out why it wasn’t propagating the exception – facelets.DEVELOPMENT – set to true results in the FaceletViewHandler.handleRenderException to simply log and not rethrow an exception. So now it works.

        But code like the following: only seems to be returning an empty page (in the NavigationHandler/catch block) – though the page is there and no errors in the page…any thoughts?

        @Override
        public void render(FacesContext context) throws FacesException {
        try {
        getWrapped().render(context);
        } catch (FacesException intercepted) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        Application application = facesContext.getApplication();
        NavigationHandler navigationHandler = application.getNavigationHandler();
        navigationHandler.handleNavigation(facesContext, null, “exceptionOccurred”);
        facesContext.renderResponse();
        facesContext.responseComplete();
        }

        }

        Comment by Nena — 2011/02/08 @ 22:43

      • Well, since her you are already in the render() processing it’s not enough to call facesContext.renderResponse() – that would only signal JSF to jump to render phase processing. Instead you have to call getWrapped().render(context) after navigating to the error page. And probably that should be done within a try/catch block again. It works, we do it like this.

        Comment by Hanspeter — 2011/02/08 @ 22:52

  8. This is a great article Hanspeter, and it is satisfying exactly what I am trying to accomplish!

    I am, however; trying to get this to work in JSF 2.0 via Mojarra’s implementation. I am getting the following stack trace…any ideas?

    Mar 10, 2011 7:14:31 AM org.apache.catalina.core.ApplicationContext log
    Mar 10, 2011 7:14:31 AM org.apache.catalina.core.ApplicationContext log
    Mar 10, 2011 7:14:34 AM org.apache.catalina.core.ApplicationContext log
    SEVERE: StandardWrapper.Throwable
    java.lang.IllegalArgumentException: Cant create Lifecycle for id: CustomLifecycleWrapper.
    at com.sun.faces.lifecycle.LifecycleFactoryImpl.getLifecycle(LifecycleFactoryImpl.java:128)
    at com.npp.web.jsf.CustomLifecycleFactory.getLifecycle(CustomLifecycleFactory.java:29)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:189)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:623)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:445)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:292)
    at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694)
    at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665)
    at org.apache.jsp.index_jsp._jspService(index_jsp.java:54)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
    Mar 10, 2011 7:14:34 AM org.apache.catalina.core.ApplicationDispatcher invoke
    SEVERE: Allocate exception for servlet Faces Servlet
    java.lang.IllegalArgumentException: Cant create Lifecycle for id: CustomLifecycleWrapper.
    at com.sun.faces.lifecycle.LifecycleFactoryImpl.getLifecycle(LifecycleFactoryImpl.java:128)
    at com.npp.web.jsf.CustomLifecycleFactory.getLifecycle(CustomLifecycleFactory.java:29)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:189)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:623)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:445)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:292)
    at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694)
    at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665)
    at org.apache.jsp.index_jsp._jspService(index_jsp.java:54)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
    Mar 10, 2011 7:14:34 AM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet jsp threw exception
    java.lang.IllegalArgumentException: Cant create Lifecycle for id: CustomLifecycleWrapper.
    at com.sun.faces.lifecycle.LifecycleFactoryImpl.getLifecycle(LifecycleFactoryImpl.java:128)
    at com.npp.web.jsf.CustomLifecycleFactory.getLifecycle(CustomLifecycleFactory.java:29)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:189)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:623)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:445)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:292)
    at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694)
    at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665)
    at org.apache.jsp.index_jsp._jspService(index_jsp.java:54)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
    Mar 10, 2011 7:14:37 AM org.apache.catalina.core.ApplicationContext log
    SEVERE: StandardWrapper.Throwable
    java.lang.IllegalArgumentException: Cant create Lifecycle for id: CustomLifecycleWrapper.
    at com.sun.faces.lifecycle.LifecycleFactoryImpl.getLifecycle(LifecycleFactoryImpl.java:128)
    at com.npp.web.jsf.CustomLifecycleFactory.getLifecycle(CustomLifecycleFactory.java:29)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:189)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:623)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:445)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:292)
    at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694)
    at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665)
    at org.apache.jsp.index_jsp._jspService(index_jsp.java:54)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
    Mar 10, 2011 7:14:37 AM org.apache.catalina.core.ApplicationDispatcher invoke
    SEVERE: Allocate exception for servlet Faces Servlet
    java.lang.IllegalArgumentException: Cant create Lifecycle for id: CustomLifecycleWrapper.
    at com.sun.faces.lifecycle.LifecycleFactoryImpl.getLifecycle(LifecycleFactoryImpl.java:128)
    at com.npp.web.jsf.CustomLifecycleFactory.getLifecycle(CustomLifecycleFactory.java:29)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:189)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:623)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:445)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:292)
    at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694)
    at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665)
    at org.apache.jsp.index_jsp._jspService(index_jsp.java:54)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
    Mar 10, 2011 7:14:37 AM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet jsp threw exception
    java.lang.IllegalArgumentException: Cant create Lifecycle for id: CustomLifecycleWrapper.
    at com.sun.faces.lifecycle.LifecycleFactoryImpl.getLifecycle(LifecycleFactoryImpl.java:128)
    at com.npp.web.jsf.CustomLifecycleFactory.getLifecycle(CustomLifecycleFactory.java:29)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:189)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:623)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:445)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:292)
    at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694)
    at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665)
    at org.apache.jsp.index_jsp._jspService(index_jsp.java:54)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)

    Comment by Mick — 2011/03/10 @ 14:18

    • Hi Hanspeter,

      I’m sorry for my previous post. I just figured out what I was doing wrong. In my web.xml, I had name of the wrapper class, and not the string value (“id”) of the INTERCEPTING_LIFECYCLE_ID constant defined in the Factory. I have been fighting this for a day and a half, and it wasn’t until I posted the question that I realized my error. Sorry for any inconvenience and thanks so very much for posting such a great article!

      Comment by Mick — 2011/03/10 @ 14:38

    • Well, with JSF 2.0 you already have ExceptionHandler in place from JSF 2.0 – so why not simply hook into JSF 2.0 ExceptionHandler? You might have a look at Ed Burns blog covering ExceptionHandler – see http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2.

      Comment by Hanspeter — 2011/04/01 @ 09:16

  9. Hi Hanspeter,

    I now have a legitimate question for you 🙂

    My intentions are to catch any/all errors in the catch statement of the LifecycleWrapper’s execute and render methods. I perform some code, and then try to do the following:

    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
    response.sendRedirect(path);

    This works great when catching errors in the execute method, however; I get a IlligalArgumentException when performing the code in the render method. I believe the problem is that response.isCommitted() is true whenever I enter the render method. Are there any options to forward or redirect the user to my friendly error page?

    Thank you a ton for any help with this!

    Mick

    Comment by Mick — 2011/03/10 @ 19:58

    • Hi Mick,
      Yes, that’s a tricky one – as soon as RENDER_RESPONSE has started writing anything to the response (not buffered), you cannot send a redirect anymore. If e.g. ServletResponse.isCommited() returns true, most likely some part of the response is already written to ServletResponse and you cannot replace that with the error page.

      To make sure you can produce your error page, you probably have to buffer the complete response and only write it to ServletResponse once you are sure you don’t have to produce the error page.

      regards
      Hanspeter

      Comment by Hanspeter — 2011/03/21 @ 10:40

  10. Using its implementation, can not capture some rendering errors, such as “duplicate id”, I would catch any error, any suggestions?

    Comment by Rafaell Pinheiro — 2011/03/29 @ 17:40

    • If you catch exceptions happening during render phase, you cannot change to error page and just let JSF continue, since JSF was already performing render phase. Instead we keep internally a reference to the lifecycle so if an exception was caught from render phase, we still xcan switch the view to the error page and then call lifecycle.render() from our ExceptionHandler. That works, but is a bit of work.

      Comment by Hanspeter — 2011/04/01 @ 09:19

      • Hi Hanspeter,
        Could you please explain me where would you switch the view to error page when you catch exceptions in render phase?

        Comment by Sheik — 2011/06/20 @ 09:55

      • As explained in previous answer, catching exception in render phase and then change ViewRoot to error page is only possible when executing Lifecycle.render() explicitly from ErrorHandler. We do that in our company internal framework, but it’s some work to get hold of a reference to the Lifecycle instance to execute it from ErrorHandler. It’s possible by implementing a custom lifecycle and e.g. put a reference to lifecycle into FacesContext attributes map. ErrorHandler is then able to obtain lifecycle instance from FacesContext attributes map and call render() on it to render the error page even for exceptions caught in render phase (but exceptions from rendering that error page will lead to servlet-error page).

        regards
        Hanspeter

        Comment by Hanspeter — 2011/07/04 @ 12:25

  11. Hi,
    I am not able to redirect to error pagefrom within render phase because JSF is trying to instantiate my managed bean although it has moved to the error page. actually the error occurs in the cinstructor of my amanaged bean.
    any idea how to solve it?
    I am using your suggestion with the lifecycle wrapper and here is my render method:
    @Override
    public void render(final FacesContext context) throws FacesException {
    try {
    LOGGER.fine(“Rendering jsf page”);
    wrapped.render(context);
    } catch (final Exception intercepted) {
    try {
    final FacesContext facesContext = FacesContext.getCurrentInstance();
    final Application application = facesContext.getApplication();
    final NavigationHandler navigationHandler = application.getNavigationHandler();
    navigationHandler.handleNavigation(facesContext, null, “errorOccured”);
    wrapped.render(facesContext);

    } catch (final Exception intercepted2) {
    System.out.println(“##################===>>> Intercepted Throwable from render()”);
    intercepted2.printStackTrace();

    }
    }
    }

    Comment by Anis Ben — 2011/11/22 @ 22:15

    • Well, no ExceptionHandler will (ever) be able to handle managed bean instances that cannot be constructed because of thrown exceptions from the constructor.
      That is why you should not perform such critical actions in the bean constructor – or at least handle it with try/catch and maintaining an init state in the bean. That way the bean’s toString() method could e.g. also display that state – and of course some log about init failure cause will also help.

      Comment by Hanspeter — 2011/11/23 @ 12:32

      • hi Hanspeter,

        the lifecycle methods execute() and render() are not getting called when i do a submit.
        it is only getting called when requesting the page for the first time i.e. when i enter the url in address bar and request the page.
        please give some pointers on this.

        Comment by pd — 2012/07/12 @ 13:07

      • Hi,
        Hook your debugger into FacesServlet.service() method to check what happens. If you don’t even get there, check your servlet mapping.
        Hanspeter

        Comment by Hanspeter — 2012/08/13 @ 12:15


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: