页面呈现过程中出现异常的错误页面



在我的JSF应用程序的后台bean中,某些异常可能随时被抛出,我希望通过重定向到错误页面来对此做出反应。我已经包含omnifaces FullAjaxExceptionHandler,并且我的web.xml包含

<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>

在包括Ajax请求在内的大多数情况下,这都很好:ResourceNotFoundException会引导我进入错误页面。然而,当在用@PostConstruct声明的方法中抛出异常时,我总是得到错误代码500的通用页面。

这是因为JSF将异常封装在其他东西中,而web.xml中的机制无法识别它吗?如果是,我如何才能使其按预期工作?

以下是我在服务器日志中看到的异常跟踪:

    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)

如日志所示,ResourceNotFoundException包含另外四个异常。

您可以像Duke’s Forest示例中那样开发自己的CustomExceptionHandler,而不是使用omnifaces FullAjaxExceptionHandler;甚至可以扩展它并向下查找原因,直到到达ResourceNotFoundException,然后使用NavigationHandler重定向到所需的错误页面

以下是杜克森林示例中相关类和faces-config.xml的编辑版本。即使在@PostConstruct方法中发生异常,这也应该如您所期望的那样工作:

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(部分)

<factory>
        <exception-handler-factory>
            com.forest.exception.CustomExceptionHandlerFactory
        </exception-handler-factory>
</factory>

相关内容

  • 没有找到相关文章

最新更新