Ajf事件中的JSF句柄异常

时间:2018-04-23 17:58:20

标签: ajax jsf exception handle

我遵循了这个solution 并且在发生ViewExpiredException时完美地工作,但是当我检查(firefox实用程序)视图错误时,我看到它替换它,但只是在普通视图的body标签内,我的意思是,视图是异常的原因。视图错误在他自己的body标签中声明了一个css类,但我不知道,为什么不替换整个视图错误,而只是获取视图的所有内容(在他的body标签之后)错误并插入普通视图的body标签内?

要获得此行为,我有一个登录视图(我在上面提到的普通视图),只需要等到会话到期,然后我尝试登录(提交视图的形式),这会触发ExceptionHandler进行渲染de view error。

以下是一些代码段:

login.xhtml

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">

  <h:head>
    <f:facet name="first">
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
      <meta name="apple-mobile-web-app-capable" content="yes" />
    </f:facet>
    <title>PrimeFaces</title>
  </h:head>

  <h:body styleClass="login-body">
    <div class="login-panel ui-fluid">
      <div class="ui-g">
    <div class="ui-g-12 logo-container">
      <p:graphicImage name="images/logo-colored.png" library="theme-layout" />
      <h1>Login to Your Account</h1>
      <h2>WELCOME</h2>
    </div>
    <div class="ui-g-12">
      <p:inputText placeholder="User" />
    </div>
    <div class="ui-g-12">
      <p:password placeholder="Password" feedback="false"/>
    </div>
    <div class="ui-g-12 chkbox-container">
      <p:selectBooleanCheckbox id="remember-me" />
      <p:outputLabel for="remember-me" value="Remember Me"/>
    </div>
    <div class="ui-g-12 button-container">
      <p:commandButton type="submit" value="Log in" icon="fa fa-user" styleClass="orange-btn" action="#{menu.login}" update="frmLoginPromo">
    </div>
      </div>
    </div>

    <h:outputStylesheet name="css/layout-#{guestPreferences.layout}.css" library="theme-layout" />
  </h:body>

</html>

error.xhtml

    <!DOCTYPE html>
      <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <f:facet name="first">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
            <meta name="apple-mobile-web-app-capable" content="yes" />
        </f:facet>
        <title>PrimeFaces - Error </title>
    </h:head>

    <h:body styleClass="exception-body">
        <div class="exception-panel">
            <p:graphicImage name="images/icon-error.png" library="theme-layout" />

            <h1>Error Occured</h1>
            <p>An error occured, please try again later.</p>
        </div>

        <h:outputStylesheet name="css/layout-blue.css" library="theme-layout" />
    </h:body>

</html>

CustomExceptionHandler.java

    @Override
    public void handle() throws FacesException{
    final Iterator<ExceptionQueuedEvent> lclExceptionQueue = getUnhandledExceptionQueuedEvents().iterator();
    final FacesContext lclFacesContext = FacesContext.getCurrentInstance();
    final Map<String, Object> requestMap = lclFacesContext.getExternalContext().getSessionMap();
    while (lclExceptionQueue.hasNext()){
    ExceptionQueuedEvent event = lclExceptionQueue.next();
    ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
    Throwable lclThrowable = context.getException();


    try{
            if (lclThrowable instanceof ViewExpiredException){
 lclFacesContext.setViewRoot(lclFacesContext.getApplication().getViewHandler().createView(lclFacesContext, "/error.xhtml"));
                lclFacesContext.getPartialViewContext().setRenderAll(true);
                lclFacesContext.renderResponse();
            }
        }finally{
            lclExceptionQueue.remove();
        }
        }
        getWrapped().handle();
    }

在渲染错误视图后,这是如何看起来的

Inspecte view error 请告诉我出错了什么?

1 个答案:

答案 0 :(得分:2)

由于您已经在使用PrimeFaces,我选择不开发自己的异常处理程序。 PrimeFaces already has one that can handle both ajax and non-ajax requests

对于不使用PrimeFaces的人,我建议使用OmniFaces exceptionhandling

对于PrimeFaces 6.2 the documentation,包含在第11.3章中配置的信息(对于PF 6.1,它与btw相同)

总结( 所有引用均来自PF文档)

配置el解析器和异常处理程序

<application>
     <el-resolver>
        org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver
    </el-resolver>
</application>
<factory>
    <exception-handler-factory>
        org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory
    </exception-handler-factory>
</factory>

如果要在web.xml中配置errorpages

<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/ui/error/error.jsf</location>
</error-page>
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/ui/error/viewExpired.jsf</location>
</error-page>

然后,您可以在错误页面

中使用有关EL中例外的信息
<h:outputText value="Message:#{pfExceptionHandler.message}" />
<h:outputText value="#{pfExceptionHandler.formattedStackTrace}" escape="false" />

有更多信息,我建议您查阅文档。

对于你可以做的ajax例外

<p:ajaxExceptionHandler type="javax.faces.application.ViewExpiredException"
    update="exceptionDialog" onexception="PF('exceptionDialog').show();" />
<p:dialog id="exceptionDialog" header="Exception: #{pfExceptionHandler.type} 
    occured!" widgetVar="exceptionDialog" height="500px">
    Message: #{pfExceptionHandler.message} <br/>
    StackTrace: <h:outputText value="#{pfExceptionHandler.formattedStackTrace}" escape="false" />
    <p:button onclick="document.location.href = document.location.href;"
        value="Reload!"/>
</p:dialog>

OmniFaces的配置非常相似。

另见: