General JSF 1.2 Information
JSF 1.2 requires JSP 2.1, which is part of JavaEE 5.0. You cannot use JSF 1.2 against JSP 1.2 or JSP 2.0. But, the JSF RI and MyFaces 1.2.x do a fallback to Facelets, when you are not in a JavaEE 5 container.
JSF 1.2 is also provided by the application server, instead of being delivered by the web application as JARs in WEB-INF/lib. In particular, this means that we no longer use the Sun RI, or MyFaces, etc. - we simply use whatever implementation is provided by the server.
A proper JSF 1.2 application server must ignore any JSF 1.1 libraries that are left over in WEB-INF/lib.
Overhauled JSP integration
Better lifecycle, no more f:verbatim
Instead of mixing component tree building and rendering, JSP integration is now strictly two phase:
- build the component tree
- render the whole tree with UIViewRoot.encodeAll()
In particular, this revised approach means that f:verbatim is now a no-op, and is not needed at all. So, *do not use f:verbatim*.
Better ID assignment
A new JspIdConsumer API lets the JSF engine match components up to JSF tags predictably. You don't need to know the details of how it works, but we should see far fewer duplicate ID exceptions and should have automatic support for tr:forEach with varying numbers of children.
New EL APIs
JSF 1.2 supports the JavaEE 5 unified expression language (EL), which unifies the JSF and JSP expression languages. The old javax.faces.el APIs are deprecated, and replaced by javax.el APIs:
vb.getValue(context) => vb.getValue(context.getELContext())
The unified EL offers the following benefits:
- c:forEach works. HOWEVER it does not support varStatus, so we still have tr:forEach for that. But both work with all JSF tags, not just tr: tags.
- JSF EL has support for EL functions
Support for inherent type coercion. E.g., if a user provides an EL binding to a boolean that mistakenly returns the Strings "true" and "false", it still works - no ClassCastExceptions.
- Ordinary JSP EL has full access to managed beans.
- Better DT APIs.
BIG GOTCHA: Do *not* cast to UIComponentTag. There is a new UIComponentELTag class, which is what we're subclassing. Instead, cast to UIComponentClassicTagBase, which is a common superclass.
New Features of JSF 1.2
Improvements to f:attribute and f:validator
JSF 1.2 <f:validator> tag supports a "binding" attribute.
In JSF 1.1.x, the <f:attribute> immediately evaluates EL expressions instead of storing the expression on the component for later evaluation. The JSF 1.2 release includes this bug fix.
Little lesson in JSF 1.1: you *cannot* pass a clientId to UIComponent.findComponent(). It does not work. It will not, for instance, find rows in an <af:table>. Even if you think it's working, you can't actually use the component you get, because, for example, enclosed regions won't have set up their EL variables or entered any task flow bindings, etc.
UIComponent.invokeOnComponent() solves this. Pass it a clientId and an implementation of the new ContextCallback API, and the ContextCallback will get called back with the component instance *and* with all component and parent state properly initialized.
Use this feature with delicacy: it does require at least a partial tree traversal, so it should not be used hundreds of times per request.
The JSF APIs use generics, so say goodbye to casting from Object to UIComponent.
You can *and should* use the new resource-bundle element in faces-config.xml instead of using <f:loadBundle> in each JSP. It is more efficient and works perfectly well during phases other than Render Response.
- UIComponent.encodeAll() - handles encodeBegin()/encodeChildren()/encodeEnd(), etc.
- UIInput.resetValue() - the same as our UIXEditableValue.resetValue().
- UIComponent.getFacetCount() - returns the number of facets (most useful for seeing if there are any before iterating through).
UIComponent.getContainerClientId(). Used instead of UIComponent.getClientId() to identify the prefix used if a component is a NamingContainer. This has two benefits:
- A component can be a naming container *without* prepending anything to its ID (use delicately\!)
- UIXTable.getClientId() now will always return the table's client ID only no matter what row is set. If you need the client ID plus the row key, call getContainerClientId().
f:view now has a renderKitId that lets you set the renderKitId per page without mucking with faces-config.xml.
SelectItem.setValue() can take null without throwing an exception.
Trinidad and JSF 1.2
The following tags will disappear:
In both cases, the corresponding f:attribute and f:validator tags are now completely identical in functionality.