jsr344-experts@javaserverfaces-spec-public.java.net

[jsr344-experts] [jsr-344-experts] Handling AbortProcessingException is unconsistent

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Thu, 30 Jun 2011 19:23:30 -0500

Hi

Checking JSF 2.0 ExceptionHandler API, an user in MyFaces notice there
is an inconsistency about how AbortProcessingException is handled
(MYFACES-3199).

Let's suppose this example:

<h:inputText valueChangeListener="#{bean.processValueChange}">

The spec javadoc of
javax.faces.event.MethodExpressionValueChangeListener.processValueChange
(on method detail) says this:

"... Call through to the MethodExpression passed in our constructor.
First, try to invoke the MethodExpression passed to the constructor of
this instance, passing the argument ValueChangeEvent as the argument.
If a MethodNotFoundException is thrown, call to the zero argument
MethodExpression derived from the MethodExpression passed to the
constructor of this instance. If that fails for any reason, throw an
AbortProcessingException, including the cause of the failure. ..."

Look the last line that says "... If that fails for any reason, throw
an AbortProcessingException, including the cause of the failure ...".
Now suppose a RuntimeException is thrown inside the listener. The spec
clearly says that any exception should be wrapped into an
AbortProcessingException, and the final effect is that exception is
just logged and the page is rendered, so from the client side you
don't see any error.

The problematic code is this one:

<h:inputText >
        <f:valueChangeListener binding="#{bean}" />
</h:inputText>

In this case, if a RuntimeException or any other happens inside the
listener, instead catch it and rethrow it as an
AbortProcessingException, the exception "comes out", the error page is
shown. This is the stack trace in Mojarra:

java.lang.RuntimeException: process validation throwValueChange failed!
        at org.apache.myfaces.testex.UserBean2.processValueChange(UserBean2.java:57)
        at com.sun.faces.facelets.tag.jsf.core.ValueChangeListenerHandler$LazyValueChangeListener.processValueChange(ValueChangeListenerHandler.java:128)
        at javax.faces.event.ValueChangeEvent.processListener(ValueChangeEvent.java:134)
        at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:777)
        at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:752)
        at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1167)
        at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:508)

Since both MyFaces and Mojarra shares the same code from facelets, the
effect is present in both implementations.

I think the problem can be found too on f:actionListener and other
similar tags.

It is clear the wrapping should be done and the error just need to be
logged, but before apply any fix on 2.0.x or 2.1.x branch I think it
is better to ask if that is true. Anyway, a clarification must be
included on the spec for JSF 2.2, because it could be components in
JSF libraries that requires do this fix too.

Suggestions are welcome.

Leonardo Uribe