Platinum Partner
java,frameworks

Apache MyFaces - Antipatterns and Pitfalls

The following is a chapter excerpt from the Apress book The Definitive Guide to Apache MyFaces and Facelets. You can download the chapter here.

[img_assist|nid=6147|title=|desc=|link=none|align=right|width=100|height=91]Dennis Byrne works for ThoughtWorks, a global consultancy with a focus on end-to-end agile software development of mission critical systems. He is a committer and PMC member for the Apache Myfaces project. He is also a committer for JBoss JSFUnit and co-author of "The Definitive Guide to Apache MyFaces and Facelets".

This chapter covers antipatterns and pitfalls of day-to-day JSF development. Many of these issues have kept us up at night, and most of these are old problems with new faces: performance, tight coupling, cache management, thread safety, security, and interoperability.

N Plus One

The N Plus One antipattern typically finds its way into web applications in a scenario like this:

You want to render a web page of purchase orders along with some data about the customer of each order. This data must be read from a database. An efficient approach would be to pull a single dataset by joining the Customer table and the Order table. A far less efficient approach would be to read a dataset from the Order table, iterate over this dataset, and go back to the database for detailed customer information related to that order. The first approach costs one round-trip; the second approach costs N plus one round-trips, where N is the number of orders. Let’s look at how this antipattern can find its way into JSF applications.

The powerful Open Transaction in View pattern has grown popular among application developers using object-relational mapping (ORM) frameworks. In the Hibernate community, the pattern often goes by a slightly different name, Open Session in View. This pattern begins by opening a transaction in a servlet filter as the request arrives and closing the transaction before the response is sent. The OpenTransactionInViewFilter class (OTVF) is an implementation of this pattern:

public class OpenTransactionInViewFilter implements Filter {
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain) {
try {
ObjectRelationalUtility.startTransaction();
chain.doFilter(request, response);
// commits transaction, if open
ObjectRelationalUtility.commitTransaction();
} catch (Throwable throwable) {
try {
ObjectRelationalUtility.rollbackå
Transaction();
} catch (Throwable _throwable) {
/* sans error handling */
}
}
}
public void init(FilterConfig config) throws ServletException { }
public void destroy() { }
}

The beauty of this pattern is the convenience of querying the ORM framework in an action method, placing a persistent object in request scope, and letting the navigation handler forward the request to the appropriate view template. The page developer has the luxury of pulling data to the response via JSF EL expressions. Data can be lazily loaded as the page renders and each JSF EL expression walks the Request-scoped object graph.

We once assisted with a project where this pattern was applied. The project was on time and under budget, but the application had performance problems. During the first six months of development, the application had developed a very loud conversation with the database. The primary culprits were view templates like this:

<!-- One trip to the database for the projects ... -->
<h:dataTable value="#{projectBean.projects}" var="project">
<h:column>
<h:commandLink action="#{projectBean.viewProject}"
value="view project"/>
</h:column>
<h:column>
<!-- ... and plus N trips for each project manager record -->
<f:facet name="header">Project Manager</f:facet>
#{project.manager.name}
</h:column>
<h:column>
<f:facet name="header">Project Name</f:facet>
#{project.name}
</h:column>
<h:column>
<f:facet name="header">Start Date</f:facet>
#{project.startDate}
</h:column>
<h:column>
<f:facet name="header">End Date</f:facet>
#{project.endDate}
</h:column>
</h:dataTable>

The data for this form could be retrieved with a single trip to the database. Instead, a single persistent instance of the domain model was being passed to the view template, and the JSF EL Resolver was triggering an additional trip to the database for each row to be rendered. The action methods in the managed beans weren’t digging deeply enough into the database and were causing the well-known N Plus One antipattern.

An architectural decision was made to isolate all database transactions to the application invocation phase with the OpenTransactionInApplicationPhaseListener class (OTAPL), which accomplishes everything provided by the OTVF with finer transaction demarcation. The OTVF scopes a transaction to the life cycle of the request, while the OTAPL scopes a transaction to a single phase in the request life cycle. This subtly makes the difference between a web page that renders in O(n) and a web page that renders in O(1).

public class OpenTransactionInApplicationPhaseListener
implements PhaseListener {
public void beforePhase(PhaseEvent event) {
try {
ObjectRelationalUtility.startTransaction();
} catch (Throwable throwable) {
/* sans error handling */
}
}
public void afterPhase(PhaseEvent event) {
try {
// commits transaction, if open
ObjectRelationalUtility.commitTransaction();
} catch (Throwable throwable) {
try {
ObjectRelationalUtility.rollbackå
Transaction();
} catch (Throwable _throwable) {
/* sans error handling */
}
/* sans error handling */
}
}
public PhaseId getPhaseId() {
return PhaseId.INVOKE_APPLICATION;
}
}

 

The OTVF was replaced with the OTAPL, and the tests were run. View templates triggering read operations to the database could be smoked out by closing the transaction before the response rendering phase. Pages with exceptions could be used to trace which dataaccess objects needed to be fine-tuned. Every unit test passed; more than half the integration tests failed.
Not only had this simple PhaseListener highlighted a performance issue, it raised the awareness of risk. There is a special time in the request processing life cycle for risk: the application invocation phase. A great number of JSF applications place risk later in the life cycle, in the response rendering phase, by performing most of the database trips after the action phase as the page is rendering, with no chance to recover from the unexpected. This is the worst time to do something risky; even logging options are limited. This behavior defeats one of the purposes of the MVC pattern: keep the view concerned about display. Hitting the database during the response rendering phase dilutes the value of your try/catch blocks in action methods. Would you write an action method like this?

public String doAction() {
String outcome = "success";
try {
getDao().goToTheDataBase();
}catch(Exception e) {
handleException();
outcome = "failure";
}finally {
// Exception uncaught
getDao().goToTheDataBaseAgain();
}
return outcome;
}

We are not suggesting that the OTVF itself is an antipattern or a pitfall. It is great for production systems, when exceptions are obviously not desired. The OTAPL, however, is better for day-to-day development and testing, when failing fast is desired—fixing a mistake costs less when the mistake is discovered earliest.

There is a time and place for risk in the JSF request processing life cycle: the invoke application phase. This phase is composed of two parts: action listeners and actions. Any action source can have zero or more action listeners and a single action method. Action listeners are always invoked first, followed by the action method. Action listeners and action methods have different properties and trade-offs. Action listeners provide the application developer with an ActionEvent reference. The ActionEvent provides useful information such as a reference to the ActionSource component from where the event originated. This information is not as easily available in an action method, where there is no ActionEvent reference. Action methods, on the other hand, are different from action listeners, because each one has a return type, something the view navigation handler can react to.

If you are using a file handle, queue, remote method, web service, or database, consider doing so in an action method, where you can declaratively react to the unexpected, rather than an action listener. There will always be corner cases, but you should try to avoid risk in an action listener, a PhaseListener, a managed bean constructor, custom converter, custom validator, or while the page is rendering.

 

If you like this excerpt from the Apress book The Definitive Guide to Apache MyFaces and Facelets. You can download the chapter here.

The Map Trick

The Map Trick antipattern is a hack used to invoke business methods from view templates via an obscure limitation in the JSP and JSF specifications. By invoking business methods from a template, the view and model become tightly coupled.
JSF EL and Unified EL do not support parameterized method invocation. You get ternary logic, and you can call getters, but that’s about it. Tapestry developers, or anyone else familiar with the Object-Graph Navigation Language (OGNL) expression language, are often disappointed to learn this because OGNL supports parameterized method invocation. The closest thing to parameterized method invocation is static method invocation via JSP EL or Facelets.
The Map interface is the only exception to this rule. JSP EL, JSF EL, and Unified EL all support invocation of the get method, a parameterized method of the Map interface:

#{myManagedBean.silvert} // pulls 'silvert' from managed bean Map
#{param['lubke']} // pulls 'lubke' request parameter

Some developers have implemented their own Map to take advantage of this.

public class MapTrick implements Map {

public Object get(Object key) {
return new BusinessLogic().doSomething(key);
}
public void clear() { }
public boolean containsKey(Object arg) { return false; }
public boolean containsValue(Object arg) { return false; }
public Set entrySet() {return null; }
public boolean isEmpty() { return false; }
public Set keySet() { return null; }
public Object put(Object key, Object value) { return null; }
public void putAll(Map arg) { }
public Object remove(Object arg) { return null; }
public int size() { return 0; }
public Collection values() { return null; }
}


When the EL Resolver invokes the get method the parameter is then used by business logic. We once saw a project where an entire miniature framework was built around the map trick. Needless to say, the view and model were severely tightly coupled. There are always better alternatives to the map trick using plain methods and value expressions.

The Déjà Vu PhaseListener


The JSF request life cycle is broken into phases. The beginning and end of each phase is considered an event, and these events can be subscribed to via a PhaseListener. If a PhaseListener subscribes to the restore view phase of the request life cycle, MyFaces will invoke a callback method on the PhaseListener instance each time the restore view phase begins and ends for a request. When PhaseListener callback methods are invoked twice, it is a referred to as a Déjà Vu PhaseListener, an old problem that often crops up on the MyFaces mailing list.

Tip
One of the most active mailing lists for the Apache Software Foundation is users@myfaces.apache.org. It is a wonderful place for exchanging new ideas, trading technical solutions, and engaging in flame wars. After all these years, MyFaces remains an open source project where the development team still interacts with application developers.

Let’s look at how PhaseListeners are registered at start-up time. PhaseListeners can be registered in any JSF configuration file:

<lifecycle>
<phase-listener>
org.apache.myfaces.PhaseListenerImpl
</phase-listener>
</lifecycle>
JSF configuration files are specified via the javax.faces.CONFIG_FILES context parameter
in the deployment descriptor:
<context-param>
<description>comma separated list of JSF conf files</description>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>
/WEB-INF/faces-config.xml,/WEB-INF/burns.xml
</param-value>
</context-param>

Per the JSF specification, MyFaces automatically parses /WEB-INF/faces-config.xml as well as all files specified in the comma-separated list of the javax.faces.CONFIG_FILES context parameter. When /WEB-INF/faces-config.xml is specified in the javax.faces.CONFIG_FILES context parameter it is parsed twice. The PhaseListeners configured in this file are consequently registered twice at start-up and invoked twice at runtime. MyFaces tries to warn you about this in the log files:

WARN org.apache.myfaces.config.FacesConfigurator - /WEB-INF/faces-config.xml has been specified in the javax.faces.CONFIG_FILES context parameter of the deployment descriptor. This should be removed, as it will be loaded twice. See JSF spec 1.2, 10.1.3

XML Hell++

JSF 1.1 and 1.2 are compatible with Java 1.4. This requirement limits the JSF specification from using Java annotations to declare things such as navigation rules or dependency injection. These things are declared in XML instead. We once looked at a project in development with a configuration file similar to the following.
The “contact us” page was to be accessible from just about every page on the site, and a separate action rule was used for each page.

<navigation-rule>
<from-view-id>/home.xhtml</from-view-id>
<navigation-case>
<from-outcome>contact_us</from-outcome>
<to-view-id>/contact.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/site_map.xhtml</from-view-id>
<navigation-case>
<from-outcome>contact_us</from-outcome>
<to-view-id>/contact.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/about_us.xhtml</from-view-id>
<navigation-case>
<from-outcome>contact_us</from-outcome>
<to-view-id>/contact.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<!-- continued ... -->

A global navigation rule was used to reduce the configuration file by more than a hundred lines:

<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>contact_us</from-outcome>
<to-view-id>/contact.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

 

If you like this excerpt from the Apress book The Definitive Guide to Apache MyFaces and Facelets. You can download the chapter here.

 

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}