JSF Configuration Resource Ordering

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>
    <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>

B.faces-config.xml:
<faces-config>
    <name>B</name>
    <application>
        <view-handler>com.b.ViewHandlerImpl</view-handler>
    </application>
    <lifecycle>
        <phase-listener>com.b.PhaseListenerImpl</phase-listener>
    </lifecycle>
</faces-config>

C.faces-config.xml:
<faces-config>
    <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>
D.faces-config.xml:
<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
The resulting parse order may be:
  1. Implementation specific configuration resource
  2. Document C
  3. Document B
  4. Document A
  5. 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
An important note on that last example - if a document has ordering requirements, but no name, then the ordering requirements will be ignored.

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>
    <absolute-ordering>
        <name>C</name>
        <name>A</name>
    </absolute-ordering>
    .
    .
    .
</faces-config>

In this case, the parsing order would be:
  • Implementation specific configuration resource
  • Document C
  • Document A
  • WEB-INF/faces-config.xml
It's pretty simple, however, developers should be aware that any documents that aren't explicitly referenced within the absolute-ordering element will not be processed.  Though it is possible to include those documents without having to enumerate them all individually.

Consider:
<faces-config>
    <absolute-ordering>
        <name>C</name>
        <others />
        <name>A</name>
    </absolute-ordering>
    .
    .
    .
</faces-config>
In this example, assuming we started with documents [A, B, C, D], then the resulting parse order may look like:

  • 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.

Comments:

"if a document has ordering requirements, but no name, then the ordering requirements will be ignored"
Why not throw an exception? Wouldn't that give better developer feedback?

"This element is only valid within the WEB-INF/faces-config.xml and will be ignored in all other cases"
Same question.

Thanks for the post!

Posted by Matt Drees on May 29, 2009 at 10:21 PM PDT #

Thanks for Sharing this, Ryan :) PrettyFaces now includes a name attribute in its faces-config.xml

Posted by Lincoln Baxter III on May 31, 2009 at 02:12 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

user12615560

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today