duminică, 22 noiembrie 2015

JSF 2.3 Take advantage of the new generic parameters in Converter<T> and Validator<T>

As you probably know, in JSF 2.2 we can write a custom converter by extending the Converter interface, and a custom validator by extending the Validator interface. The methods defined in these interfaces works with Object class, as you can see in the below skeletons:

JSF 2.2 custom converter skeleton

@FacesConverter(value = "fooConverter")
public class FooConverter implements Converter {

 @Override
 public Object getAsObject(FacesContext context, UIComponent component, String value) {
  ...
 }

 @Override
 public String getAsString(FacesContext context, UIComponent component, Object value) {
  // check value type and cast it
  ...
 }
}

JSF 2.2 custom validator skeleton

@FacesValidator(value = "fooValidator")
public class FooValidator implements Validator {

 @Override
 public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException {
  // check value type and cast it
  ...
 }
}

Starting with JSF 2.3 Converter and Validator have now been parameterized and implementations can concisely define the exact input type.

// Mojarra 2.3.0-m04 Converter snippet of source code
public interface Converter<T> {
 T getAsObject(FacesContext context, UIComponent component, String value);
 String getAsString(FacesContext context, UIComponent component, T value);
}

// Mojarra 2.3.0-m04 Validator snippet of source code
public interface Validator<T> {
 void validate(FacesContext context, UIComponent component, T value);
}

For example, let's suppose that we have the following simple class:

public class User implements Serializable {

 private String name;
 private String email;

 public User(String name, String email) {
  this.name = name;
  this.email = email;       
 }

 // getters and setters  
 // equal and hash code
 ...
}

Now, we can convert/validate a string against this class by indicating the User type in our custom converter/validator:

JSF 2.3 custom converter with defined type example

@FacesConverter(value = "UserConverter")
public class UserConverter implements Converter<User> {

 @Override
 public User getAsObject(FacesContext context, UIComponent component, String value) {
  ...
 }

 @Override
 public String getAsString(FacesContext context, UIComponent component, User value) {
  // no need to check value type and cast it
  ...
 }
}

JSF 2.3 custom validator with defined type example

@FacesValidator(value = "UserValidator")
public class UserValidator implements Validator<User> {

 @Override
 public void validate(FacesContext fc, UIComponent uic, User o) throws ValidatorException {
  // no need to check value type and cast it
  ...
 }
}

Note In JSF 2.3, you can still write custom converters/validators  as in JSF 2.2. If you don't want to take advantage of the new generic parameters, you can use the classical approach.

A complete and functional example can be found here. I've tested under Payara 4.1.

Niciun comentariu:

Trimiteți un comentariu