0

I am running the duke guess number example , I don't see the life cycle executing as expected. I have an inputText which expects a number. We also have a converter and a validator. Once I submit the <h:form> the validator is called. It should check the input if it is an integer. The value is not getting updated on the managed bean property. Please explain, below is the code snippet.

<h:inputText id="userNo" label="User Number" value="#{UserNumberBean.userNumber}" 
               converterMessage="#{ErrMsg.userNoConvert}"  validator="#{UserNumberBean.validate}">
      <f:valueChangeListener  type="#{UserNumberBean.valueChange()}"></f:valueChangeListener>
                  <f:validateLongRange minimum="#{UserNumberBean.minimum}" maximum="#{UserNumberBean.maximum}" /> 
  </h:inputText>

here the validator method is set in inputText component. Once I submit the <h:form>, the validate method is called, below is the method

public String validate(javax.faces.context.FacesContext fc, javax.faces.component.UIComponent ui, java.lang.Object o){
        System.out.println("in my own validation method");
        if(userNumber ==8){
            return "validation";
        }
        return "validation";
    }

here userNumber is the backing bean property of the class

public class UserNumberBean {

     public Integer userNumber = null;

public void setUserNumber(Integer user_number) {
        System.out.println("setting userName" + user_number);
        userNumber = user_number;
    }

    public Integer getUserNumber() {
        return userNumber;
    }
}

it has getters and setter but still userNumber value is not set. I get NullPointerException in validator method when accessing userNumber. Please let me know what is wrong. Below is the code snippet

<HTML xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <HEAD> <title>Hello</title> </HEAD>
    <%@ page contentType="application/xhtml+xml" %>
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    <body bgcolor="white">
    <f:view>
    <h:form id="helloForm" >
      <h2>Hi. My name is Duke.  I'm thinking of a number Man from
      <h:outputText lang="en_US" value="#{UserNumberBean.minimum}"/> to
      <h:outputText value="#{UserNumberBean.maximum}"/>.  Can you guess
      it?</h2>

      <h:graphicImage id="waveImg" url="/wave.med.gif" alt="Duke waving" />
      <h:inputText id="userNo" label="User Number" value="#{UserNumberBean.userNumber}" 
                   converterMessage="#{ErrMsg.userNoConvert}"  validator="#{UserNumberBean.validate}">
          <f:valueChangeListener  type="#{UserNumberBean.valueChange()}"></f:valueChangeListener>
                      <f:validateLongRange minimum="#{UserNumberBean.minimum}" maximum="#{UserNumberBean.maximum}" /> 
      </h:inputText>
      <h:commandButton id="submit" action="success" value="Submit" />
      <p>
      <h:message style="color: red; font-family: 'New Century Schoolbook', serif; font-style: oblique; text-decoration: overline" id="errors1" for="userNo"/>
    </p>
   </h:form>
  </f:view>
 </body>
</HTML> 




import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.LongRangeValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import java.util.Random;


public class UserNumberBean {
    Integer randomInt = null;
     public Integer userNumber = null;
    String response = null;
    private boolean maximumSet = false;
    private boolean minimumSet = false;
    private long maximum = 0;
    private long minimum = 0;

    public UserNumberBean() {

        System.out.println(" in constructor");
        Random randomGR = new Random();
        randomInt = new Integer(randomGR.nextInt(10));
        System.out.println("Duke's number: " + randomInt);
    }

    public void setUserNumber(Integer user_number) {
        System.out.println("setting userName" + user_number);
        userNumber = user_number;
    }

    public Integer getUserNumber() {
        return userNumber;
    }

    public String getResponse() {
        System.out.println(" in getResponse");
        if ((userNumber != null) && (userNumber.compareTo(randomInt) == 0)) {
            return "Yay! You got it!";
        } else {
            return "Sorry, " + userNumber + " is incorrect.";
        }
    }

    public long getMaximum() {
        return (this.maximum);
    }

    public void setMaximum(long maximum) {
        this.maximum = maximum;
        this.maximumSet = true;
    }

    public long getMinimum() {
        return (this.minimum);
    }

    public void setMinimum(long minimum) {
        this.minimum = minimum;
        this.minimumSet = true;
    }


    public String validate(javax.faces.context.FacesContext fc, javax.faces.component.UIComponent ui, java.lang.Object o){
        System.out.println("in my own validation method");
        if(userNumber ==8){
            return "validation";
        }
        return "validation";
    }

    public void valueChange(){
        System.out.println(" in value change");
    }
}

What actually is the Apply Request phase? What happens in Apply Request phase? How different is it from Update Model Values phase

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Ashwin
  • 47
  • 2
  • 11
  • 2
    Why are you learning JSF 1.x while JSF 2.x is already out more than 3.5 years? By the way, the statement in your title is completely wrong. It's definitely called. – BalusC Jul 18 '13 at 15:20

1 Answers1

4

Your validator is broken in 2 ways:

  1. Wrong method signature. It should return void. On validation faliures, you should be throwing a ValidatorException. On success you should just be returning and doing nothing additional.

  2. You should be validating the value provided as 3rd argument, not the model value (which isn't been set at that point at all).

So, this should do:

public void validate(FacesContext context, UIComponent component, Object value) {
    if (value == null) {
        return; // Ignore it. Let required="true" handle.
    }

    if (value != 8) {
        // Assuming that 8 is the guess number?
        throw new ValidatorException(new FacesMessage("Wrong guess, try again."));
    }
}

Your NullPointerException is caused because you're attempting to compare the model value userNumber to a primitive integer 8. This causes autoboxing to try to unbox userNumber to a primitive, however that fails if the userNumber itself is null which cannot be represented in any primitive form.

As to the phases, the apply request values phase is definitely called, the validations phase is otherwise never called. You seem to expect that the apply request values phase updates the model values. This is not true, it applies the request parameters on JSF input component's submittedValue.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555