JSF Configuration Resource Ordering
Wednesday May 27, 2009
A common issue in JSF 1.1/1.2 was the inability to control the order in which faces-config.xml files were parsed when said files were included in a JAR file. Why does ordering matter? Consider the decoration of entities such as ViewHandler or Application. If your application contains more than two ViewHandlers, you may wish to have the ViewHandler delegation chain configured in a certain order.
The same holds true for PhaseListeners. A developer may wish to have PhaseListenerB execute before PhaseListenerA.
A stop-gap measure was implemented by Mojarra (MyFaces does the same I believe) where the ordering of META-INF/faces-config.xml documents was determined by the natural sort order of the JAR name that contained the file. While this worked, it wasn't a perfect solution as you were then forced to rename the JAR files to achieve the desired result.
JSF 2.0 solves this by requiring implementations to support partial ordering of the configuration resources via the ordering element.
The ordering element offers a way for a single document to state it wishes to be ordered before or after a specific document, or a group
of documents. Documents can be identified by the top-level name element. It's imporant to note that there are two documents in configuration processing that are always processed in a specific order and as such the ordering element has no impact. The implementation default configuration resource is always processed first and the WEB-INF/faces-config.xml (if present) is always processed last.
Given the above, let's start with an example straigh from the specification:
A.faces-config.xml:
<faces-config>B.faces-config.xml:
<name>A</name>
<ordering>
<after>
<name>B</name>
</after>
</ordering>
<application>
<view-handler>com.a.ViewHandlerImpl</view-handler>
</application>
<lifecycle>
<phase-listener>com.a.PhaseListenerImpl</phase-listener>
</lifecycle>
</faces-config>
<faces-config>C.faces-config.xml:
<name>B</name>
<application>
<view-handler>com.b.ViewHandlerImpl</view-handler>
</application>
<lifecycle>
<phase-listener>com.b.PhaseListenerImpl</phase-listener>
</lifecycle>
</faces-config>
<faces-config>D.faces-config.xml:
<name>C</name>
<ordering>
<before>
<others />
</before>
</ordering>
<application>
<view-handler>com.c.ViewHandlerImpl</view-handler>
</application>
<lifecycle>
<phase-listener>com.c.PhaseListenerImpl</phase-listener>
</lifecycle>
</faces-config>
<faces-config>
<name>D</name>
<application>
<view-handler>com.my.ViewHandlerImpl</view-handler>
</application>
<lifecycle>
<phase-listener>com.my.PhaseListenerImpl</phase-listener>
</lifecycle>
</faces-config>
Looking over the four documents, we see that:
- Document A is after document B
- Document B has no ordering requirements
- Document C is uses the others element to say it should be ordered
before all the other documents that are being sorted - Document D has no ordering requirements
- Implementation specific configuration resource
- Document C
- Document B
- Document A
- WEB-INF/faces-config.xml (if present)
Here's a couple other examples to illustrate an important point about the ordering. When documents state they wish to be before or after another document, it may not necessarily be the case that the documents are ordered right next to each other. I think the following examples will clarify what I mean:
Document A - <after><others/><name>C</name></after>
Document B - <before><others/></before>
Document C - <after><others/></after>
Document D - no ordering
Document E - no ordering
Document F - <before><others/><name>B</name></before>
The resulting parser order could be [F, B, D, E, C, A], but [F, B, E, D, C, A] would also be accurate.
Here's another:
Document <no id> - <after><others/></after><before><name>C</name></before>
Document B - <before><others/></before>
Document C - no ordering
Document D - <after><others/></after>
Document E - <before><others/></before>
Document F - no ordering
Possible parsing orders are:
- B,E,F,<no id>,C,D
- E,B,F,<no id>,C,D
- B,E,F,C,<no id>,D
- E,B,F,C,<no id>,D
Now, there are most likely going to be cases where the resulting partial parsing order doesn't quite fit with what an application needs.
In that case, the developer can fallback to another new element called absolute-ordering. This element is only valid within the WEB-INF/faces-config.xml and will be ignored in all other cases. The use of this element allows the developer complete control over the order that faces-config documents will be processed.
Here's a simple example:
<faces-config>In this case, the parsing order would be:
<absolute-ordering>
<name>C</name>
<name>A</name>
</absolute-ordering>
.
.
.
</faces-config>
- Implementation specific configuration resource
- Document C
- Document A
- WEB-INF/faces-config.xml
Consider:
<faces-config>In this example, assuming we started with documents [A, B, C, D], then the resulting parse order may look like:
<absolute-ordering>
<name>C</name>
<others />
<name>A</name>
</absolute-ordering>
.
.
.
</faces-config>
- Implementation specific configuration resource
- Document C
- Document B
- Document D
- Document A
- WEB-INF/faces-config.xml
Note that B/D could be interchanged. The others element may appear any where within the absolute-ordering element, but it may only do so once.











"if a document has ordering requirements, but...
Thanks for Sharing this, Ryan :) PrettyFaces now i...