2

I want to create validator for input filed in order to check values and send error message if the inserted value is not int.

bean:

public class PricingCalculatorValidator implements Validator
{
    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
    {
        // Cast the value of the entered input to String.
        String input = (String) value;

        // Check if they both are filled in.
        if (input == null || input.isEmpty())
        {
            return; // Let required="true" do its job.
        }

        // Compare the input with the confirm input.
        if (containsDigit(input))
        {
            throw new ValidatorException(new FacesMessage("Value is not number."));
        }
    }

    public final boolean containsDigit(String s)
    {
        boolean containsDigit = false;

        if (s != null && !s.isEmpty())
        {
            for (char c : s.toCharArray())
            {
                if (containsDigit = Character.isDigit(c))
                {
                    break;
                }
            }
        }

        return containsDigit;
    }

}

What is the proper way to cast the inserted value? Now I get exception

serverError: class java.lang.ClassCastException java.lang.Integer cannot be cast to java.lang.String
Peter Penzov
  • 1,126
  • 134
  • 430
  • 808
  • I think the proper way to do that is with a converter. You can use `f:convertNumber` for instance. – Diego Jun 24 '15 at 20:38
  • looks like your value argument is coming as of type `Integer`. In that case `String input = (String) value;` this won't work. If you want it to be converted to `String`, you can try `value.toString();`. This will give you `String` representation of `Integer` value. – Amit.rk3 Jun 24 '15 at 20:42

2 Answers2

4

As per the exception, JSF is actually passing an Integer instance as value to the validate() method. Technically, you should be casting it to Integer as below to keep the Java runtime happy.

// Cast the value of the entered input to Integer.
Integer input = (Integer) value;

Apparently you already bound the input field to an Integer property in the model like so:

<h:inputText value="#{bean.pricing}" />
private Integer pricing;

In other words, the whole custom validator is unnecessary. There's no point of validating if the value is an integer if it's already an Integer in first place. It can impossibly contain a non-digit as value.

Just get rid of that custom validator altogether.

JSF has several builtin converters for standard types like Integer which run automatically depending on the model value type. And, converters run right before validators. That's why the value already arrives as Integer in your custom validator. The only thing which seems relevant in your custom validator is the error message which is different from the standard conversion error message. In case you merely wanted to customize the conversion error message on the specific input field, just set it as converterMessage attribute on the input field.

<h:inputText value="#{bean.pricing}" converterMessage="Value is not numeric." />

Unrelated to the concrete problem, "validating" if the value represents a valid Integer or not (this process is in JSF actually called conversion and is supposed to take place in a custom converter) can be performed in a much simpler way:

String string = getItSomehowWithoutClassCastException();

try {
    Integer integer = Integer.valueOf(string);
} catch (NumberFormatException e) {
    throw new ConverterException(new FacesMessage("Value is not an integer."));
}

No need to inspect every single digit if you ultimately want to get an Integer. As said, the JSF builtin converter already takes care of this.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • One small question: I have a form with 20 input fields. If I insert wrong values into each field only the last one error message is shown. How I can show error message as long as there is a wrong value into the input fields? – Peter Penzov Jun 24 '15 at 21:28
  • Depends on how you're updating/displaying error messages. This is not related to the current question. – BalusC Jun 24 '15 at 21:33
1

You don't have to verify each character. Just perform:

boolean isDigit = true;
try {
    new Integer(input).intValue();
} catch (NumberFormatException nfe) {
    isDigit = false;
}

If any of the chars in input is not a number, the catch block will be executed, otherwise, that block will be skipped. At the end, isDigit tells you whether input is an integer or not. Note, if your input has too many digits to be an integer, it will also tell you that input is not an integer, even if every single character is a digit.

Mohammad Faisal
  • 5,783
  • 15
  • 70
  • 117