Sunday, October 2, 2022

OmniFaces 4.0 has been released!

OmniFaces 4.0 has been released!

Finally, as a response to the Jakarta EE 10 release on 22 September 2022, OmniFaces 4.0 is now final after a long serie of milestones!

It's basically the Jakartified version of 3.14 with a few breaking changes. OmniFaces 4.0 is compatible with Faces 4.0 from Jakarta EE 10 as well as Faces 3.0 from Jakarta EE 9.1. OmniFaces 4.0 requires a minimum of Java 11.

Breaking changes

  • Minimum dependencies are changed from Java 1.8, JSF 2.3, EL 3.0, Servlet 3.1, CDI 2.0, WS 1.1 and BV 2.0 to Java 11, Faces 3.0, EL 4.0, Servlet 5.0, CDI 3.0, WS 2.0 and BV 3.0; as of now, OmniFaces 4.0 is NOT backwards compatible with previous versions of these dependencies because of the compiler-incompatible rename of the javax.* package to jakarta.* package.
  • All things which were during 3.x @Deprecated have been physically removed, such as <o:form includeViewParams="true"> (has become the default behavior), WebXml.INSTANCE and FacesConfigXML.INSTANCE (replaced by WebXml.instance() and FacesConfigXml.instance() respectively), and omnifaces:fixviewstate.js (replaced by JSF 2.2 native fix)
  • #{now} and #{startup} will now return an instance of java.time.temporal.Temporal instead of java.util.Date; it still supports the time property as in #{now.time} and #{startup.time} in a backwards compatible manner; additionally, it's got two new convenience properties: instant and zonedDateTime as in #{now.instant}, #{now.zonedDateTime}, #{startup.instant} and #{startup.zonedDateTime}.
  • Callback interfaces which dated from Java 1.7 and have replacements available in Java 1.8 are now @Deprecated. Callback.Void is replaced by Runnable, Callback.Returning is replaced by Supplier, Callback.WithArgument is replaced by Consumer and Callback.ReturningWithArgument is replaced by Function. Utility methods in Components and Events are have been adjusted to use the new types. True, this could have been done during the OmniFaces 3.x era, but this was simply completely overlooked.

New things

There's a new utility method important for component library authors who'd like to be compatible with both Faces 3.0 and 4.0: Components#addFacesScriptResource(). This will allow the component developer to support both Faces 3.0 jakarta.faces:jsf.js and Faces 4.0 jakarta.faces:faces.js as resource dependency. This utility method exists because it is technically not possible to use a variable as an attribute of the annotation such as @ResourceDependency. In other words, something like below won't work because it's not allowed by the Java compiler:

@FacesComponent
@ResourceDependency(library="jakarta.faces", name=(isFaces4() ? "faces.js" : "jsf.js"), target="head")
public class YourCustomComponent extends UISomething {
    // ...
}

It really has to be compile time constant. So the best way to go is to perform this in a constructor with help of Events#subscribeToRequestBeforePhase() and Components#addFacesScriptResource().

@FacesComponent
public class YourCustomComponent extends UISomething {
   
    public YourCustomComponent() {
        Events.subscribeToRequestBeforePhase(RENDER_RESPONSE, Components::addFacesScriptResource);
    }

    // ...
}

Another new thing is that the Faces#addResponseCookie() got a new overload accepting a new Map<String, String> argument representing custom attributes to be added to the cookie. This way you can add e.g. SameSite:None to the cookie.

You can find the complete list of additions, changes and fixes at What's new in OmniFaces 4.0? list in showcase.

As a refresher, you can find everything about new things in Faces 4.0 in this blog post: What's new in Faces 4.0?

Changed things

The omnifaces.js is now not anymore sourced by "plain vanilla JavaScript", but by TypeScript. The biggest advantage of TypeScript is that it allows us to transpile the exact same source code to an older ES version such as ES5 or even ES3 for ancient webbrowsers. It's the idea to do the same for Jakarta Faces own faces.js. The omnifaces.js is currently targeted at ES5, so it's compatible with the browsers listed here.

Integration tests

Currently, all integration tests pass successfully on the following servers:

  • WildFly 27 (Mojarra 4)
  • WildFly 26 (Mojarra 3)
  • GlassFish 7 (Mojarra 4)
  • GlassFish 6 (Mojarra 3)
  • TomEE 9 (MyFaces 3)
  • Tomcat 10 + Mojarra 4
  • Tomcat 9 + Mojarra 3
  • Tomcat 9 + MyFaces 3

The following servers were also available but are deactivated because not all integration tests pass:

  • Liberty 21.0.0.12-beta -- because of deployment timeout on EagerIT and ParamIT for a yet unclear reason; probably related to CDI extension
  • Tomcat 10 + MyFaces 4.0.0-RC1 -- because every subsequent Ajax form submit isn't seen as type=XHR but as type=NONE by Graphene
  • Piranha -- because it explicitly requires JDK17 and a newer Arquillian/Selenium version which isn't yet supported by all other servers

This will be investigated and fixed later on.

Installation

Non-Maven users: download OmniFaces 4.0 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.

Maven users: use <version>4.0</version>.

<dependency>
    <groupId>org.omnifaces</groupId>
    <artifactId>omnifaces</artifactId>
    <version>4.0</version>
</dependency>

In case you're still on JSF 2.3, then use 3.14. With this version, the 3.x branch will enter maintenance mode like as 2.x. For now.

How about OmniFaces 2.x and 1.1x?

The 2.x got the same bugfixes as 3.14 and has been released as 2.7.20. This version is for JSF 2.2 users with CDI. In case you've already migrated to JSF 2.3, use 3.x instead. Or in case you've already migrated to Faces 3.0 or 4.0, use 4.x instead.

The 1.1x is basically already since 2.5 in securityfix mode. I.e. only security-related bugfix versions will be released. It's currently still at 1.14.1 (May 2017), featuring the same features as OmniFaces 2.4, but without any JSF 2.2 and CDI things and therefore compatible with CDI-less JSF 2.0/2.1.