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
and
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:
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:
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. -
Thefaces-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:
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:
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:
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:
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]:
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>
)
(implementation of <ordering>
)
The LiferayFacesBridge patch addressing the PrimeFaces AJAX issue
JIRA ticket covering the PrimeFaces + Liferay AJAX compatibility issue
- 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."↩
- At this point, I deliberately oversimplify things a bit to keep language simple↩
- apart from license files and stuff like that↩