; last updated - 7 minutes read

Why ordering matters

Every once in a while it's important to control the order in which JSF libraries are loaded.[1] For instance, loading the LiferayFacesBridge 6.1 before PrimeFaces 5.x breaks the AJAX features of PrimeFaces. Both libraries replace the same Mojarra or MyFaces base class by their own, improved implementation. Unfortunately, Liferay doesn't cope with the implementation of PrimeFaces. Loading PrimeFaces first fixes the problem. There are many more examples. JSF libraries such as

OmniFaces, AngularFaces

and

BabbageFaces

don't provide widgets. Instead, they modify the way JSF requests are processed.[2] Those processors are stacked behind each other like a pipeline. It's easy to imagine situations in which the reordering the pipeline makes a difference. For instance, it's important that BabbageFaces is the last stage of the pipeline: it optimizes the HTML code generated by the previous stages.

Foreign feathers

As it happens, there's a very good article on the topic:

Ryan Lubke

describes the load ordering features introduced with JSF 2.0. He suggests to add an <ordering> tag to the

faces-config.xml. Funny thing is, when I tried the feature he describes I stumbled over a warning when the JSF library is initialized:

JSF1081: /WEB-INF/faces-config.xml contains elements. These will be ignored.

As it turns out,

  • <ordering> is intended to be used by JSF library developers

  • <absolute-ordering> is intended to be used by JSF application developers (in other words: the vast majority of us).

Oh - did I loose you already? Don't worry: I'll explain <ordering> and

<absolute-ordering> in a minute.

Default load order

When I talked about load order, I simplified things to keep the language simple. In reality, we're talking about something slightly different: the order in which the faces-config.xml files are processed. Being an application developer, you may only be aware of the faces-config.xml file you write yourself. A close look reveals that every JSF library has a

faces-config.xml, too. To my surprise, my company project uses seven faces-config.xml files - not only the one my team wrote ourselves. There are two faces-config.xml files that are processed in a fixed, immutable order:

  • The faces-config.xml of the JSF base library (i.e. Mojarra or MyFaces) is always processed first.

  • The faces-config.xml of your application is always processed last. Thus, you have full control over every aspect of your JSF ecosystem. You can modify every setting defined by one of the standard libraries you're using.

The other libraries are processed more or less in random order. As many developers found out, libraries are typically loaded in alphabetical order so renaming libraries can make a difference. However, there's a more reliable way.

How to influence the load order

We need a bit of preparation first. Every JSF library can be given a name by adding a <name> entry in the library's

faces-config.xml. We need this name to define load ordering. You can look up the name by unzipping the JSF library jar file, opening the file META-INF/faces-config.xml and looking for the <name> section:

AngularFaces

For the sake of convenience, here's a quick collection of the names of a couple of popular JSF libraries:

JSF Library Library name used for load ordering
PrimeFaces primefaces
OmniFaces omnifaces
AngularFaces 2.1+ AngularFaces
BabbageFaces 1.1+ BabbageFaces
BootsFaces bootsfaces
ICEFaces ICEfacesCore
RichFaces (missing?)

Now that you know the name of the JSF libraries, you can add an <absolute-ordering> tag to your application's

WEB-INF/faces-config.xml file:

MyOwnJSFApplication primefaces LiferayFacesBridge ... ...

In this example, PrimeFaces is initialized first (directly after Mojarra or MyFaces, that is). Liferay is initialized second. After that, every other JSF library you may use in your application (such as OmniFaces, BabbageFaces, AngularFaces) is initialized in random order. The example above fixes the AJAX problem of Liferay 6.1 and PrimeFaces 5.x. First, PrimeFaces replaces Mojarra's BodyRenderer with its own implementation. That's the implementation that happens to be incompatible to Liferay. That doesn't matter because our <absolute-ordering> tag initializes the LiferayFacesBridge a short time later. The bridge replaces the PrimeFaces BodyRenderer by it's Liferay counterpart.

Defining the ordering in a JSF library

As far as I can see, <absolute-ordering> can only be defined in your application. JSF libraries should use relative

<absolute-ordering>, as described in

Ryan Lubke's article. A snippet

taken from the LiferayFacesBridge

shows the idea:

LiferayFacesBridge HTML_BASIC com.liferay.faces.bridge.renderkit.html_basic.RenderKitBridgeImpl Overrides the BodyRenderer that comes with the JSF implementation javax.faces.Output javax.faces.Body com.liferay.faces.bridge.renderkit.html_basic.BodyRendererBridgeImpl

Mostly, this relative ordering does the same trick as the absolute ordering of our previous example. It sees to it that the bridge is initialized before the other libraries. The syntax is more elaborated than the syntax of

<absolute-ordering>. We're talking about relative ordering now, so it doesn't suffice to simply list the libraries. We have to indicate whether our library is located relative to the other libraries:

It's also possible to mention a particular library explicitly:

primefaces

In this case PrimeFaces is the first library, followed by the current library, which in turn precedes every other library.

<ordering> vs. <absolute-ordering>

Things get interesting when more than one library defines a relative order. The JSF specification has a couple of sophisticated examples. Nothing stops the libraries from containing contradicting ordering rules. In this case, it's a good idea to resort to defining the absolute ordering in your application (as opposed to relying on the automatic resolution based on the information stored in the libraries). So

<ordering> is intended to be used in a JSF library. It doesn't define an absolute position. It merely gives a hint of where to position the library relative to other libraries. The relative ordering is very flexible. It still works when new, previously unknown libraries are added.

<absolute-ordering>, in contrast, is intended to be used in an application. The application programmer knows which libraries they use. So they can easily define the absolute ordering. Defining a relative ordering in an application is pointless: as I mentioned above, the application's faces-config.xml is always processed last.

The code snippet above shows the original version of the LiferayFacesBridge. Neil Griffin published

a patch addressing the PrimeFaces AJAX issue, which is interesting itself: quite possibly it's the smallest JSF library ever written. It consists of a single

META-INF/faces-config.xml file and nothing else[3]:

Overrides the BodyRenderer that comes with PrimeFaces javax.faces.Output javax.faces.Body com.liferay.faces.bridge.renderkit.html_basic.BodyRendererBridgeImpl

The idea is to add both the original LiferayFacesBridge jar file and the patch jar file to your application's libraries. JSF loads both files, examines the faces-config.xml file and moves the patch to the end of the list. So the patch can activate the appropriate BodyRenderer implementation without being disturbed by PrimeFaces (or any other JSF library, for that matter).

Wrapping it up

Most of the time you simply use JSF libraries without thinking about exotic topics such as load order. However, sometimes you run into nasty problems caused by libraries that aren't perfectly compatible with each other, so it's good to know JSF 2.x offers decent support of those use cases.


Dig deeper

Ryan Lubke's excellent article

on <ordering>

JSF 2.2 Specification (browse for section 11.4.8)

com.sun.faces.config.FacesConfigInfo

(the class that emits the warning on <ordering>)

DocumentOrderingWrapper

(implementation of <ordering>)

The LiferayFacesBridge patch addressing the PrimeFaces AJAX issue

JIRA ticket covering the PrimeFaces + Liferay AJAX compatibility issue


  1. More precisely: the order in which the libraries are configured and activated. However, the difference isn't important for this article, so I'll stick with the more common notion of "load ordering."↩
  2. At this point, I deliberately oversimplify things a bit to keep language simple↩
  3. apart from license files and stuff like that↩

Comments