Nach meiner vorherigen Frage in Creating FacesMessage in action method outside JSF conversion/validation mechanism?, versuche ich die Ausnahmen aus der Business-Schicht außerhalb meiner verwalteten Beans zu behandeln.JSF 2: Ist dies ein guter Ansatz, um Business Exceptions zu behandeln?
Die Strategie besteht darin, Business Exceptions nach Faces-Nachrichten in einem PhaseListener zu suchen und zu konvertieren.
Es funktioniert wie ich erwartet habe, aber ich frage mich nur, ob ich gerade das Rad neu erfinden, oder es richtig mache mit dem falschen Weg?
Hier ist mein Beispielcode-Schnipsel:
public class BusinessExceptionHandler implements PhaseListener {
@Override
public void afterPhase(PhaseEvent phaseEvent) {
ExceptionHandler exceptionHandler = phaseEvent.getFacesContext().getExceptionHandler();
// just debugging the handled exception, nothing here
/*
for (ExceptionQueuedEvent event : exceptionHandler.getHandledExceptionQueuedEvents()) {
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
System.out.println("handled exception : " + context.getException());
}*/
for (Iterator<ExceptionQueuedEvent> it = exceptionHandler.getUnhandledExceptionQueuedEvents().iterator();
it.hasNext();) {
ExceptionQueuedEvent event = it.next();
ExceptionQueuedEventContext eventContext = (ExceptionQueuedEventContext) event.getSource();
Throwable e = eventContext.getException();
System.out.println("unhandled exception : " + e);
// get the root cause exception
while (e.getCause() != null) {
e = e.getCause();
}
System.out.println("cause exception : " + e +
", cause exception is BE : " + (e instanceof BusinessException));
// handle BE
if (e instanceof BusinessException) {
BusinessException be = (BusinessException) e;
System.out.println("processing BE " + be);
FacesMessage message = Messages.getMessage(
"com.corejsf.errors",
be.getMessage(),
be.getParamValues()
);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, message);
it.remove(); // remove the exception
// works fine without this block, if BE is thrown, always return to the original page
/*
NavigationHandler navigationHandler = context.getApplication().getNavigationHandler();
System.out.println("navigating to " + context.getViewRoot().getViewId());
navigationHandler.handleNavigation(context, context.getViewRoot().getViewId(), null);
*/
}
}
}
@Override
public void beforePhase(PhaseEvent phaseEvent) {
}
@Override
public PhaseId getPhaseId() {
return PhaseId.INVOKE_APPLICATION;
}
}
Thank you!
Grüße, Albert Kam
Hallo nochmal. Danke für die Idee. Die Seite 282 ist nicht verfügbar. Aber nach einigem googeln fand ich edburns Artikel über diese Art von Angelegenheit und werde diese Praxis später benutzen: http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception- jsf2 – bertie