Next to a bunch of utility methods, this version adds a MessagesKeywordResolver and a SourceMapResourceHandler. This version also deprecatesWebXml.INSTANCE and FacesConfigXml.INSTANCE with as replacement the WebXml.instance() and FacesConfigXml.instance() respectively via an interface instead of an enum. This way they can easier be mocked during unit testing.
You can find the complete list of additions, changes and fixes at What's new in OmniFaces 3.1? list in showcase.
Installation
Non-Maven users: download OmniFaces 3.1 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.
This way, only the message components are updated on submit. This is more efficient than e.g. render="@form" which unnecessarily also updates the input and button components.
SourceMapResourceHandler
If you've more than often debugged minified CSS/JS resources in browser developer toolset, you'll probably ever have heard of "source maps", usually referenced by a code comment somewhere in the bottom of the minified file, such as /*# sourceMappingURL=some.js.map */. To the point, these files represent the mapping between the minified version and the unminified version, so that the browser developer toolset can after downloading the source map file automatically unminify the minified version, whereby the original variable names are substituted back.
Very useful, particularly for minified/uglified JS resources. Unfortunately, resolving the source map files doesn't always work well with suffix-mapped JSF resources which uses a virtual URL pattern with /javax.faces.resource/ prefix and .xhtml suffix. The average CSS/JS compiler/minifier also has no knowledge about the way how JSF resources are being served. Fortunately, source map URLs can be set by a SourceMap header on the response of the CSS/JS resource. This is thus exactly what the SourceMapResourceHandler does.
It can be installed in the JSF application by below entry in faces-config.xml:
It will by default asusme that the source map files are by the build tool placed in the same folder as the minified resources and have a .map extension appended to the resource name. So it will work when you have a some.js resource and a some.js.map file in the same folder. In case it's by the build tool being placed in a subfolder as in sourcemaps/some.js.map, then you can use the below web.xml context parameter to instruct the SourceMapResourceHandler on this.
2.x is basically already since 2.6 in maintenance mode. I.e. only bugfix versions will be released. It's currently already at 2.6.9, also released today. As long as you're still on JSF 2.2 with CDI, you can continue using latest 2.6.x, but it won't contain new things introduced in 3.x.
1.1x is basically already since 2.5 in maintenance mode. I.e. only 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.
Maven download stats
Here are the 2018's Maven download stats so far:
January 2018: 14646
February 2018: 14786
March 2018: 18059
Below is the pie of March 2018, 3.0 is already on 9%:
No, JSF 2.4 is not there yet. Technically speaking, Mojarra 2.4.0 represents the latest state of the master branch as it was during the transfer from Oracle to Eclipse. That transfer took place when JSF 2.3 specification was already released and JSF 2.4 specification has still to be started yet. JSF 2.4 is far from being a beta, let alone a reasonable snapshot. And yet there is a Mojarra 2.4.0 in Maven instead of e.g. a Mojarra 2.4.0-M1. As per the agreement between Oracle and Eclipse, it was necessary to release the latest work on Mojarra under Oracle's umbrella into Maven Central before the transfer to Eclipse was completed. And later Eclipse will do the same after the transfer is completed so that the integrity can be validated by the public. Using version "2.4.0" is indeed way confusing for the public, but it is what it is.
In other words, you should not use it. A few days later, Mojarra 2.3.4 was also released. Use this instead.
Technically speaking, Mojarra 2.4.0 is even a step back from Mojarra 2.3.4 as to bugfixes. Mojarra 2.4.0 misses among others the fixes on issues
4274,
4313,
4321,
4324,
4330,
4331,
4332,
4337 and
4358.
After the transfer to Eclipse, we'll as first step change the package name (and thus also the Maven coordinates). We already have a lot of other plans on it. High in our wishlist is removing everything which is @Deprecated and JSP related.
The minimum requirements have been upgraded from Java 1.7, JSF 2.2, EL 2.2, Servlet 3.0, CDI 1.1 and (optional) BV 1.1 to Java 1.8, JSF 2.3, EL 3.0, Servlet 3.1, CDI 2.0 and (optional) BV 2.0. WebSocket 1.1 hasn't been upgraded since, so it's still the same. As of now, OmniFaces 3.0 is technically still backwards compatible with EL 2.2, CDI 1.1 and BV 1.1, as features in newer versions are still unutilized, but that may change in a future 3.x version. OmniFaces 3.0 will explicitly prevent deployment when Java 1.8, JSF 2.3 or CDI 1.1 are absent in the environment.
As shown in what's new in OmniFaces 3.0 at the showcase site, below is a summary of breaking changes, new things and deprecated things in OmniFaces 3.0 as compared to OmniFaces 2.6.8, which is also released today.
Breaking changes:
<o:form useRequestURI="true"> is now the default behavior of <o:form> as it was basically the main reason to use <o:form>. I.e. it will always submit to exactly the same URL as in browser's address bar whereas the <h:form> only submits to the forwarded URL without query string, causing among others view parameters and path parameters to get lost every time. You can if necessary disable this by <o:form useRequestURI="false"> or switching back to <h:form>.
<o:form> will now by default perform a partial submit on any JSF ajax request. In other words, only the parameters actually covered by execute attribute of <f:ajax> will be sent, hereby reducing the request payload to not contain unnecessary parameters. This is similar to PrimeFaces partialSubmit feature. Even though this has proven to work flawlessly in PrimeFaces for ages, you can if necessary disable this by <o:form partialSubmit="false">.
<o:validateBean showMessageFor="@violating"> will not anymore show the "remaining" messages (coming from other bean properties which are not covered by the JSF form) as a global message but just suppress them.
ValidateMultipleFields (all multi-field validators basically) have previously skipped all disabled/readonly/nonrendered inputs. Now they won't anymore be skipped, and the values argument (3rd argument of validate method) will contain their current model value (and thus not the submitted value).
Package org.omnifaces.component.output.cache has been migrated to org.omnifaces.util.cache and several previously private/hidden artifacts have been made public, so that it's now more useful for non-component related caches.
All Faces/FacesLocal/Components/Servlets methods which previously threw IOException will now throw Java8's java.io.UncheckedIOException instead, hereby reducing down unnecessary throws IOException boilerplate in methods because those should always be bubbled up into the container.
org.omnifaces.facesviews.FacesServletDispatchMethod and ViewHandlerMode which was deprecated since 2.6 have now been removed without replacement (as they have become superfluous since Servlet 3.0).
org.omnifaces.renderkit.Html5RenderKit which was deprecated since 2.2 has now been removed without replacement (as this has become superfluous since JSF 2.2 with new passthrough attribtue feature).
org.omnifaces.config.BeanManager which was deprecated since 2.5 has now been removed with org.omnifaces.util.Beans as replacement.
RichFaces targeted hacks have been removed. OmniFaces 3.0 is therefore not anymore compatible with RichFaces. Note that RichFaces itself was declared "End of Life" June 2016 and is already not compatible with JSF 2.3.
New things:
<o:selectItemGroups> has been added which should remove the need to manually bake SelectItemGroup/SelectItem[] instances in beans as there's (still) no corresponding tag in standard JSF for this.
<o:url> has been extended with a value attribute which can take an arbitrary/external URL.
omnifaces.ImplicitNumberConverter which extends <f:convertNumber>, but doesn't annoyingly require enduser to explicitly input the percent or currency symbol when using type="percent" or type="currency".
org.omnifaces.eventlistener.FacesRequestLogger phase listener is introduced which will print detailed logs of JSF requests, including request method/URI/params, session/viewstate ID, remote user, action method expressions, faces messages and phase timings.
Faces#isRequestSecure()/Servlets#isSecure() has been added which also checks the de-facto X-Forwarded-Proto header which returns the protocol as obtained by the proxy. Useful in case the server runs HTTP but proxy runs HTTPS.
#{of:parenthesize(object)} has been added which will print parenthesis around the given object only and only if it isn't null nor empty nor equals zero.
NoAutoGeneratedIdViewHandler will now also recognize prependId="false" and log a warning because this is bad practice.
Under the covers, many things are replaced by new JSF 2.3 API things (among others, a bunch of new constants, improved faces wrappers and ResourceHandler#markResourceRendered() / isResourceRendered()) and also Java8 lambdas and streams have been introduced where possible.
Deprecated things:
<o:commandScript> has been deprecated as it's now moved into JSF 2.3 as <h:commandScript> with exactly the same functionality.
fixviewstate.js has been deprecated as it's now finally solved in JSF 2.3 (by yours truly).
<o:form includeViewParams="true"> as well as <o:form includeRequestParams="true"> have been deprecated as those have never proven to be more useful than useRequestURI="true".
Noted should be that the <o:socket> is also moved into JSF 2.3 as <f:websocket> with here and there a few small API generifications. But this won't be deprecated anywhere in OmniFaces 3.x as it still has room for new ideas and improvements.
As to new things, the benefits of <o:selectItemGroups>, omnifaces.ImplicitNumberConverter and Faces#getXxxAttribute() overloads are detailed below.
Not anymore explicitly creating new SelectItemGroup()
When grouping select item options in a <optgroup>, you had to manually bake SelectItemGroup instances yourself. Assuming that you have List<Category> as wherein Category in turn has a List<Product>:
private Product selectedProduct;
private List<SelectItem> categories;
@Inject
private ProductService productService;
@PostConstruct
public void init() {
categories = productService.listCategories().stream().map(category -> {
SelectItemGroup group = new SelectItemGroup(category.getName());
group.setSelectItems(category.getProducts().stream()
.map(product -> new SelectItem(product, product.getName()))
.toArray(SelectItem[]::new));
return group;
}).collect(Collectors.toList());
}
This is too much JSF 1.0. Even in JSF 2.3, there's still nothing like <f:selectItemGroups>. OmniFaces 3.0 therefore brings a <o:selectItemGroups> into the game.
However, this would surprisingly fail with a conversion error when the enduser doesn't explicitly specify the currency symbol in the input field.
Price $
'12.34' could not be understood as a currency value. Example: $99.99
Of course you could work around it by replacing type="currency" with pattern="#,##0.00". But this is embarrassingly harder to remember than just type="currency" and even prone to locale-specific differences. In some locales the fractions are optional or even omitted. And what if the enduser thought to enter the currency symbol anyway?
Entering the currency symbol has now become optional and it will be inferred when absent. On outputting, it will be hidden from the output and it will be assumed that the user interface already covers this. The same facility is also available for type="percent".
Not anymore explicitly checking if scoped attribute exists
You might have repeatedly stumbled into the below use case in some non-managed JSF artifact (where you'd otherwise of course just have used CDI):
public SomeObject getSomeObject() {
SomeObject someObject = Faces.getRequestAttribute(SomeObject.class.getName());
if (someObject == null) {
someObject = new SomeObject();
Faces.setRequestAttribute(SomeObject.class.getName(), someObject);
}
return someObject;
}
The getRequest/Flash/View/Session/ApplicationAttribute() methods have now all an overload which takes a Supplier<T>. The usage is now much like Map#computeIfAbsent().
public SomeObject getSomeObject() {
return Faces.getRequestAttribute(SomeObject.class.getName(), SomeObject::new);
}
Not anymore explicitly rethrowing IOException
Some utility methods in Faces throw IOException when something fails during handling the HTTP response. Generally this is unavoidable, such as end user facing a local network error. Those exceptions are documented to be rethrown. For example,
@PostConstruct
public void init() throws IOException {
if (someCondition()) {
Faces.redirect("other.xhtml");
}
}
However, redeclaring this everytime is tiresome and moreover, in this specific example it goes against the @PostConstruct contract as it may actually not throw a checked exception. Weld will even warn about this during webapp startup.
With OmniFaces 3.0, all methods which previously threw IOException will now throw it as Java 8's new UncheckedIOException instead. So you can safely strip out any unnecessary throws IOException coming from Faces/FacesLocal/Servlets utility methods over all place.
@PostConstruct
public void init() {
if (someCondition()) {
Faces.redirect("other.xhtml");
}
}
Installation
Non-Maven users: download OmniFaces 3.0 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.
Don't panic. I wrote a clean set of installation instructions in Mojarra README. In a nutshell, for Tomcat 8.x you just need to upgrade the JARs and add JSONP API as compared to Mojarra 2.2 (with CDI + BV). For Java EE 7 (e.g. WildFly 8-11.x, Payara 4.x, TomEE 7.x, etc) you need to manually swap out server-provided JARs as instructed in the README.
How about OmniFaces 2.x and 1.1x?
2.x is basically already since 2.6 in maintenance mode. I.e. only bugfix versions will be released. It's currently already at 2.6.8, also released today. As long as you're still on JSF 2.2 with CDI, you can continue using latest 2.6.x, but it won't contain new things introduced in 3.x.
1.1x is basically already since 2.5 in maintenance mode. I.e. only 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.
For the ones who want to express their excessive thanks for my work, I used to have an Amazon wishlist with a list of books, but right now I don't have any interesting books on the list anymore (to anyone who've sent books before: thank you very much, I got 6 books in 6 months). You can always donate something so that I can use it for other stuff, such as Nespresso coffee.