How to create a Custom JSF Converter

In Jakarta Server Faces (JSF), you can use converters to convert data between its model (backend) representation and its view (UI) representation. By default, JSF provides built-in converters for common types such as Integer, Double, Date, etc. However, in some cases, you may need to create a custom converter to handle custom data types or data conversion logic specific to your application. In this tutorial, we’ll create a custom JSF converter to convert a custom object User to and from its string representation in the UI.

In this first article of this series we discuss how to use built-in converters in JSF applications: Using Built-in Converters in JSF Applications . In this tutorial we will see a more advanced use case where we code our own Converters to manage the conversion of fields between the Model and the View.

Step 1: Define a simple Model class

Firstly, add a Class User to your JSF Project which represents your Model:

public class User implements Serializable {

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

    private int id;
    private String name;

      // Getters/Setters omitted

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + "]";
    }

}

Step 2: Implement the Custom Converter

To create a custom converter, you need to implement the javax.faces.convert.Converter interface. This interface requires you to implement two methods: getAsString and getAsObject.

  • getAsString: Converts the User object to its string representation to be displayed in the UI.
  • getAsObject: Converts the string representation from the UI back to the User object in the backend.

Here’s the implementation of the

@FacesConverter("myConverter")
 
public class UserConverter implements Converter  {

    HashMap<Integer, User> map = new HashMap<>() {{
        put(1, new User(1, "John Smith"));
        put(2, new User(2, "Frank Doe"));
    }};
    
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
     
        try {
            Integer intValue = Integer.parseInt(value);
            
            return map.get(intValue);
        } catch (NumberFormatException e) {
            throw new ConverterException(
                new FacesMessage("Invalid ID"), e);
        }
              
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {

        System.out.println("getAsString "+value);
        if (value == null) {
            throw new ConverterException(
                new FacesMessage("ID not found"));
        }
       
        return value.toString();
    }
}

As you can see, the FacesConverter is a two phase step:

At first the getAsObject callback method will kick in with the String value we will pass from the User Interface. We will return an Object that we can build from the String. Typically, we would query a resource like the DB at this point. To make it simple, we are just returning an User from an HashMap

Then, the getAsString method will render the User object it receives as input. In this case, we merely return the toString version of the User Object

Step 3: Define a Controller

Finally, you need to define a Controller for your Jakarta Faces application. The role of the Controller is minimal. We leave a no-op implementation of the update method and we add a String field that will map the text field of the User Interface:

@Named
@RequestScoped
public class Manager {
 
    private String name;
    

    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public void update() {
        // Add business logic here 
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Saved", null);
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
         

    }
     
}

Step 4: Define the User Interface

The application View will contain an HTML form with a TextField in it:

<h:form id="sampleform">
        <h:messages id="version" errorStyle="color: red" infoStyle="color: green"  />
        <h:inputText value="#{manager.name}" converter="myConverter" />
        <h:commandButton value="Submit" action="#{manager.update}"></h:commandButton>
</h:form>

Notice that we are setting the converter attribute for the inputText field. This way, when we hit return on the inputField (or when we click on the Submit button) the FacesConverter will kick-in and perform the transformation.

Running the application

Finally, deploy your Jakarta Faces application on your application server. For example, we will deploy it on WildFly:

mvn install wildfly:deploy

Then, try entering an ID in the text field, for example “1”:

facesconverter tutorial

As you can see from the next picture, the text field will automatically replace the “ID” with the toString() of the User object:

how to use converters facesconverter

Conclusion

That’s it! You have successfully created a custom JSF converter using the @FacesConverter annotation. The converter can now be used to handle conversions between the Product object and its string representation in your JSF application.

Source code: https://github.com/fmarchioni/mastertheboss/tree/master/web/jsf-custom-converter

Found the article helpful? if so please follow us on Socials