Validation Error: Value is not valid

86,762

Solution 1

Validation fails with the message "form:location: Validation Error: Value is not valid"

This error boils down to that the selected item does not match any of the available select item values specified by any nested <f:selectItem(s)> tag during processing of the form submit request.

As part of safeguard against tampered/hacked requests, JSF will reiterate over all available select item values and test if selectedItem.equals(availableItem) returns true for at least one available item value. If no one item value matches, then you'll get exactly this validation error.

This process is under the covers basically as below, whereby bean.getAvailableItems() fictionally represents the entire list of available select items as defined by <f:selectItem(s)>:

String submittedValue = request.getParameter(component.getClientId());
Converter converter = component.getConverter();
Object selectedItem = (converter != null) ? converter.getAsObject(context, component, submittedValue) : submittedValue;

boolean valid = false;

for (Object availableItem : bean.getAvailableItems()) {
    if (selectedItem.equals(availableItem)) {
        valid = true;
        break;
    }
}

if (!valid) {
    throw new ValidatorException("Validation Error: Value is not valid");
}

So, based on the above logic, this problem can logically have at least the following causes:

  1. The selected item is missing in the list of available items.
  2. The equals() method of the class representing the selected item is missing or broken.
  3. If a custom Converter is involved, then it has returned the wrong object in getAsObject(). Perhaps it's even null.

To solve it:

  1. Ensure that exactly the same list is been preserved during the subsequent request, particularly in case of multiple cascading menus. Making the bean @ViewScoped instead of @RequestScoped should fix it in most cases. Also make sure that you don't perform the business logic in the getter method of <f:selectItem(s)>, but instead in @PostConstruct or an action event (listener) method. If you're relying on specific request parameters, then you'd need to explicitly store them in the @ViewScoped bean, or to re-pass them on subsequent requests by e.g. <f:param>. See also How to choose the right bean scope?
  2. Ensure that the equals() method is implemented right. This is already done right on standard Java types such as java.lang.String, java.lang.Number, etc, but not necessarily on custom objects/beans/entites. See also Right way to implement equals contract. In case you're already using String, make sure that the request character encoding is configured right. If it contains special characters and JSF is configured to render the output as UTF-8 but interpret the input as e.g. ISO-8859-1, then it will fail. See also a.o. Unicode input retrieved via PrimeFaces input components become corrupted.
  3. Debug/log the actions of your custom Converter and fix it accordingly. For guidelines, see also Conversion Error setting value for 'null Converter' In case you're using java.util.Date as available items with <f:convertDateTime>, make sure that you don't forget the full time part in the pattern. See also "Validation Error: Value is not valid" error from f:datetimeConverter.

See also:


If anyone can throw some troubleshooting/debugging tips for this sort of problem it would be greatly appreciated.

Just ask a clear and concrete question here. Do not ask too broad questions ;)

Solution 2

In my case I forgot to implement a correct get/set methods. It happened because I have changed a lot of attributes along the development.

Without a proper get method, JSF can´t recover your selected item, and happens what BalusC said at item 1 of his answer:

1 . The selected item is missing in the list of available items. This can happen if the list of available items is served by a request scoped bean which is not properly reinitialized on subsequent request, or is incorrectly doing the business job inside a getter method which causes it to return a different list in some way.

Solution 3

This can be a Converter Issue or else DTO issue. Try to solve this, by adding hashCode() and equals() methods in your object DTO; In the above scenario you can generate these methods within the Location object class which indicate as the 'DTO' here.

Example:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (id ^ (id >>> 32));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Location other = (Location) obj;
    if (id != other.id)
        return false;
    return true;
}
  • Please note that the above example is for an 'id' of type 'long'.
Share:
86,762

Related videos on Youtube

klonq
Author by

klonq

Updated on July 05, 2022

Comments

  • klonq
    klonq almost 2 years

    I have a problem with a p:selectOneMenu, no matter what I do I cannot get JSF to call the setter on the JPA entity. JSF validation fails with this message:

    form:location: Validation Error: Value is not valid

    I have this working on several other class of the same type (ie, join table classes) but cannot for the life of me get this one working.

    If anyone can throw some troubleshooting/debugging tips for this sort of problem it would be greatly appreciated.

    Using log statements I have verified the following:

    1. The Conveter is returning correct, non null values.
    2. I have no Bean Validation in my JPA entities.
    3. The setter setLocation(Location location) is never called.

    This is the simplest example I can do and it simply will not work:

    <h:body>
        <h:form id="form">
            <p:messages id="messages" autoUpdate="true" />
            <p:selectOneMenu id="location" value="#{locationStockList.selected.location}" converter="locationConverter">
                <p:ajax event="change" update=":form:lblLocation"/>
                <f:selectItems value="#{locationStockList.locationSelection}"/>
            </p:selectOneMenu>
        </h:form>
    </h:body>
    

    Converter:

    @FacesConverter(forClass=Location.class, value="locationConverter")
    public class LocationConverter implements Converter, Serializable {
        private static final Logger logger = Logger.getLogger(LocationConverter.class.getName());
    
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            if (value.isEmpty())
                return null;
            try {
                Long id = Long.parseLong(value);
                Location location = ((LocationManagedBean) context.getApplication().getELResolver().getValue(context.getELContext(), null, "location")).find(id);
                logger.log(Level.SEVERE, "Converted {0} to {1}" , new Object[] {value, location});
                return location;
            } catch (NumberFormatException e) {
                return new Location();
            }
        }
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            if (value == null || value.toString().isEmpty() || !(value instanceof Location))
                return "";
            return String.valueOf(((Location) value).getId());
        }    
    }
    

    Console output:

    // Getter method
    INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 
    // Session Bean
    INFO: Finding ejb.locations.Location with id=3 
    // Session Bean
    INFO: ### Returning : ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
    // Converter
    SEVERE: Converted 3 to ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
    // Getter method -> Where did my selected Location go ??
    INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 
    
  • Thang Pham
    Thang Pham over 11 years
    @BalusC: Where exactly is it in the mojarra code, that this equals check happen. My situation is a bit complex. I create my own custom component that allow the user to have complex radio layout. It works fine if I just have one radio group (f:selectItems right underneath my custom component). However as the layout get more complex (multiple radio group, each have their own f:selectItems but all share the same selection), I have to have f:selectItems inside ui:repeat, then the ui:repeat is under my custom component. I then ran into this issue. I want to see the mojarra code that handle this
  • Thang Pham
    Thang Pham over 11 years
    Also my f:selectItems is String type, so I am sure this is not a conversion problem, I think this is cause because the list of f:selectItems is not there during validation phase.
  • Agustí Sánchez
    Agustí Sánchez over 9 years
    Can you elaborate on how to use f:param to send state to the managed bean so that it can recreate the "initial state"??? Thanks.
  • Gilberto
    Gilberto over 9 years
    Having a similar error. I'm using the SelectItemsConverter and this component is inside a disabled fieldset - so it is disabled as well. Is it a known behavior?
  • Philip Puthenvila
    Philip Puthenvila over 8 years
    If you are using enum for the items to display and your backing bean have String type for setting the value in the bean and not using any converters you will get the same error. That is how I ended up here.
  • Mateus Viccari
    Mateus Viccari almost 7 years
    If i want to use my controller as @RequestScoped, what can i do to reinitialize it? I tried to load the items in the @PostConstruct method, but i got the value is not valid error.
  • Rafael Segovia
    Rafael Segovia about 6 years
    Could it be possible that this error happens if there are two selectItems with different values but same description(visible text)? It has happened to me, and when deleted from database one of them, error message does not show up again...
  • BalusC
    BalusC about 6 years
    Only if its equals() is broken, which is already covered by the answer.
  • Kukeltje
    Kukeltje over 5 years
    Like stated in #2 in the accepted and highly upvoted answer
  • Joe
    Joe almost 5 years
    @BalusC, I have a field which is not required=true and it is a date field, i do have validation for this field at the server sided based on other field value( like if the field 1 value is Y then enter date and validate the date if they are correct at server side). but when i try to enter wrong values in the date field like 11/11 and submit then it validates and gives error message. so how do i stop validation for one particular field all the time as i have validation for those field/all the field at server side. ?