Skip to main content

5. JSF Validating Inputs part 2/2

0. Introduction


I am an old poor beginner and I am very pleased with the help of Java gurus like Marty Hall and his coreservlet page. So while learning his invaluable lessons, I try to give an example.

I will cover 3 aspects:

  1. Validating by means of Action Controller of a managed bean 
  2. Using custom validator method with validator attribute 
  3. Validation through Bean Validation JSR 380

1. Validation using a managed bean action controller

In order to display messages, these steps may be needed:

  1. A xhtml tag <h:message for="control_to_validate_id">
  2. But it is preferred a <h:messages ..> to put messages at the top of the form
  3. Add messages to display by means of java code:
FacesMessage errorMessage = new FacesMessage("This an error ..");
errorMessage.setSeverity(FacesMessages.SERVERITY_ERROR); 
FacesContext.getCurrentInstance().addMessage(null, errorMessage);

The severity can be:

  1. SEVERETY_ERROR (for errors)
  2. SEVERETY_INFO (informational messages)

The value null in red color means that it is a global message, not specific to a field or control. If it refers to a control, instead of null, "formID:fieldID" should be supplied. "formID" is the id indicated in the <h:form> tag.

To verify if any message has been created, it may be used:

context.getMessageList().size()

In this example we are using <f:convertDateTime pattern="MM/dd/yyyy"/> to convert string to dates

Let's see the xhtml code (ttest05-validation-page.xhtml)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core" 
      xmlns:p="http://primefaces.org/ui">  
    <h:head>  
    </h:head>  
      
    <h:body>  
      <h:form>  
        <h2>VALIDATION EXAMPLE</h2>
        <h:messages styleclass="error"/>
                     
        <p:panelGrid  columns="2">  
          <!-- First line -->  
    Start date:
    <h:inputText value="#{conversionBean.startDate}"
                    required="true" requiredMessage="Start date required"
                    converterMessage="Illegal date (should be mm/dd/yyyy)">
         <f:convertDateTime pattern="MM/dd/yyyy"/>  
       </h:inputText>           
       
          
          <!--Second line --> 
          Start date:
    <h:inputText value="#{conversionBean.endDate}"
                    required="true" requiredMessage="End date required"
                    converterMessage="Illegal date (should be mm/dd/yyyy)">
         <f:convertDateTime pattern="MM/dd/yyyy"/>  
       </h:inputText>           
       
        </p:panelGrid>sen
        <h:commandButton value="Send" action="#{conversionBean.send}"/>
                         
      </h:form>
    </h:body>  
</html>


The bean used in the last post, has been updated (ConversionBean.java)



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package org.ximodante.jsf.validation;

import java.io.Serializable;
import java.util.Date;

import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import lombok.Getter;
import lombok.Setter;

/**
 * For numeric conversion use objects and no primitives
 *   Use Double, Integer instead of double and int
 * @author Ximo Dante
 *
 */
@Named
@SessionScoped
public class ConversionBean implements Serializable {
 
 
 private static final long serialVersionUID = 20171024L;
 @Getter @Setter private Integer anyInteger=0;
 @Getter @Setter private Double anyDouble= 0.0;
 @Getter @Setter private Integer anyInteger2=-1;
 @Getter @Setter private Double anyDouble2= -50.0;
 @Getter @Setter private String string3_5;
 @Getter @Setter private String stringRegex;
 
 @Getter @Setter private Date startDate;
 @Getter @Setter private Date endDate;
 
 
 public String send() {
  String messageText = null;
   
  if (!startDate.before(endDate)) {
      messageText = "Date begin must be before date end";
  }
  
  if (messageText != null) {
      startDate = null;
      endDate = null;
      FacesMessage errorMessage = new FacesMessage(messageText);
      errorMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
      FacesContext.getCurrentInstance().addMessage(null, errorMessage);
      return(null);
  } else {
      return("test06-validationOK-page"); 
  }
 } 
}


2.Validating using custom validator method with validator attribute.

In this case, the xhtml code is:

<h:inputText validator="#someBean.someValidatorMethod}">

In the java part:

public void someValidatorMethod 
    (FacesContext context, 
     UIComponent componenToValidate, 
     Object value) throws Validator Exception{
  //When an error occurs:
  String messageText= "This error has been produced..";
  FacesMessage errorMessage = new FacesMessage(messageText);
  errorMessage.setSeverity(FacesMessage.SEVERETY_ERROR);
  throw new ValidationException(errorMessage);  
}

As we can see, when an error occurs, an error message should be provided and a ValidationException thrown.

3. Validating through Validator classes (components)


We can also define validator classes that affects only one control. In this case the xhtml code is:

    <h: inputText ..>
    <f:validator validatorId="someId"/>
  <h:inputText>

 And the java class code is:

@FacesValidator("someId")
public class SomeValidator implements Validator
  @Override
  public voild validate(..) ..{ 
  }
}


4. Validating with Bean Validation

It is the plainest validation method. Here is a simple xhtml file:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core" 
      xmlns:p="http://primefaces.org/ui">  
    <h:head>  
    </h:head>  
      
    <h:body>  
      <h:form> 
         
        <h2>VALIDATION EXAMPLE</h2>
        <p:panelGrid  columns="3">  
          <!-- First line -->  
          Name:
          <h:inputText value="#{validationBean.name}" id="idName"/>
          <h:message for="idName"/>
          
          <!-- 2ond line -->
          URL:
          <h:inputText value="#{validationBean.url}" id="idUrl"/>
          <h:message for="idUrl"/>
          
          <!--3rd line --> 
          Email Address:
          <h:inputText value="#{validationBean.emailAddress}" id="idEmailAdress"/>
          <h:message for="idEmail"/>
          
          <!--4th line --> 
          Credit Card
          <h:inputText value="#{validationBean.cardNumber}" id="idCardNumber1"/>
          <h:message for="idCardNumber1"/>
          
          <!--5th line --> 
          Repeat Credit Card
          <h:inputText value="#{validationBean.cardNumberConfirmation}" id="idCardNumberConfirmation"/>
          <h:message for="idCardNumberConfirmation"/>
          
           
                 
        </p:panelGrid>
        <h:commandButton value="Submit" action="#{validationBean.sendReport}"/>
                         
      </h:form>
    </h:body>  
</html>


and the validation is at the bean


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package org.ximodante.jsf.validation;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.CreditCardNumber;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.URL;

import lombok.Getter;
import lombok.Setter;

@Named
@SessionScoped
public class ValidationBean implements Serializable {
 
 private static final long serialVersionUID = 20171030L;
 
 @Getter @Setter
 @Size(min = 3, message = "Name should at least be 3 characters long")
 private String name;
 
 @Getter @Setter
 private String problemDescription;
 
 @Getter @Setter @Email
 private String emailAddress; 
 
 @Getter @Setter @URL(message = "Should be a valid URL my folk!")
 private String url; 
 
 
 @Getter @Setter @CreditCardNumber private String cardNumber=""; 
 @Getter @Setter @CreditCardNumber private String cardNumberConfirmation; 

 public String getAbbreviatedCardNumber() {
  // Returns last four digits of card number
  return "1234";
 }
 public String sendReport() {
  System.out.println("Sending Report ...");
  //storeReportInDatabase();
  return("test07-ok-page"); 
 }
}

Simpler? Nearly impossible.... but not as good as I would like!.

Note:

  1. I talk out of Apache MyFaces <mcv:validateBlah> as I am getting into trouble with versions and no solution found while googling!
  2. Take care that @Email and @URL do not validate fields in a good manner! A good knowledge of Regex should be acquired!
  3. Another way of validating is using Java with Apache commons validator library!



Comments