I've been working with both the Apache MyFaces and the Oracle Mojarra teams on improving JSF 2 support in Metawidget.Metawidget is a more dynamic component than most, and exercises JSF 2 in a way few component libraries do. In particular, it stresses the relationship between dynamically modifying the component tree, partial state saving (new in JSF 2), and firing nested SystemEvents (new in JSF 2). As such, all 3 teams (MyFaces, Mojarra, Metawidget) have uncovered bugs in our implementations.
I'm delighted to say it looks like all these will be resolved in time for MyFaces 2.0.3 and Mojarra 2.2. For those interested in the 'correct' implementation of a dynamic JSF 2 component, as agreed by all teams, I've put together a little Acid Test that tests your JSF implementation for full compliance. In the process, it demonstrates the 'right' way to implement a dynamic JSF 2 component using SystemEvents. Which is:
public class UIAddComponent
extends UIComponentBase implements SystemEventListener {
public UIAddComponent() {
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
root.subscribeToViewEvent( PreRenderViewEvent.class, this );
}
public boolean isListenerForSource( Object source ) {
return ( source instanceof UIViewRoot );
}
public void processEvent( SystemEvent event )
throws AbortProcessingException {
if ( !FacesContext.getCurrentInstance().isValidationFailed() ) {
// Safely manipulate component tree here
}
}
}
extends UIComponentBase implements SystemEventListener {
public UIAddComponent() {
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
root.subscribeToViewEvent( PreRenderViewEvent.class, this );
}
public boolean isListenerForSource( Object source ) {
return ( source instanceof UIViewRoot );
}
public void processEvent( SystemEvent event )
throws AbortProcessingException {
if ( !FacesContext.getCurrentInstance().isValidationFailed() ) {
// Safely manipulate component tree here
}
}
}
My thanks to all teams for working so hard on this issue!
UPDATE 1: looks like this approach may be making it into the JSF spec: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1007
UPDATE 2: for AJAX requests, you also need to test partialViewContext.isAjaxRequest (see comments below)
