I got some uncaught exception basically from an SQL operation via Primefaces AJAX call. Interestingly this uncaught exception APPEAR on FireBug's JavaScript secion as error:
<?xml version='1.0' encoding='UTF-8'?> <partial-response><error><error-name>class javax.faces.el.EvaluationException</error-name><error-message><![CDATA[Transaction rolled back]]></error-message></error></partial-response>
and on the server.log with all stacktrace and everything.
But I am unable to to bring it to the user attention without redirecting them to a separate error page (and lost all input data).
The proper way to handle this to create validator, which I will do, but there are always possibility of unaware database problem which will only appear doing the SQL operation. So I am only talk about no validator situation.
Let say I have this JSF snippet.
<h:form>
<p:messages />
<..... primefaces (AJX) some button .... action="bean.save()" />
</h:form>
and the bean.save();
public void save()
{
try
{
em.merge(this.data);
}
catch(Exception e)
{
// never been in here EVEN if the data can't be merge for some constraint breaking reason.
}
}
If there is an database error, we will not see it until the transaction ends (AFTER save()) so I can't catch it. (This is confirmed with debug walk through and the fact that adding "em.flush()" here make the whole things works).
After looked left and right, I created a PhaseListener and I am able to get the exception. However, I am unable to show that exception on <p:messages />
public void afterPhase(final PhaseEvent event)
{
final Iterable exceptionEvents = event.getFacesContext().getExceptionHandler().getUnhandledExceptionQueuedEvents();
for (final ExceptionQueuedEvent exceptionEvent : exceptionEvents)
{
// This print out goes (found in server.log).
System.out.println("Problem: " + exceptionEvent.getContext().getException());
// But this message does not.
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Problem", "Problem: " + exceptionEvent.getContext().getException()));
}
}
Any advice is very appreciated.