My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

luni, 19 octombrie 2015

JSF 2.2 programmatic faces-config.xml

Starting with JSF 2.2, we can programmatically reproduce the content and tasks of faces-config.xml. The starting point consists of a callback method, named populateApplicationConfiguration, which gets a single argument of type org.w3c.dom.Document—this class belongs to DOM API. Basically, a Document (tree node) is a representation in memory of an XML document, and we can manipulate it by adding, removing, importing, or adopting nodes, elements, and text. For each of these operations, there are dedicated methods. For some JSF developers, this API can be something new that should be learned; therefore, this can be a drawback of programmatic configuration.

For now, let's resume the dissertation from the callback method. The populateApplicationConfiguration method is provided by a class that extends and implements the abstract class ApplicationConfigurationPopulator found in the javax.faces.application package. In order to tell JSF about this class, you need to:

1. Create a JAR package (for example, faces-config.jar or by using any other name).
2. In this JAR package, create a folder named META-INF.
3. In the META-INF folder, create a folder named services.
4. In the services folder, create an empty file named javax.faces.application.ApplicationConfigurationPopulator.
5. In this file, write the fully qualified name of the class that extends and implements the abstract class ApplicationConfigurationPopulator.
6. In the JAR root, place the class that extends and implements the abstract class ApplicationConfigurationPopulator.

Done! Now when you add this JAR package in your project CLASSPATH, JSF will process it and apply the found configurations. Supposing that the class that extends and implements the abstract class ApplicationConfigurationPopulator is named faces.config.Initializer (you can use any other name), then the JAR content will look like in the following image:

When we are working directly on a DOM tree node, we tend to make stupid mistakes, like forgetting to add the text of an element, or placing an element in an improper place, and so on. In order to eliminate these errors without headaches, you can write a simple method to serialize the DOM in an XML file, which can be easily debugged visually or using a specialized tool. The following method accomplishes this task:

private void serializeFacesConfig(Document document,String path) {
 FileOutputStream fileOutputStream = null;
 OutputFormat outputFormat = new OutputFormat();
 outputFormat.setIndent(5);
 outputFormat.setLineWidth(150);
 ...
 fileOutputStream = new FileOutputStream(path);
 XMLSerializer xmlSerializer = new XMLSerializer();
 xmlSerializer.setOutputFormat(outputFormat);
 xmlSerializer.setOutputByteStream((OutputStream)fileOutputStream);
 xmlSerializer.serialize(document);
 ...
}

For example a custom phase listener is configured in faces-config.xml as follows:

<lifecycle>
 <phase-listener>beans.DebugPhaseListener</phase-listener>
</lifecycle>

The programmatic reflection of this configuration in JSF 2.2 is as follows:

public class Initializer extends ApplicationConfigurationPopulator {

 @Override
 public void populateApplicationConfiguration (Document toPopulate) {     
  String ns = toPopulate.getDocumentElement().getNamespaceURI();
  Element lifecycleEl = toPopulate.createElementNS(ns, "lifecycle");
  Element phaselistenerEl = toPopulate.createElementNS(ns, "phase-listener");
  phaselistenerEl.appendChild(toPopulate.createTextNode("beans.DebugPhaseListener"));
  lifecycleEl.appendChild(phaselistenerEl);
  toPopulate.getDocumentElement().appendChild(lifecycleEl);
  serializeFacesConfig(toPopulate, "D://faces-config.xml");
 }
 ...
}

Done!

Un comentariu :

  1. That's an interesting tech demo, but it doesn't seem to be very useful to me. Basically, what you're doing is creating the XML DOM model using Java. That allows you to add "if" conditions to the faces-config.xml, but other than that, there's little extra value.

    It would be much more useful to have a debuggable API - much the way Spring Boot offers. For instance, I want to be able to set a breakpoint in the line loading and / or initializing the CombinedResourcesListener. Is something like this possible?

    RăspundețiȘtergere

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors