JSF 2.0 and JSR303 Bean Validation weird behaviour (or standard?)

2011-12-07

I noticed some strange behaviour in using JSF 2.0 together with JSR 303. And a really ugly "feature" (a really ugly feature!). This post is, I guess, both an observation and perhaps also a question if this is standard behaviour.

Looking at the JSR 303 specification it states the annotations can be placed both on the field or the property (e.g, the property's getter-method). The JavaServer Faces specification (2.5.7) does not seem to constrain this further. In other words it does not specify the JSR303 annotations should be placed on the property (which does make sense to me, because JSF relies on the JavaBean specification for its binding).

I tried three different scenarios: place on setter, place on getter, and place on field (that's where the ugliness comes in!)

Annotate the Property

When placing the constraint on the properties it only works when you annotate the getter method. The logic of that escapes me, because it seems the validation is performed when you set the value. The JSR 303 specification however does state this (3.1.12): "Constraints on non getter methods are not supported." So the following will not work

//Does not work
@Email
public void setEmailAddress(String emailAddress) {
  this.emailAddress = emailAddress;
}

The following does

//Does  work
@Email
public String getEmailAddress() {
  return emailAddress;
}

Annotate the Field (the ugliness)

Placing the annotation on a field works as well, but there is a catch. The following works:

//Does  work
@Email
private String emailAddress;

public String getEmailAddress() {
  return emailAddress;
}
public void setEmailAddress(String emailAddress) {
  this.emailAddress = emailAddress;
}

However, the following does not work(!)

//Does  work
@Email
private String email;

public String getEmailAddress() {
  return email;
}
public void setEmailAddress(String emailAddress) {
  this.email = emailAddress;
}

Notice the field and the property have different names. The JavaBean specification does not relate fields and properties. In other words properties don't need fields, and if they read from//write to fields these fields don't have to conform to any naming pattern. An example where a property does not use a field is in a "connected" property of some network component. The getter method would just see if the socket port is open; setting the property to false would close the socket connection. In this example there is no field "connected" of type boolean. But more importantly here the JavaBean specification does not tell you for a property foo you need a private field foo. It only states the property foo exists because of the getFoo and/or setFoo methods.

So its seems field annotations works as long as the field has the same name as the property. This feature for me is ugly as there is no specification to back this up.

My environment:

  • JBoss jboss-as-web-7.0.2.Final
  • org.hibernate:hibernate-validator:4.2.0.Final

tl;dr: JSR 303 and JSF work great: use annotations the get method. Annotated fields works as well as long as the field has the same name as the property (which is an ugly feature).

This article does not necessarily reflect the technical opinion of EDC4IT, but purely of the writer. If you want to discuss about this content, please use thecontact ussection of the site