Dennis has posted 2 posts at DZone. View Full User Profile

JSF Anti-Patterns and Pitfalls

12.12.2008
| 42945 views |
  • submit to reddit

This article covers anti-patterns and pitfalls of day to day JSF development. Most of these issues have kept the author up at night; some of these are the same old challenges with a new face, pun intended. These challenges include performance, tight coupling, thread safety, security, interoperability and just plain ugliness.


The Validating Setter

Constructors are a good place to put validation logic for a domain model. In a perfect world every XML marshalling framework, object-relational mapping library, and dependency injection framework would support constructor injection - our domain models would not need setters for each field. As it turns out we do not live in a perfect world.

The JSF specification defines a dependency injection mechanism for managed beans: setter injection was defined, constructor injection was not. I understand this. JSF is a standard for java MVC web development, not dependency injection. Unfortunately this limitation gave rise to a whole slew of workarounds for application developers who want to perform domain validation and bean initialization logic.

The Validating Setter anti-pattern occurs when code that would normally be in the managed bean constructor is moved to the setter that would be invoked last by JSF dependency injection. How does one know which setter will be called last? The specification states that a JSF implementation must inject the dependencies of a managed bean in the order in which they are configured.

<managed-bean>
<managed-bean-name>iteration</managed-bean-name>
<managed-bean-class>net.dbyrne.agile.Iteration</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property> <!-- setStart called first -->
<property-name>start</property-name>
<value>#{projectBean.currentStart}</value>
</managed-property>
<managed-property>
<property-name>end</property-name>
<value>#{projectBean.currentEnd}</value>
</managed-property>
<managed-property><!-- setLast called last -->
<property-name>last</property-name>
<value>hack</value>
</managed-property>
</managed-bean>

Below is the Iteration class. The author of this class wants the start and end fields to be mandatory – an Iteration without these is invalid. Furthermore, start should never follow end.

 

public class Iteration {

private Calendar start, end; // injected

// sans setters and getters for start, end

public void setLast(String last) {

if(start == null || end == null)
throw new NullPointerException("incomplete range");

if(start.after(end))
throw new IllegalStateException("start cannot be after end");

}

}

 

Let's look at solutions. Applications that are using JSF 1.2 can take advantage of the PostConstruct annotation. Below, the PostConstruct annotation instructs the JSF implementation to invoke the initialize method after the managed bean has been created.

public class Iteration {

private Calendar start, end; // injected

// sans setters and getters for start, end

@javax.annotation.PostConstruct
public void initialize() {

if(start == null || end == null)
throw new NullPointerException("incomplete range");

if(start.after(end))
throw new IllegalStateException("start cannot be after end");

}
}

 

The PostConstruct approach is sexy in a time when much of the java community is revolting against XML in favor of annotations. But it doesn't quite solve the problem - the Iteration author wants every Iteration to have a start and end. The PostConstruct annotation insures that the JSF implementation will not create an invalid Iteration, but there is no way to make sure the JSF implementation has exclusive access to the no args constructor (and the setters).

The PostConstruct approach is not bad, but a better approach would be to ditch the dependency injection capabilities that come with any JSF implementation and to use a full blown dependency injection framework. Using Spring is as easy as placing the following lines of code in your JSF deployment descriptor.

<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>

 

The latest release of Apache MyFaces provides a Guice VariableResolver as well.

Published at DZone with permission of its author, Dennis Byrne.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Bruce Fancher replied on Mon, 2008/12/15 - 2:20am

Using JSF is itself an anti-pattern.

Manrico Corazzi replied on Tue, 2008/12/16 - 9:11am

So it turns out I'm not the only one utterly disliking JSF... :)

Marc Stock replied on Tue, 2008/12/16 - 2:06pm

+1 to Bruce Fancher

 Asking about JSF pitfalls is like sticking your hand in a fire and asking, "What are the pitfalls of sticking your hand in fire?" 

Omar Palomino S... replied on Thu, 2008/12/18 - 2:19pm in response to: Bruce Fancher

Wich alternatives do you propose that gets same tool support and ajax integration? I'm looking to speed-up time-to-develop projects and I really want to know about the alternatives to JSF-Ajax frameworks. Hope anyone could give a hand here.

Dzmitry Churbanau replied on Mon, 2008/12/22 - 11:46pm

Bruce Fancher, Manrico Corazzi and Marc Stock: everybody can criticize (read write this is bad and so on) but not everybody can give any valuable reason to it.
So, what is your reason? Can you give any reason, or it is just "i don't like it"? :)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.