Error de validación: el valor no es válido
Tengo un problema con ap:selectOneMenu, no importa lo que haga, no puedo lograr que JSF llame al configurador en la entidad JPA. La validación JSF falla con este mensaje:
formulario: ubicación: Error de validación: el valor no es válido
Tengo esto funcionando en varias otras clases del mismo tipo (es decir, unir clases de tabla) pero por mi vida no puedo hacer que esta funcione.
Si alguien puede ofrecer algunos consejos para la solución de problemas/depuración de este tipo de problemas, se lo agradecería mucho.
Usando declaraciones de registro, he verificado lo siguiente:
- Está
Conveter
devolviendo valores correctos, sinnull
valores. - No tengo Validación de Bean en mis entidades JPA.
- El armador
setLocation(Location location)
nunca es llamado.
Este es el ejemplo más simple que puedo hacer y simplemente no funcionará:
<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>
Convertidor:
@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());
}
}
Salida de consola:
// 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]
La validación falla con el mensaje "formulario: ubicación: Error de validación: el valor no es válido"
Este error se reduce a que el elemento seleccionado no coincide con ninguno de los valores de elementos seleccionados disponibles especificados por cualquier <f:selectItem(s)>
etiqueta anidada durante el procesamiento de la solicitud de envío del formulario.
Como parte de la protección contra solicitudes manipuladas/pirateadas, JSF reiterará todos los valores de artículos seleccionados disponibles y probará si selectedItem.equals(availableItem)
se devuelve true
al menos un valor de artículo disponible. Si ningún valor de elemento coincide, obtendrá exactamente este error de validación.
Este proceso se realiza básicamente como se muestra a continuación, por lo que bean.getAvailableItems()
representa ficticiamente la lista completa de elementos seleccionados disponibles según lo definido por <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");
}
Entonces, según la lógica anterior, este problema lógicamente puede tener al menos las siguientes causas:
- El artículo seleccionado falta en la lista de artículos disponibles.
- El
equals()
método de la clase que representa el elemento seleccionado falta o está roto. - Si hay una costumbre
Converter
involucrada, entonces ha devuelto el objeto incorrecto engetAsObject()
. Quizás sea inclusonull
.
Para solucionarlo:
- Asegúrese de que se conserve exactamente la misma lista durante la solicitud posterior, especialmente en el caso de varios menús en cascada. Hacer el frijol
@ViewScoped
en lugar de@RequestScoped
debería solucionarlo en la mayoría de los casos. También asegúrese de no realizar la lógica de negocios en el método getter de<f:selectItem(s)>
, sino en@PostConstruct
un método de evento de acción (escucha). Si confía en parámetros de solicitud específicos, deberá almacenarlos explícitamente en el@ViewScoped
bean o volver a pasarlos en solicitudes posteriores, por ejemplo<f:param>
, . Consulte también ¿Cómo elegir el alcance del bean adecuado? - Asegúrese de que el
equals()
método se implemente correctamente. Esto ya se hace correctamente en tipos Java estándar comojava.lang.String
,java.lang.Number
etc., pero no necesariamente en objetos/beans/entites personalizados. Consulte también Forma correcta de implementar el contrato de igualdad . En caso de que ya esté utilizandoString
, asegúrese de que la codificación de caracteres de solicitud esté configurada correctamente. Si contiene caracteres especiales y JSF está configurado para representar la salida como UTF-8 pero interpreta la entrada como, por ejemplo, ISO-8859-1, entonces fallará. Consulte también la entrada Unicode recuperada mediante componentes de entrada de PrimeFaces que se corrompen . - Depure/registre las acciones de su costumbre
Converter
y corríjalas en consecuencia. Para obtener pautas, consulte también el valor de configuración del Error de conversión para 'Convertidor nulo'. En caso de que esté utilizandojava.util.Date
elementos disponibles con<f:convertDateTime>
, asegúrese de no olvidar la parte de tiempo completo en el patrón. Consulte también el error "Error de validación: el valor no es válido" de f:datetimeConverter .
Ver también:
- Nuestra
selectOneMenu
página wiki - ¿Cómo completar las opciones de h:selectOneMenu desde la base de datos?
- Haga múltiples listas desplegables selectOneMenu dependientes/en cascada en JSF
Si alguien puede ofrecer algunos consejos para la solución de problemas/depuración de este tipo de problemas, se lo agradecería mucho.
Simplemente haga una pregunta clara y concreta aquí. No hagas preguntas demasiado amplias ;)
En mi caso, olvidé implementar métodos get/set correctos. Sucedió porque cambié muchos atributos a lo largo del desarrollo.
Sin un método de obtención adecuado, JSF no puede recuperar el elemento seleccionado y sucede lo que dijo BalusC en el elemento 1 de su respuesta:
1 . El artículo seleccionado falta en la lista de artículos disponibles. Esto puede suceder si la lista de elementos disponibles es entregada por un bean con ámbito de solicitud que no se reinicia correctamente en una solicitud posterior, o si realiza incorrectamente el trabajo comercial dentro de un método getter, lo que hace que devuelva una lista diferente de alguna manera.