Showing posts with label Converter. Show all posts
Showing posts with label Converter. Show all posts

Sunday, 21 September 2014

Input in uppercase with JSF inputText, a TagHandler example

Introduction

Recently there was a requirement from a client to be able to input data all in uppercase within a JSF web application.

When you write a simple JSF converter and add a CSS style class to the component to uppercase all input client side, you’re done. You can find various posts on the internet where this solution is described.

This blog shows how you can improve the solution.  You can create a JSF tagHandler which allows you to combine the adding of the converter and CSS style class, by defining your custom tag.
It is convenient and typesafe.  Typesafe Because it is a tag, so you have IDE autocompletion.  Within the name of the converter and the CSS style class name, you can make some typos which leads to an incorrect behaviour.

TagHandler

What is a JSF TagHandler? The tagHandler is some piece of code executed when JSF encounters your custom tag that you have placed in the xhtml page.  This code runs during the creation of the JSF component tree and thus ideal to tweak some components as we like to do for the uppercase scenario.

Your tagHandler should extend from the javax.faces.view.facelets.TagHandler JSF class.  And all your work should go into the apply method.  This method is called in response to the identification of your custom tag in the xhtml file.

This method has a UIComponent typed parameter representing the parent component your custom tag belongs to.  So adding a converter and style class to your inputText component is very straightforward:

public class UppercaseHandler extends TagHandler { 
 
    public UppercaseHandler(TagConfig config) { 
        super(config); 
    } 
 
    @Override 
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException { 
        if (parent instanceof HtmlInputText) { 
            HtmlInputText inputText = (HtmlInputText) parent; 
            inputText.setConverter(new UppercaseConverter()); 
 
            String styleClass = inputText.getStyleClass(); 
            if (styleClass == null) { 
                styleClass = ""; 
            } 
            if (!styleClass.contains("uppercase")) { 
                inputText.setStyleClass(styleClass + " uppercase"); 
            } 
        } 
    } 
} 

Configuration

The next step we have to do, is define the name of our custom tag and link the tagHandler class to it. This is done in the Facelets configuration file. Here you can define your new tag name and the tagHandler class name which is associated with it.

<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd" 
                version="2.0"> 
    <namespace>http://www.c4j.be/rubus</namespace> 
 
    <tag> 
        <tag-name>uppercase</tag-name> 
        <handler-class>be.sezz.handler.UppercaseHandler</handler-class> 
    </tag> 
 
</facelet-taglib>

In other scenarios, you can assign tags to converters, custom defined components or user defined EL functions.

Example

In the Facelets Configuration file, we have defined a namespace(http://www.c4j.be/rubus in the example above)  This namespace we can be used in the xhtml file and our custom tag can be used. An example could be.

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:r="http://www.c4j.be/rubus"> 
 
... 
 
<h:body> 
    <h:form id="mainForm"> 
        <h:inputText id="field" value="#{someBean.value}"> 
            <r:uppercase/> 
        </h:inputText> 
    </h:form> 
</h:body> 
</html> 

Conclusion

The JSF TagHandler is a very convenient way of assigning a tag name to some custom functionality you have created.  Better because it is ‘typesafe’ and thus you get warned when you should make a typo.
In the example above, you saw how you can assign in a few lines a custom converter and CSS style class to a JSF inputText component.




Wednesday, 25 September 2013

Generic JPA 2.1 converter for enum

Introduction

Until now, an enum value could be stored in the database by its ordinal number or his name in JPA. When you have a ‘legacy’ database or when you are doing refactorings you could be in trouble.  The only option then was to rely on the implementation to allow a custom value as the representation of the numeration in the database.
In the latest release of JPA, 2.1, there is support for custom converters so you can solve these kind of issues.

JPA 2 Converter

What do you need to do to have a custom converter? The enumeration class doesn’t need any change. In the entity were you use the enum, you need to specify the converter you like to use, like this:
@Entity
public class Person {
...

  @Column
  @Convert(converter = GenderEnumConverter.class)
  private Gender gender;
...
}

The converter class can look as this
@Converter
public class GenderEnumConverter implements AttributeConverter< Gender, String> {

  @Override
  public String convertToDatabaseColumn(Gender attribute) {
    String result = "";
    switch (attribute) {

      case MALE:
        result = "M";
        break;
      case FEMALE:
        result = "F";
        break;
      default:
    }
    return result;
  }

  @Override
  public Gender convertToEntityAttribute(String dbData) {
    Gender result = null;
    switch (dbData) {
      case "M":
        result = Gender.MALE;
        break;
      case "F":
        result = Gender.FEMALE;
        break;
      default:
    }
    return result;
  }
}

And the last thing you need to do is to ‘register’ the converter with JPA as no scanning is performed of the available classes.  You can specify the class name, just as you specify the entity classes in the persistence.xml file.
<persistence-unit name="converter-unit" >
  <description>Forge Persistence Unit</description>

  <class>be.rubus.web.ee7.jpa.converter.model.Person</class>
  <class>be.rubus.web.ee7.jpa.converter.jpa.GenderEnumConverter</class>
</persistence-unit>

Not OO


The above code is not ideal in several ways. If you have an enum class with a lot of values, you have to write a large if-then-else structure which is not very OO like. And you also need to write a lot of similar code which wants me to search for a more generic solution.

If we could define the database value together with the enum value, it would be a great improvement. It makes the code also much more logic as you can define the database value together with the enum value.

Since we need such functionality for each numeration that we use in the persistent objects, we can create an interface like DatabaseEnum.
public interface DatabaseEnum {

  Serializable getDatabaseValue();

}

And change the enum to implement this interface.
public enum Gender implements DatabaseEnum  {
  MALE("M"), FEMALE("F");

  private Serializable databaseValue;

  Gender(Serializable databaseValue) {
    this.databaseValue = databaseValue;
  }

  public Serializable getDatabaseValue() {
    return databaseValue;
  }

}

This should allow us to create a generic converter for the enums, except that the Java compiler removes the information regarding the generic types, know as type erasure. Otherwise a converter like this could be possible.
@Converter
public class EnumConverter<T extends DatabaseEnum> implements AttributeConverter< T, Serializable> {

  @Override
  public Serializable convertToDatabaseColumn(T attribute) {
    return attribute.getDatabaseValue();
  }

  @Override
  public T convertToEntityAttribute(Serializable dbData) {
    // There is no way we can create such a method
    return determineEnum(T, dbData);
  }

}

If we would be able to define that a custom constructor needs to be called, where we supply as parameter the class T, we would get away with it.  But this is not the case.
public EnumConverter(Class<T> enumType) {..}

Almost generic converter


Based on the optimal code above, we are able to create a converter that uses a generic utility method.  It means that we still need to create a converter for each enum class we like to use, but the code is much cleaner then the first example we show in the text.
@Converter
public class GenderEnumConverter implements AttributeConverter<DatabaseEnum, Serializable> {

  @Override
  public Serializable convertToDatabaseColumn(DatabaseEnum attribute) {
    return attribute.getDatabaseValue();
  }

  @Override
  public Gender convertToEntityAttribute(Serializable dbData) {
    return DatabaseEnumUtil.getEnumValue(Gender.class, dbData);
  }
}

And the utility method can be small and generic thanks to the not very known method getEnumConstants() of the JVM core classes.
  public static <T extends DatabaseEnum> T getEnumValue(Class<T> enumClass, Serializable dbValue) {
    T result = null;
    if (dbValue != null) {

      for (DatabaseEnum enumInstance : enumClass.getEnumConstants()) {
        if (dbValue.equals(enumInstance.getDatabaseValue())) {
          result = (T) enumInstance;
          break;
        }
      }
    }
    return result;
  }

Conclusion


In the latest version of JPA, a custom converter can be defined which can be very handy in a lot of situations.  You can use it to create a converter for Joda-time classes or for specifying the database value of an enum value.

The only thing that keeps us from creating a generic converter for enums is the type erasure thing of Java. Otherwise we could create a beautiful converter for all our enums.