0

I have some inputtext in a form which is managed by a bean @Named and i would like to centralize the information concerning this fields such as which validator is assigned to which field.

If i directly write the name of the @FaceValidator, it works.

<h:inputText validator="validatorLogin"/>

If i tried to put the name of the validator with a bean property such as String validatorLogin = validatorLogin.

It will throw an error in the .xhtml like "Expression must be a method expression but is a value expression".

If i try to still run the code it will throw the following exception "validator=#{bean.validatorLogin}: Method not found".

<h:inputText validator="#{bean.validatorLogin}"/>

I expect the validator name to be set in the bean and the bean to feed the validator id in the inputtext field. So all informations about the form are centralized in one bean.

As well is it dumb to do so or is it something that will make the code more organized ?

fra
  • 33
  • 8
  • Why do you want to do this? Do you conditionally switch the validator? If not, simply hard code the validatorId into the validator attribute. – Selaron Apr 05 '19 at 06:49
  • I was thinking that the information about how validation is done on the page should be contained in the ManagedBean. So we only check in the bean to know information about the logic, front page contains only design. – fra Apr 07 '19 at 21:28

1 Answers1

1

As the validator attribute documentation states, there is no way to provide a validatorId via bean property to this attribute:

validator: MethodExpression representing a validator method that will be called during Process Validations to perform correctness checks on the value of this component. The expression must evaluate to a public method that takes FacesContext, UIComponent, and Object parameters, with a return type of void.

You would normally either hard code a validatorId as you did in your first example, or a method expression (in your second example) that resolves to a method like this:

public void validatorLogin(FacesContext context, UIComponent component, Object value)
        throws ValidatorException {
    // ...
}

Of course it's up to this bean implementation how the input is validated then. If you want to combine both approaches, you can delegate validation to one (or multiple) validators known by ID in your validatorLogin method:

public void validatorLogin(FacesContext context, UIComponent component, Object value)
        throws ValidatorException {
    final Collection<String> validatorIds = determineValidatorIds(context, component);
    for (String validatorId : validatorIds) {
        Validator<Object> validator = context.getApplication().createValidator(validatorId);
        validator.validate(context, component, value);
    }
}

private Collection<String> determineValidatorIds(FacesContext context, UIComponent component) {
    // return hard coded validatorIDs or determine them on arbitrary logic.
}

If you urgently need to provide a validatorId via bean property, you can do so by using the f:validator tag within your input component:

<h:inputText id="txt" value="#{myBean.textValue}">
    <f:validator validatorId="#{myBean.arbitraryValidatorId}" />
</h:inputText>
Selaron
  • 5,617
  • 4
  • 26
  • 38
  • thank you for your answer. What i try to do is from the hard coded id . I would like that this hard coded string is in an external class as a field. so i can use it this way. . Basically i want the hard coded id of the validator to be somewhere in an external class and use this class to retrieve the id name. – fra Apr 08 '19 at 23:29
  • But when i try, it will throw errors such as It will throw an error in the .xhtml vlalidation like "Expression must be a method expression but is a value expression". If i bypass the xhtml validation error and i try to still run the code, it will throw the following exception "validator=#{bean.validatorLogin}: Method not found". – fra Apr 08 '19 at 23:29
  • You can implement my method `determineValidatorIds` to return the result of `#{bean.fields.validatorIdForInputText}`. You can't `validator="#{bean.fields.validatorIdForInputText}"` because a method expression is expected. – Selaron Apr 09 '19 at 06:03
  • Thank you, yes i think your implementation can be used for the meantime. Long term will be nice to use a property of the bean to return the id rather than using a method. – fra Apr 10 '19 at 02:00
  • @fra I have updated my answer and added `f:validator` tag as alternative. – Selaron Apr 10 '19 at 06:33
  • Thank you for the solution, it gives options and it is a good idea. I tried the and it returns a object null exception while myBean was properly registered as @Name("myBean"). – fra Apr 11 '19 at 19:25
  • Without knowing exception details I'd guess it's a very different topic and a candidate for [Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable](https://stackoverflow.com/questions/30128395/identifying-and-solving-javax-el-propertynotfoundexception-target-unreachable) – Selaron Apr 11 '19 at 20:55
  • I think the error is related to the fact that it is not something that can be done. I will need to dig it further. For now your answer is accepted. A big thank you for the help, you really took time to give relevant comments and solutions. Thank you @Selaron. – fra Apr 12 '19 at 00:24
  • You are welcome! Do you mean `` is not possible? For me that worked (using Mojarra 2.3.3). – Selaron Apr 12 '19 at 06:23
  • @Seleron , yes it did not work. I will do further test and post a comment here in case it is not something coming from my side. Thank you again. – fra Apr 15 '19 at 00:27