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:
Conveter
is returning correct, non null
values.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]
Validations errors are errors when users do not respond to mandatory questions. A validation error occurs when you have validation/response checking turned on for one of the questions and the respondent fails to answer the question correctly (for numeric formatting , required response).
It is precisely because validation errors can be caused by such a wide range of reasons (i.e. the input's content, length, formatting, etc) that it is so important to let the user know exactly why their input failed because they'll otherwise have to try and work it out themselves.
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:
equals()
method of the class representing the selected item is missing or broken.Converter
is involved, then it has returned the wrong object in getAsObject()
. Perhaps it's even null
.To solve it:
@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? 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.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.selectOneMenu
wiki pageIf 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 ;)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With