Converters, Listeners and Validators in Java EE 7

1. Overview

Java Enterprise Edition (JEE) 7 provides some useful features e.g. for
validating user input, converting values into appropriate Java data
types.

In this tutorial, we’ll focus on those features provided by converters,
listeners, and validators.

2. Converters

A converter allows us to transform string input values into a Java data
types. Predefined converters are located in the javax.faces.convert
package, and they are compatible with any Java data type or even
standard classes like Date.

To define an Integer converter, first we create our property in the
managed bean used as a back end of our JSF form:

private Integer age;

// getters and setters

Then we create the component in our form using the f:converter tag:

<h:outputLabel value="Age:"/>
<h:inputText id="Age" value="#{convListVal.age}">
    <f:converter converterId="javax.faces.Integer" />
</h:inputText>
<h:message for="Age" />

In a similar way, we create the other numeric converters like the
Double converter:

private Double average;

Then we create the appropriate JSF component in our view. Please note
that we are using the variable average, which is then mapped to the
field using the getter and the setter by name convention:

<h:outputLabel value="Average:"/>
<h:inputText id="Average" value="#{convListVal.average}">
    <f:converter converterId="javax.faces.Double" />
</h:inputText>
<h:message for="Average" />

If we want to give the feedback to the user, we need to include an
h:message tag to be used by the control as a placeholder for error
messages.

A useful converter is the DateTime converter because it allows us to
validate dates, times and format these values.

First, as in previous converters, we declare our field with the getters
and setters:

private Date myDate;
// getters and setters

Then we create the component in our view. Here we need to enter the date
using the pattern, if the pattern is not used then we get an error with
an example of a correct pattern of the input:

<h:outputLabel value="Date:"/>
<h:inputText id="MyDate" value="#{convListVal.myDate}">
    <f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>
<h:message for="MyDate" />
<h:outputText value="#{convListVal.myDate}">
    <f:convertDateTime dateStyle="full" locale="en"/>
</h:outputText>

In our case, we can convert our input date and send the post data,
formatted as a full date in our h:outputText.

*3. Listeners

*

A listener allows us to monitor changes in our components; we are
monitoring when the value of a text field changes.

As before we define the properties in our managed bean:

private String name;

Then we define our listener in the view:

<h:outputLabel value="Name:"/>
<h:inputText id="name" size="30" value="#{convListVal.name}">
    <f:valueChangeListener type="com.baeldung.convListVal.MyListener" />
</h:inputText>

We set our h:inputText tag by adding an f:valueChangeListener and
also, inside the listener tag, we need to specify a class, which will be
used to perform the tasks when the listener is triggered.

public class MyListener implements ValueChangeListener {
    private static final Logger LOG = Logger.getLogger(MyListener.class.getName());

    @Override
    public void processValueChange(ValueChangeEvent event)
      throws AbortProcessingException {
        if (event.getNewValue() != null) {
            LOG.log(Level.INFO, "\tNew Value:{0}", event.getNewValue());
        }
    }
}

The listener class must implement the ValueChangeListener interface
and override the processValueChange() method to do the listener tasks,
to write a log message.

4. Validators

We use a validator to validate a JSF component data, with a set of
standard classes provided, to validate the user input.

Here, we defined a standard validator to enable us to check the length
of a user input in a text field.

First, we create our field in the managed bean:

private String surname;

Then we create our component in the view:

<h:outputLabel value="surname" for="surname"/>
<h:panelGroup>
    <h:inputText id="surname" value="#{convListVal.surname}">
        <f:validateLength minimum="5" maximum="10"/>
    </h:inputText>
    <h:message for="surname" errorStyle="color:red"  />
</h:panelGroup>

Inside the h:inputText tag we put our validator, to validate the
length of the input. Please remember that there are various standard
validators predefined in JSF and we can use them in a similar way to the
one presented here.

5. Tests

To test this JSF application, we are going to use Arquillian to perform
a functional testing with Drone, Graphene and Selenium Web Driver.

First, we deploy our application using ShrinkWrap:

@Deployment(testable = false)
public static WebArchive createDeployment() {
    return (ShrinkWrap.create(
      WebArchive.class, "jee7.war").
      addClasses(ConvListVal.class, MyListener.class)).
      addAsWebResource(new File(WEBAPP_SRC, "ConvListVal.xhtml")).
      addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}

Then we test the error messages of each component to verify that our
application is working properly:

@Test
@RunAsClient
public void givenAge_whenAgeInvalid_thenErrorMessage() throws Exception {
    browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf");
    ageInput.sendKeys("stringage");
    guardHttp(sendButton).click();
    assertTrue("Show Age error message",
      browser.findElements(By.id("myForm:ageError")).size() > 0);
}

Similar tests are performed on each component.

6. Summary

In this tutorial, we created implementations of converters, listeners,
and validators provided by JEE7.

You can find the code from the article
over on Github.

Leave a Reply

Your email address will not be published.