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

Popular posts from this blog

10. JSF How to access my resources files?

Sometimes it is really difficult to access any resources form different Java applications. So let's see some scenarios: 1. Executable jar application in a NO WEB environment. Take into account that this is not a JSF application !!! It is desired to have a property file outside the "jar file" so that we can change properties when needed. For instance, we will place the properties file in the same folder that the "jar file" lies. To access the folder where the jar is, the trick is to access the folder where the compiled classed are placed and scale 3 folders . (Oh! rather strange, if anybody knows a better idea.., he will be welcome). Here is a simple code. The name of the class containing the code is ThisClass, and we have created a Property class that feeds with a file in the same folder that the" jar 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 /** * Gets the folder where resides the executable...

9. JSF: Solving common problems

1. Target Unreachable, identifier [bean] resolved to null When you reference a bean in a xhtml file with "#{bean.method}" and get this error, you should verify that: The bean implements Serializable . The references (javax.servlet-api.4.0.0, javax.faces.2.3.3,  javax.el.api.3.0.1, org.primefaces.6.1) have been selected in your pom.xml You have created the files bean.xml and faces-config.xml in the webapp/WEB-INF folder You have used the correct annotations from CDI  (javax.inject.Named and javax.enterprise.context.SessionScoped, ...) and not ManagedBean or jsf2.2 scopes. 2. Bean declaring a passivating scope must be passivation capable This error causes server not starting and fills up the console with long chained exceptions. It is very annoying. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 SEVERE: A child container failed during start java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to star...

2. Create a Maven JSF project and a simple login page

Updated on Oct-25-2107 0. Introduction Remember to install previously: Java JDK 8 Eclipse Oxygen Lombok  Apache Tomcat 9 1. Create a Maven Project In the top menu select : File - New - Maven Project Press Next Now fill the next form as follows It is important to select: Group id: org.ximodante.jsf  (or another packet you like) Packaging: war Artifact Id and Name: JSFv02 or any name for the project Press Finish 2. The pom.xml file Eclipse complains about the simple generated file. It seems that a web.xml is required if the packaging is selected to war. The simple generated file is  1 2 3 4 5 6 7 8 9 <project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion> 4.0.0 </modelVersion> <groupId> org.ximodante...