这就是问题所在:EJB 抛出了这个异常(来自 glassfish 日志):
SEVERE: Attempting to confirm previously confirmed login using confirmation UUID: b90b33ca-dc69-41c1-9c60-99152810c89b
com.extremelatitudesoftware.els_commons.exceptions.LoginPreviouslyConfirmedException: Attempting to confirm previously confirmed login using confirmation UUID: b90b33ca-dc69-41c1-9c60-99152810c89b
at com.extremelatitudesoftware.security.auth.CredentialsController.checkForPreviousConfirmation(CredentialsController.java:244)
在异常堆栈的客户端(在底部)我看到了这个:
WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
at com.extremelatitudesoftware.accesscontrol.registration.RegistrationConfirmationBean.setChallengeQuestion(RegistrationConfirmationBean.java:61)
at com.extremelatitudesoftware.accesscontrol.registration.RegistrationConfirmationBean.fetchChallengeResponse(RegistrationConfirmationBean.java:51)
当然,在浏览器中,我得到一个通用的 500 异常错误,表示存在空指针异常。
我想要一个自定义错误页面来检测“com.extremelatitudesoftware.els_commons.exceptions.LoginPreviousConfirmedException”并说“哎呀,你已经确认了!”
有人可以为我指出正确的方向,让客户端/JSF 层正确地“看到”异常,以便可以做到这一点。
这是问题的用例:
我在 EJB 层中有一个方法,用于检查用户之前是否确认了他们的登录帐户。如果他们没有,它会处理他们确认新帐户的请求。如果他们说回到旧电子邮件并说,嗯,让我们再次单击它,后端将检测到,抛出异常以使其被 JSF/客户端层拾取并通知用户该帐户已被确认。
添加示例代码:
方法检查条件并在必要时抛出异常。请注意,大多数情况下这不会发生,所以我想使用这种机制,而不是在每次有人确认他们的帐户时都拨打不必要的电话。
...
private void checkForPreviousConfirmation(Credentials cr)
throws LoginPreviouslyConfirmedException {
if (!(CredentialsStatusType.PENDING.equals(cr.getStatus()))
|| !(CredentialsDispositionType.WAITING.equals(cr.getDisposition()))) {
String msg = "Attempting to confirm previously confirmed login using "
+ "confirmation UUID: " + cr.getConfirmationUuid();
Logger.getLogger(CredentialsController.class.getName()).log(Level.INFO,
msg);
throw new LoginPreviouslyConfirmedException(msg);
}
}
自定义异常:
public class LoginPreviouslyConfirmedException extends RuntimeException {
public LoginPreviouslyConfirmedException(String msg, Throwable cause) {
super(msg, cause);
}
public LoginPreviouslyConfirmedException(String msg) {
super(msg);
}
}
这是在 JSF 层的 ManagedBean 中。它通过以下方式调用:preRenderView
...
public void fetchChallengeResponse() {
try {
crespList = regFacade.fetchChallengeResponse(confirmUuid);
} catch (LoginPreviouslyConfirmedException ex) {
String msg = "Attempting to confirm previously confirmed login using " + "confirmation UUID: " + getConfirmUuid();
Logger.getLogger(RegistrationConfirmationBean.class.getName()).log(Level.SEVERE, msg, ex);
FacesContext facesContext = FacesContext.getCurrentInstance();
Application application = facesContext.getApplication();
NavigationHandler navigationHandler = application.getNavigationHandler();
navigationHandler.handleNavigation(facesContext, null, "faces/errorpages/already_confirmed.xhtml");
facesContext.renderResponse();
}catch (Exception ex){
String msg = "Including this to see if the previously confirmed exception was skipped over";
Logger.getLogger(RegistrationConfirmationBean.class.getName()).log(Level.SEVERE, msg, ex);
}
this.setChallengeQuestion();
}
这是日志显示的内容:
INFO: Attempting to confirm previously confirmed login using confirmation UUID: b90b33ca-dc69-41c1-9c60-99152810c89b
WARNING: EJB5184:A system exception occurred during an invocation on EJB CredentialsController, method: public java.util.ArrayList com.extremelatitudesoftware.security.auth.CredentialsController.fetchChallengeResponseByCredentialUuid(java.lang.String) throws com.extremelatitudesoftware.els_commons.exceptions.LoginPreviouslyConfirmedException
WARNING: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
然后有几个追踪:
SEVERE: Including this to see if the previously confirmed exception was skipped over
javax.ejb.EJBTransactionRolledbackException
根据 BalusC 的建议,我将 ManagedBean 中的代码更改为:
public void fetchChallengeResponse() throws LoginPreviouslyConfirmedException{
crespList = regFacade.fetchChallengeResponse(confirmUuid);
this.setChallengeQuestion();
}
这是在 web.xml
<error-page>
<exception-type>com.extremelatitudesoftware.els_commons.exceptions.LoginPreviouslyConfirmedException</exception-type>
<location>/errorpages/already_confirmed.xhtml</location>
</error-page>