Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error pages for exceptions during page rendering

Tags:

jsf

omnifaces

In the backing beans of my JSF application, certain exceptions may be thrown at any time, and I want to react to this by redirecting to an error page. I have included the omnifaces FullAjaxExceptionHandler, and my web.xml contains

<error-page>
    <exception-type>my.own.ResourceNotFoundException</exception-type>
    <location>/error/error404.xhtml</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/error/error500.xhtml</location>
</error-page>

In most cases, including Ajax requests, this works fine: ResourceNotFoundException leads me to the error page. However, when the exception is thrown in a method annotaded with @PostConstruct, I always get the generic page for error code 500.

Is this because JSF wraps the exception in something else and the mechanism in web.xml does not recognize it? If yes, how can I get this to work as expected?

Here is the exception trace I see in the server log:

    Feb 07, 2013 11:08:32 AM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/my/projects/details/details.xhtml]
javax.el.ELException: //P:/codebase/code/portal/jsf-impl/target/classes/META-INF/resources/common/title.xhtml: Bei der Ressourcen-Einspeisung auf dem verwalteten Bean projectDetailsController ist ein Fehler aufgetreten.
    at com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:90)
    at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:309)
    at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779)
    at com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:78)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at my.own.filters.SecurityFilter.doFilter(SecurityFilter.java:48)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:185)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:151)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at my.own.UTF8Valve.invoke(UTF8Valve.java:34)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:269)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: com.sun.faces.mgbean.ManagedBeanCreationException: Bei der Ressourcen-Einspeisung auf dem verwalteten Bean projectDetailsController ist ein Fehler aufgetreten.
    at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:229)
    at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:105)
    at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:409)
    at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269)
    at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
    at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at org.apache.el.parser.AstIdentifier.getValue(AstIdentifier.java:71)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:147)
    at org.apache.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:44)
    at org.apache.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:50)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2362)
    at com.sun.faces.el.CompositeComponentAttributesELResolver$ExpressionEvalMap.get(CompositeComponentAttributesELResolver.java:345)
    at javax.el.MapELResolver.getValue(MapELResolver.java:52)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:169)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
    at com.sun.faces.facelets.el.ELText$ELTextVariable.writeText(ELText.java:227)
    at com.sun.faces.facelets.el.ELText$ELTextComposite.writeText(ELText.java:150)
    at com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:85)
    ... 43 more
Caused by: com.sun.faces.spi.InjectionProviderException
    at com.sun.faces.vendor.WebContainerInjectionProvider.invokeAnnotatedMethod(WebContainerInjectionProvider.java:119)
    at com.sun.faces.vendor.WebContainerInjectionProvider.invokePostConstruct(WebContainerInjectionProvider.java:99)
    at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:223)
    ... 66 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.faces.vendor.WebContainerInjectionProvider.invokeAnnotatedMethod(WebContainerInjectionProvider.java:117)
    ... 68 more
Caused by: my.own.ResourceNotFoundException: Did not find project
    at my.own.projects.details.ProjectDetailsController.createModel(ProjectDetailsController.java:198)
like image 516
Alex Krauss Avatar asked May 21 '26 19:05

Alex Krauss


1 Answers

As your log suggests, ResourceNotFoundException is wrapped in four other exceptions.

You could develop your own CustomExceptionHandler like the one in Duke's Forest example instead of using omnifaces FullAjaxExceptionHandler or even extend it and go down causes until you reach ResourceNotFoundException then use NavigationHandler to redirect to the desired error page.

Here is edited version of related classes and faces-config.xml from Duke's Forest example. This should work as you expect even if the exception occurs in @PostConstruct method:

CustomExceptionHandlerFactory.java

package com.forest.exception;

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
   private ExceptionHandlerFactory parent;

   // this injection handles jsf
   public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
       this.parent = parent;
   }

    @Override
    public ExceptionHandler getExceptionHandler() {

        ExceptionHandler handler = new CustomExceptionHandler(parent.getExceptionHandler());

        return handler;
    }

}

CustomExceptionHandler.java

package com.forest.exception;

public class CustomExceptionHandler extends ExceptionHandlerWrapper {
    private static final Logger log = Logger.getLogger(CustomExceptionHandler.class.getCanonicalName());
    private ExceptionHandler wrapped;

    CustomExceptionHandler(ExceptionHandler exception) {
        this.wrapped = exception;
    }

    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

    private boolean includesResourceNotFoundException(Throwable t) {
        if(t == null) {
            return false;
        else {
            return t instanceof ResourceNotFoundException || includesResourceNotFoundException(t.getCause());
        }
    }


    @Override
    public void handle() throws FacesException {

        final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
        while (i.hasNext()) {
            ExceptionQueuedEvent event = i.next();
            ExceptionQueuedEventContext context =
                    (ExceptionQueuedEventContext) event.getSource();

            // get the exception from context
            Throwable t = context.getException();

            final FacesContext fc = FacesContext.getCurrentInstance();
            final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
            final NavigationHandler nav = fc.getApplication().getNavigationHandler();

            //here you do what ever you want with exception
            if(hasResourceNotFoundException(t) {
                try {
                    //log error ?
                    log.log(Level.SEVERE, "Critical Exception!", t);

                    //redirect error page
                    requestMap.put("exceptionMessage", t.getMessage());
                    nav.handleNavigation(fc, null, "/error/error500?face-redirect=true");
                    fc.renderResponse();
                } finally {
                    //remove it from queue
                    i.remove();
                }
            }
        }
        //parent hanle
        getWrapped().handle();
    }
}

faces-config.xml (partial)

<factory>
        <exception-handler-factory>
            com.forest.exception.CustomExceptionHandlerFactory
        </exception-handler-factory>
</factory>
like image 122
Sam Avatar answered May 24 '26 10:05

Sam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!