What's new in JSF 2.3?

The process of developing JSF 2.3 started late september 2014, which is approximately 1.5 half year after JSF 2.2 was finalized. It currently has an anticipated release date of h2 2017, which is aligned with the anticipated release date of Java EE 8.

So what will be in JSF 2.3?

The official JSR gives some hints, but is a little vague in what will actually be done. This time around, there is little big upfront planning and because of resources the scope of new features is kept limited.

There have been a few important changes in the organization of the EG as well. While Ed Burns is still the spec lead, there is now a co-spec lead: Manfred Riem. As can be seen from the commit log, Manfred is currently most involved with working in the Mojarra source code. At a personal level, a big change is that both my co-worker Bauke (BalusC) as well as myself are now members of the JSF EG and are actively contributing to JSF.

So instead of merely monitoring the trunk of the reference implementation to see what's new as I did for JSF 2.2, I'll now be reporting from the inside ;)

Download

Latest JSF 2.3 snapshots
Latest JSF 2.3 milestones

Latest JSF 2.3 blog posts

The following is an excerpt of a list of blog posts from around the net about JSF 2.3 that I found interesting. The full list can be found on my ZEEF page.

New features

CDI

Injection and EL resolving of JSF artifacts (spec issue 1316) (partially)

JSF has traditionally used static entry methods and chaining to let the user obtain the various artifacts that it provides, such as the FacesContext, session map, external context, etc. The following gives a few examples of this:

FacesContext facesContext = FacesContext.getCurrentInstance()
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
Map<String, Object> cookieMap = FacesContext.getCurrentInstance().getExternalContext().getRequestCookieMap();
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
// etc

Especially the artefacts that have to be obtained by deep chaining can be problematic. Not only makes this the code verbose and hard to read, it can also be unclear to users that the view map has to be obtained via the view root but the cookie map via the external context as shown above.

Furthermore, the pattern makes it hard to override what is returned by the runtime. In JSF it IS possible to influence this by providing/setting a custom FacesContext, but especially for the deeper chained artefacts multiple levels or wrapping are then required, which is not always trivial to implement. The problem there is clearly that the abstraction is at the wrong level; providing an alternative view map requires a custom faces context, which provides a wrapped view root, which then finally provides the view map we wanted to provide.

A more modern approach in Java EE is to inject artefacts in order to obtain them (essentially flattening the lookup) and to provide alternative producers for those when the need to override them arises.

JSF 2.3 will therefore provide default producers for the most important artefacts, which at the moment being:

Artefact EL name Qualifier Type
Application #{application} - java.lang.Object (javax.servlet.ServletContext)
ApplicationMap #{applicationScope} @ApplicationMap java.util.Map<String, Object>
CompositeComponent #{cc} (Not injectable) javax.faces.component.UIComponent
Component #{component} (Not injectable) javax.faces.component.UIComponent
RequestCookieMap #{cookie} @RequestCookieMap java.util.Map<String, Object>
FacesContext #{facesContext} - javax.faces.context.FacesContext
Flash #{flash} - javax.faces.context.Flash
FlowMap #{flowScope} @FlowMap java.util.Map<Object, Object>
HeaderMap #{header} @HeaderMap java.util.Map<String, String>
HeaderValuesMap #{headerValues} @HeaderValuesMap java.util.Map<String, String[]>
InitParameterMap #{initParam} @InitParameterMap java.util.Map<String, String>
RequestParameterMap #{param} @RequestParameterMap java.util.Map<String, String>
RequestParameterValuesMap #{paramValues} @RequestParameterValuesMap java.util.Map<String, String[]>
Request #{request} (Not injectable) java.lang.Object (javax.servlet.http.HttpServletRequest)
RequestMap #{requestScope} @RequestMap java.util.Map<String, Object>
ResourceHandler #{"resource"} - javax.faces.application.ResourceHandler
Session #{session} (Not injectable) java.lang.Object (javax.servlet.http.HttpSession)
SessionMap #{sessionScope} @SessionMap java.util.Map<String, Object>
View #{view} - javax.faces.component.UIViewRoot
ViewMap #{viewScope} @ViewMap java.util.Map<String, Object>
ExternalContext #{externalContext} (new) - javax.faces.context.ExternalContext

The general types, in this case the maps, need an extra qualifier to avoid clashing with other producers. The JSF specific types however don't need such qualifier since JSF is the sole owner of these types.

Obtaining the JSF artefacts is therefore as easy as can be; one only needs to know the type of the artefact one wants. For example:

@Inject
private ExternalContext context;
For the ones that do need a qualifier, this qualifier has to be looked-up of course, but that's essentially a flat lookup. For example:
@Inject
@ApplicationMap
private Map<String, Object> applicationMap;
Furthermore, somewhat as a side-effect of Injection in more JSF artifacts, user created instances of the following artefacts are also injectable:
  • Converter
  • Validator
  • Behavior
This list is somewhat different, as we're not talking about say -the- Converter instance within the current scope, but about a specific named custom converter in the user's application. E.g.
@Inject
@FacesConverter(value = "myConverter", managed = true)
private Converter myConverter;
Note that this particular injection pattern is possible, but not entirely how things are normally done in CDI.

As far as the implementation side is concerned, there's a CDI Bean<T> instance (aka "default bean") provided for every artefact. Since the term "bean" already has a meaning in JSF and CDI is not profoundly clear about this term either, the RI implementation code calls them "dynamic producer", or just "producer". Maybe "factory" would be better, but that term has a bit of a history itself and we wanted to avoid using that one.

The following shows an example of a Bean<T>/dynamic producer for the HeaderValues artefact:

public class HeaderValuesMapProducer extends CdiProducer<Map<String, String[]>> {
    
    public HeaderValuesMapProducer() {
        super.name("headerValues")
             .scope(RequestScoped.class)
             .qualifiers(new HeaderValuesMapAnnotationLiteral())
             .types(
                 new ParameterizedTypeImpl(Map.class, new Type[]{String.class, String[].class}),
                 Map.class,
                 Object.class)
             .beanClass(Map.class)
             .create(e -> FacesContext.getCurrentInstance().getExternalContext().getRequestHeaderValuesMap());
    }
    
}

Commits for this feature have been done between 13/okt/14 and 21/sep/15.


Injection in more JSF artifacts (spec issue 1316) (partially)

In JSF 2.1 very few JSF artifacts were injection targets. In JSF 2.2 injection was made possible in a huge amount of additional artefacts but the very ones where injection actually matters most, converters and validators, were mysteriously left in the cold.

In JSF 2.3 this has now finally been taken care of as the following artefacts have been added to the list of injection targets:

  • javax.faces.convert.Converter
  • javax.faces.validator.Validator
  • javax.faces.component.behavior.Behavior

However, in contrast to the artefacts already on this list these new 3 are not automatically injection targets. They will only become so when a new attribute called "managed" on the corresponding annotations @FacesConverter, @FacesValidator and @Behavior is set to true. Furthermore all these 3 annotations have been upgraded to being CDI qualifiers by adding the @Qualified annotation to their definition.

The existing attributes of @FacesConverter, @FacesValidator and @Behavior have not been modified, meaning they are all *binding*, as is the new attribute "managed".

What happens behind the scenes now is that when JSF needs a converter it simply asks the CDI bean manager for a bean that implements Converter with a qualifier @FacesValidator that has the "managed" attribute set to true and the value (coverterId) or forClass attribute set to the right value (which is why it's important that these attributes are all binding).

It then wraps the bean returned by CDI in a delegating converter instance. This wrapper then delegates to the bean returned by CDI. This wrapper can be state-saved, but since the CDI bean is stored in a transient field it won't save&restore that. Instead, it will only save&restore the converterId or forClass. The restored wrapper will then use the JSF Application instance to ask for a converter with said converterId or forClass (which will go to CDI again, and will do the wrapping again, so we have a double wrapped converter at this point).

In effect the mechanism is essentially quite like the age old workaround of using an EL expression pointing to a managed bean for a converter or validator.

An example of a JSF 2.3 converter in which injection can take place:

@FacesConverter(value = "myConverter", managed = true)
public class MyConverter implements Converter {

    @Inject
    private MyService service;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        // Convert string to Object here
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        // Convert Object to String here
    }
}

Note that this new style converter must have a constructor as defined by CDI (a no-args one here) and the alternative constructor is not supported here.

Commits for this feature have been done between 14/Jan/15 and 15/jan/15.


Lifecycle

System event published after view rendered (spec issue 1135)

JSF 2 introduced the concept of system events, which are events that can be fired by arbitrary objects at arbitrary points during the request processing lifecycle.

In the current version JSF 2.2 there are some 20 events defined, e.g. PostAddToViewEvent, PostConstructViewMapEvent, PreValidateEvent, and specifically PreRenderViewEvent.

However, while there's a PreRenderViewEvent that's published right before a view is rendered, there's no event published right after. Such event can be useful for a variety of things, such as per view clean-ups, post rendering view processing, state handling, etc.

For these reasons and simply to be more consistent JSF 2.3 will add a new event called the PostRenderViewEvent, which as its name implies is published immediately after a view is rendered.

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:body>
        <f:event type="postRenderView" listener="#{myBean.doPostProcessing}" />
      
      <!-- Rest of view here -->
    </h:body>
</html>
Commits for this feature have been done on 31/jan/15.


Networking

WebSocket integration (spec issue 1396)

WebSocket support for JSF has been talked about for quite some time, and there are fairly advanced implementations available by now.

Still, just as with the AJAX support that was added in JSF 2.0 and was available in proprietary component libraries before that, WebSocket support was seen as fundamental enough to be put directly into the core spec.

Therefor JSF 2.3 will provide direct support for WebSockets via the new tag <f:websocket>.

An important detail of the JSF 2.3 implementation of WebSocket support is that it uses the WebSocket JSR and therefor integrates with the WebSocket support offered by the server on which JSF is running. Proprietary implementations are not rarely based on frameworks such as Atmosphere. Both approaches have their own cons and pros, and just as with AJAX support the user can typically choose what to use; the version offered by core JSF, or the one by a component library.

The tag supports a number of attributes, of which the primary required attribute is "channel". The value set here can be used to send notifications to, which will then be pushed to all instances of the socket with that channel name. The second required attribute is "onmessage". Here a client-side Javascript event handler can be set that is called whenever a push arrives from the server.

The following shows a minimal example of using the tag on a JSF view:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
>
    <h:head>
        Websocket Example
    </h:head>
    <h:body>
        <f:websocket channel="myChannel" onmessage="function(message){alert(message)}" />
    </h:body>
</html>

Receiving messages is one part of the process. The other part is of course to push out a message. This can be done via the new javax.faces.push.PushContext, which can be injected anywhere where CDI is available. The following shows an example:

@Named
@RequestScoped
public class SomeBean {

    @Inject @Push
    private PushContext myChannel;

    public void send(){
        myChannel.send("Hello, from the server by push!");
    }
}

The injected PushContext is associated with one specific named channel, which by default has the same name as the instance variable in which injection takes place ("myChannel" in the example above).

Integration between JSF and WebSocket revealed one spec related problem; the WebSocket spec now assumes that the application has statically defined a so-called EndPoint via java code. In the case of <f:websocket> such required EndPoint has to be created in a more dynamic way, during runtime, or at the very least allow a (CDI) extension to define one. Unfortunately neither is possible now, at least not officially (some implementations support it anyway).

For those implementations that do not support adding an EndPoint dynamically (at the moment only GlassFish/Tyrus), a fake one has to be defined by the application. This kind of end point server no other function than to activate the container's WebSocket implementation. At the moment this is only known to be needed for GlassFish. On Tomcat and JBoss (WildFly/Undertow) this is not needed.

The following is an example of this:

public class FakeEndpoint extends Endpoint {
    @Override
    public void onOpen(Session session, EndpointConfig config) {}
}

We will try to resolve this issue with the WebSocket EG, but due to the Java EE 8 hiatus it's unfortunately profoundly difficult to start a MR or revision for any spec that hasn't started one. As an alternative we may look into defining an SPI that each container that incorporates Mojarra has to implement, and in which WebSocket activation can be done in a proprietary way.

Due to unfinished work with the CDI integration, the following parameter now has to be set (to avoid clashes with a deprecated but still used switch that looks at the 2.3 version of a faces-config.xml file, if any).

<context-param>
 <param-name>javax.faces.ENABLE_CDI_RESOLVER_CHAIN</param-name>
 <param-value>true</param-value>
</context-param>
While the fake end point is used to initialise the container, the actual WebSocket end point needs to be started as well. This can't be done by default, since otherwise there will be an open socket even when WebSocket is never used. Fully dynamically creating the end point whenever an <f:websocket> is encountered is unfortunately even harder. Therefor another setting needs to be used:
<context-param>
 <param-name>javax.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name>
 <param-value>true</param-value>
</context-param> 

Further reading:

Commits for this feature have been done on 10/dec/15 and 14/mar/2016


Conversion / Validation

Class level bean validation (spec issue 1)

JSF has supported bean validation ever since JSF 2.0 was released. This support was however limited to validating individual properties bound to individual components. E.g. an input component bound to a password property of a backing bean.

Besides validating individual fields or properties, bean validation also has a concept of class level validation. This involves a special constraint validator that receives an instance of the class that has to be validated. This special validator can then do cross-field validations. For instance, check that two password fields are equal.

Class level validation does not play well with the JSF validation model though. In JSF the idea is that the model is not touched if validation fails. But to validate a class level constraint, we have to update the model with all values before proceeding. This problem was solved in OmniFaces by making a copy of the bean, storing the new values in that bean, and then validating the result.

This approach and some of the code have been standardized in JSF 2.3 by means of a new tag: <f:validateWholeBean>

Class level bean validation practically speaking most often applies to entities that have their own semantic constraints with associated validation code. Typically such entity is returned fully from a backing bean, but the properties of such entity are then bound to individual components. The OmniFaces example of class level bean validation demonstrates exactly this.

Another possibility is a more ad-hoc class level validation, for instance done by a backing bean. This can be used as a multi-field validator, where the multiple fields being validated are not necessarily part of a more structural and re-usable constraint. This usecase is in fact the major driver behind the very first JIRA issues for JSF; JAVASERVERFACES_SPEC_PUBLIC-1 which was filed in 2004!

Using class level bean validation for this usecase is slightly verbose and perhaps not a fully ideal match, but it does align well with the current strategy of delegating as much concerns as possible to existing functionality in Java EE instead of introducing native mechanisms that partially overlap with that existing functionality. We show an example of this below.

First of all, the new tag must be explicitly enabled in web.xml. If it's not enabled, the tag will do nothing. The following setting will take care of this:

<context-param>
    <param-name>javax.faces.validator.ENABLE_VALIDATE_WHOLE_BEAN</param-name>
    <param-value>true</param-value>
</context-param>

After this initial nuasance we can create a view with two input fields, and the mentioned <f:validateWholeBean> tag. There are a few things to be aware of here:

  1. At least one input component in the view must have a bean validation group set
  2. The <f:validateWholeBean> tag must appear AFTER all other input components
  3. The group for the input component(s) and the <f:validateWholeBean> tag must be the same
  4. The special default group (javax.validation.groups.Default) does not count, it's explicitly ignored.

The following gives an example:

<h:form>
    <h:inputText value="#{indexBean.foo}">
        <f:validateBean validationGroups="javax.validation.groups.Default,java.util.RandomAccess"/>
    </h:inputText>
    <h:inputText value="#{indexBean.bar}">
        <f:validateBean validationGroups="javax.validation.groups.Default,java.util.RandomAccess"/>
    </h:inputText>

    <f:validateWholeBean value="#{indexBean}" validationGroups="java.util.RandomAccess"/>

    <h:commandButton value="submit"/>
</h:form>

In order to keep the example as small as possible I re-used an existing "random" interface for the group marker. Note that the default group javax.validation.groups.Default is also added to make sure individual fields are still bean validated as well.

Next thing is the backing bean itself. In order to use class level bean validation the following has to be done:

  1. An annotation has to be defined that adheres to the bean validation spec for class level constraints
  2. A constraint validator implementation has to be provided, which takes care of the actual validation
  3. The backing bean has to be annotated with that annotation
  4. The annotation's groups attribute has to be set to the same group that was used in the view
The following gives an example of this:
@Named
@RequestScoped
@ValidIndexBean(groups = java.util.RandomAccess.class)
public class IndexBean implements ConstraintValidator<ValidIndexBean, IndexBean> {

    @Constraint(validatedBy = IndexBean.class)
    @Documented
    @Target(TYPE)
    @Retention(RUNTIME)
    public @interface ValidIndexBean {
        String message() default "Invalid Bean";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }

    @Override
    public void initialize(ValidIndexBean constraintAnnotation) {
        //
    }

    @Override
    public boolean isValid(IndexBean other, ConstraintValidatorContext context) {
        return other.getFoo().equals(other.getBar());
    }

    @NotNull
    private String foo;

    @NotNull
    private String bar;

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

As mentioned this is indeed slightly verbose for a one-off multiple fields validation. Specifically the verbosity of the annotation is hard to reduce in this case. A default annotation for cases like this would probably help a lot, but at the moment there's none (at least not that I know of). The unneeded initialize method could be solved if the bean validation spec used a default method in the interface for this. Unfortunately there's no bean validation spec update or even MR planned at the moment.

Note that the other instance that the isValid method receives is a "copy" of the same bean. However, currently it's not really a copy but a new instance. The JSF 2.3 implementation code principally has the same copiers available as the ones for the OmniFaces version, but because of what seems to be a bug only the so-called NewInstanceCopier actually seems to be used in practice. Unlike in OmniFaces, it's also not currently possible to explicitly select a copier strategy or provide a custom one.

Further reading:

Commits for this feature have been done between 18/sep/15 and 28/sep/15 and the associated issue has been marked as resolved.


JDK 8 time support in f:convertDateTime (spec issue 1370)

JSF 2.3 will have Java 8 as a minimum dependency. One of the big advantages of this is that it's actively able to support new features in Java 8. One of those features concern the new data and time classes in JDK 8, otherwise known as JSR 310.

JSF 2.3 will provide support for these using its existing <f:convertDateTime> converter. In JSF 2.2 and before the type attribute of this converter only supported the values "date", "time" and "both". For JSF 2.3 this has been expanded with various values as shown in the table below:

Type attribute Class involved Default when pattern not specified
both java.util.Date DateFormat.getDateTimeInstance(dateStyle, timeStyle)
date java.util.Date DateFormat.getDateTimeInstance(dateStyle)
time java.util.Date DateFormat.getDateTimeInstance(timeStyle)
localDate java.time.LocalDate DateTimeFormatter.ofLocalizedDate(dateStyle)
localTime java.time.LocalTime DateTimeFormatter.ofLocalizedTime(dateStyle)
localDateTime java.time.LocalDateTime DateTimeFormatter.ofLocalizedDateTime(dateStyle)
offsetTime java.time.OffsetTime DateTimeFormatter.ISO_OFFSET_TIME
offsetDateTime java.time.OffsetDateTime DateTimeFormatter.ISO_OFFSET_DATE_TIME
zonedDateTime java.time.ZonedDateTime DateTimeFormatter.ISO_ZONED_DATE_TIME

In addition the pattern attribute has changed as well. In JSF 2.2 when this pattern attribute was set, the other attributes were ignored and java.text.SimpleDateFormat was used exclusively. In JSF 2.3 if the type attribute is set to any of the new JDK 8/JSR 310 values then java.time.format.DateTimeFormatter will be used instead. In all cases the pattern attribute still overrides the timeStyle and dateStyle attributes.

Example of usage:

<h:inputText value="#{myBean.startTime}">
    <f:convertDateTime type="localDateTime" />
</h:inputText>

<h:outputText value="#{myBean.endDate}">
    <f:convertDateTime type="localDate" pattern="dd.MM.uu" />
</h:outputText>

Further reading:

Commits for this feature have been done between 29/sep/15 and 2/oct/15 and the associated issue has been marked as resolved.


Java API

Support for the Iterable interface in UIData and UIRepeat (spec issue 1103)

From the beginning of JSF, the UIData component (known from e.g. <h:dataTable>) and UIRepeat (known from e.g. <ui:repeat>) only realistically supported the List, native array and JSF specific DataModel as input for its value binding. This meant other collection types had to be expressed as one of these types.

In JSF 2.2 UIData was extended to support Collection as well, but UIRepeat was mysteriously left out (which is one reason why UIRepeat should really share common functionality with UIData; it happens much more often that both should be updated but only one of them is)

The thing is that while Collection support is nice, it's actually just as easy to support Iterable. It's perhaps a small oversight that this was not supported right from the beginning, but in JSF 2.3 this will finally be addressed.

Just as with the Collection support in 2.2, Iterable will be added to the bottom of the list of types being checked, so for Iterables that are also a List or Collection (in case of UIData), the existing code will take precedence.

The following are now the supported types for UIData:

  • null (becomes empty list)
  • javax.faces.model.DataModel
  • java.util.List
  • java.lang.Object[]
  • java.sql.ResultSet
  • javax.servlet.jsp.jstl.sql.Result
  • java.util.Collection
  • java.lang.Iterable new!
  • java.lang.Object (becomes ScalarDataModel)

And the following are the supported types for UIRepeat:

  • null (becomes empty list)
  • javax.faces.model.DataModel
  • java.util.List
  • java.lang.Object[]
  • java.sql.ResultSet
  • java.lang.Iterable new!
  • java.lang.Object (becomes ScalarDataModel)

Note that both Result and Collection are missing for UIRepeat. The latter will be handled by Iterable, since it's the base class of Collection. Result is actually missing, likely because its JSP specific and UIRepeat was designed specifically for Facelets).

Commits for this feature have been done on 2/mar/15 and the associated issue has been marked as resolved.


Support for the Map interface in UIData and UIRepeat (spec issue 1364)

Besides support for the Iterable interface in UIData and UIRepeat, JSF 2.3 will also add support for maps. The way this is done is closely aligned with how JSTL has supported maps for many years:

Existing JSTL based looping through a map

<c:forEach var="entry" items="${myMap}">
  Key: <c:out value="${entry.key}"/>
  Value: <c:out value="${entry.value}"/>
</c:forEach>
New JSF 2.3 based looping through a map using ui:repeat
<ui:repeat var="entry" value="#{myMap}">
    Key: #{entry.key}
    Value: #{entry.value}
</ui:repeat>
New JSF 2.3 based looping through a map using h:dataTable
<h:dataTable var="entry" value="#{myMap}">
    <h:column>#{entry.key}</h:column>
    <h:column>#{entry.value}</h:column>
</h:dataTable>

Including the Iterable support from the previous feature and the Map support discussed here, the following are now the supported types for UIData:

  • null (becomes empty list)
  • javax.faces.model.DataModel
  • java.util.List
  • java.lang.Object[]
  • java.sql.ResultSet
  • javax.servlet.jsp.jstl.sql.Result
  • java.util.Collection
  • java.lang.Iterable new!
  • java.util.Map new!
  • java.lang.Object (becomes ScalarDataModel)

And the following are the supported types for UIRepeat:

  • null (becomes empty list)
  • javax.faces.model.DataModel
  • java.util.List
  • java.lang.Object[]
  • java.sql.ResultSet
  • java.lang.Iterable new!
  • java.util.Map new!
  • java.lang.Object (becomes ScalarDataModel)

Commits for this feature have been done on 18/mar/15.


Support for custom types in UIData and UIRepeat (spec issue 1078)

A third new feature in JSF 2.3 next to support for the Iterable interface in UIData and UIRepeat, and support for the Map interface in UIData and UIRepeat is support for custom types.

This has been requested for a long time, and JSF 2.3 will now (finally) provide this support. The way this is done is by creating a wrapper DataModel for a specific type, just as one may have done years ago when returning data from a backing bean, and then annotating it with the new @FacesDataModel annotation. A “forClass” attribute has to be specified on this annotation that designates the type this wrapper is able to handle.

The following gives an abbreviated example of this:

@FacesDataModel(forClass = MyCollection.class)
public class MyCollectionModel<E> extends DataModel<E> {
    
    @Override
    public E getRowData() {
        // access MyCollection here
    }

    @Override
    public void setWrappedData(Object myCollection) {
        // likely just store myCollection
    }

    // Other methods omitted for brevity
}

Note that there are two types involved here. The “forClass” attribute is the collection or container type that the DataModel wraps, while the generic parameter E concerns the data this collection contains. E.g. Suppose we have a MyCollection<User>, then “forClass” would correspond to MyCollection, and E would correspond to User. If set/getWrappedData was generic the “forClass” attribute may not have been needed, as generic parameters can be read from class definitions, but alas.

With a class definition as given above present, a backing bean can now return a MyCollection as in the following example:

@Named
public class MyBacking {
    public MyCollection<User> getUsers() {
        // return myCollection
    }
}
h:dataTable will be able to work with this directly, as shown in the example below:
<h:dataTable value="#{myBacking.users}" var="user">
    <h:column>#{user.name}</h:column>
</h:dataTable>

Further reading:

Commits for this feature have been done on 13/jul/15 and 15/jul/15.


Type-safety

Generics for ExternalContext#getInitParamterMap (spec issue 1382)

Quite a number of types in JSF originate from before generics were available in Java. In subsequent releases Java 5 was targeted and existing types and methods were extended with generic parameters.

One of the methods that was missed before is ExternalContext#getInitParamterMap, which returns a raw Map in JSF 2.2 and earlier.

In JSF 2.3 this has been corrected and ExternalContext.html#getInitParameterMap now returns a Map<String, String>.

Commits for this feature have been done on 26/aug/15.


Generics for Converter and Validator interfaces (spec issue 1355)

Both the Converter and Validator interfaces in JSF take an Object as their input value. Implementations then typically demand that this Object is of a specific type and that otherwise an exception should be thrown.

This contract predates generics and instead of demanding such type constraint via JavaDoc one can far better express this via a generic parameter. In JSF 2.3 both interfaces have now been parameterized and implementations can concisely define the exact input type, and in case of the Converter interface additionally the exact return type.

This updated interfaces are shown below:

public interface Converter<T> {
  T getAsObject(FacesContext context, UIComponent component, String value);
  String getAsString(FacesContext context, UIComponent component, T value);
}
public interface Validator<T> {
  void validate(FacesContext context, UIComponent component, T value);
}

Note that the myriad of existing Converter and Validator implementations in JSF have not been parameterized and are raw types. The reason for this is backwards compatibility.

E.g. in some obscure but possible cases code could actually depend on passing an Object to some Converter implementation. Even when such Object could only be of say type Foo, then actually typing the constructor as accepting only Foo will not compile anymore. A variety of other even more obscure but theoretical possible incompatibilities were discovered as well. One could ask how generics can ever have been introduced in the JDK itself for existing types, but even there some compromises were made (like the infamous Map#get taking an Object as input instead of the generic parameter for the key).

New converters and validators can of course take advantage of the new generic parameters, but existing ones in JSF have been frozen in time and can never change.

Commits for this feature have been done between 30/jul/15 and 18/aug/15.


Configuration

Facelets default to non-hot reload in production (spec issue 936)

JSF has the ability to cache Facelets. Caching here means that the result of the XML parsing and compilation step is kept in memory, e.g. Facelets will not read the XML from disk at every request and will not reparse that XML either. (it will however still do the composition of includes and templates at every request)

While the default is not specified, the RI (Mojarra) uses a default of 2 seconds before it looks on disk again if the source file has changed or not. There is a setting to control this default, namely the javax.faces.FACELETS_REFRESH_PERIOD context parameter in web.xml. For example, the following sets a timeout of 10 seconds:

<context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>10</param-value> <!-- Cache for 10 seconds -->
</context-param>

There are two special values; -1 means no refresh (cache indefinitely), while 0 means no caching at all (always hot reload).

For production usage there really is only 1 sensible value, and that's -1, as the Facelets source files will of course not change during production.

JSF 2.0 introduced a setting to indicate the stage its in, which includes the Production stage.

JSF 2.3 now finally adds one and one together and defines that when the project stage is Production (which incidentally is the default stage) the Facelets refresh period is -1 (no refresh).

Commits for this feature have been done on 25/feb/15.



That's it for now! I'll periodically update this page to cover the latest JSF 2.3 developments. In the short term this may be a dedicated folder to store views and a generic parameter adding to the Converter and Validator interfaces, but this is all preliminary. Arjan Tijms

9 comments:

  1. Great, it will avoid some boilerplate code.

    ReplyDelete
  2. Galera aqui só usa Mac OSX. Fico pensando onde o Swift se coloca nessa história.

    ReplyDelete
  3. But I feel like there are tons of things that should be implemented.
    On the top of my head:

    1. Ability to ajax render the head tag. (why the hell it's not there already ?)
    2. Ability to use outputScript for external js. Why ? Because of number 3.
    3. Ordering resources in the head tag is a fucking guess work. "Has target=head even though it's in the head already ?" Go first. Be external script and last mentioned ? You go first. It's just insane. At least something like primeface f:facet = first.
    4. Make all not recognized attributes passThrough, why the flying monkey not?
    5. build and render break the encapsulation by making the developer having to think about it. Just make it work in all case somehow.
    6. No inline javascript option ?

    I've made renderers for this but it's annoying to have to retrofit it when I will update to JSF 2.3

    ReplyDelete
  4. Hi Arjan. How will server push be incorporated into JSF 2.3? From the J1 presentation by Ed Burns he moted the idea that the PushBuilder would be used in the ExternalContext.encodeResourceURL() method to push resources to the client. I have not found any information other than his presentation that confirms that this. I wondered if you have a comment on this. Thanks in advance.

    ReplyDelete
    Replies
    1. Hi Alex,

      The JavaOne presentation from Ed Burns hinted at how HTTP2 push might be incorporated into JSF. This form of push is a kind of pre-emptive pushing; the server pushes things to the client for which it anticipates the client will need it.

      The is slightly different from the current support for push in JSF 2.3 (http://arjan-tijms.omnifaces.org/p/jsf-23.html#1396), which is based on WebSockets, and where such socket is explicitly set up by the client.

      Due to a series of issues mostly relating to resource allocation at Oracle, the HTTP2 pre-emptive pushing has not been researched yet. Because of those same resource allocations problems, a practical issue is that the proposed Servlet 4.0 HTTP2 support has not been implemented yet in GlassFish, and since the GF team has other priorities it's not planned even to do implement it (see https://java.net/projects/javaee-spec/lists/users/archive/2016-05/message/2).

      Without HTTP2 being implemented in GlassFish (which is the RI), Mojarra (JSF RI) can not easily target that API, so the research and prototypes can not really start.

      Delete