BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News JSF 2.2 and HTML5

JSF 2.2 and HTML5

Leia em Português

This item in japanese

Lire ce contenu en français

Though only a minor release, the updates in JSF 2.2, in particular the ability to pass through HTML attributes without the JSF components needing to be aware of them, are important for developers wanting to use HTML5 technologies in a JSF application.

Amongst the many new features in HTML5 are a series of new attributes for existing elements. Those attributes include things like the type attribute for input elements, supporting values such as text, search, email, url, tel, range, number, and date. Additionally there are a range of custom data attributes whose purpose is to attach small amounts of data to HTML elements. These aren't rendered, but can be read using JavaScript.

For a component based library such as JSF this presents a problem, since existing JSF components need to be updated in order to recognize the new attributes. For components that need to explicitly support them this makes sense, but in many cases a component doesn't need to do anything more than include the new attribute in the markup it ultimately produces. JSF 2.2 pass-through attributes do exactly that.

From a Facelet, pass-through attributes can be set in 3 ways:

1. Via a name-spaced attribute on the component tag:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://java.sun.com/jsf/passthrough">
<h:form>
<h:inputText value="#{bean.value}" p:placeholder="Enter text"/>
</h:form>
</html>

2. Using the child TagHandler f:passThroughAttribute that sets a single attribute:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:form>
<h:inputText value="#{bean.value}" >
<f:passThroughAttribute name="placeholder" value="Enter text" />
</h:outputText>
</h:form> 
</html>

3. Using the child TagHandler f:passThroughAttributes that sets multiple attributes:

<h:outputText value="Something" >
<f:passThroughAttributes value="#{bean.multipleAttributes}" />
</h:outputText>

#{bean.multipleAttributes} refers to a Map<String, Object>. The values for it can either be literals or a value expression.

Using Expression Language 3 (also part of Java EE 7), multiple attributes can also be directly defined using an EL expression:

<h:outputText value="Something" >
<f:passThroughAttributes value="{"one":1, "two":2, "three":3}" />
</h:outputText>

The upshot of these changes is that it is now possible for a developer to write the JSF view using pure HTML, an often cited advantage of rival frameworks such as a Wicket.

From the server end, attributes can be set in Java via the new getPassThroughAttributes() and getPassThroughAttributes(boolean create) methods in UIComponent, thus:

UIComponent component = new SomeComponent();
Map passThrough = component.getPassThroughAttributes();
passThrough.put("placeholder", "Enter text");

Along with the pass through capability, JSF 2.2 introduces a number of other significant enhancements including Faces Flow and Stateless Views.

Faces Flow

Faces Flow is inspired by ADF Task Flows and Spring Web Flow. It provides direct support for a flow that takes a user through a set of pages and a number of related use cases. A flow is defined as flow between "nodes", where a node can be:

  • A View: Any JSF page in the application
  • A Method Call: Invoke application logic from a flow graph via an EL
  • A Switch: Navigation decisions in the flow graph based on boolean EL
  • A Flow Call: Call another flow with parameters and receive return values
  • A Flow Return: Return to the calling flow

The nodes define the entry and exit points of a flow.

Two new annotations are introduced:

  • @FlowScoped is a CDI scope that defines the scope of a bean in the specified flow. This enables automatic activation/passivation of the bean when the scope is entered/exited.
  • @FlowDefinition is a class level annotation that allows the flow definition to be defined using the fluent FlowBuilder API.

Finally a new EL object, #{flowScope}, for flow local storage is also introduced. This maps to facesContext.getApplication().getFlowHandler().getCurrentFlowScope().

Stateless Views

Many frameworks, particularly component frameworks, are stateful. Not needing to maintain state though has some advantages. Perhaps the most important is that you avoid having to replicate the state across multiple nodes in a cluster, or using sticky-sessions to ensure that requests return to the node from which they originated. Other often cited advantages, however, are less clear-cut. Performance and Memory consumption can be an issue for stateful web frameworks, though in practice these tend to be trivial for the majority of enterprise applications. There is a performance hit for applying and saving state, though JSF 2.x's Partial State Saving, which means that only changes to state are updated, is pretty efficient, and similarly the amount of memory used to store state information is generally quite small.

JSF's stateless implementation is straightforward. The TagHandler for <f:view> now has a boolean attribute transient and passes it to UIViewRoot#setTransient. If the page is set to transient, the JSF StateManager doesn't store any data related to this view, and during restore view phase, the view is created with no state applied to it.

There are a huge number of other more minor changes. Arjan Tijms' article on J-Development gives a more exhaustive run-down.

Rate this Article

Adoption
Style

BT