Error de validación: el valor no es válido

Tengo un problema con ap: selectOneMenu, no importa lo que haga, no puedo hacer que JSF llame al setter en la entidad JPA. La validación de JSF falla con este mensaje:

formulario: ubicación: Error de validación: el valor no es válido

Tengo esto trabajando en varias otras clases del mismo tipo (es decir, unirme a las clases de tabla) pero no puedo por mi vida hacer que funcione.

Si alguien puede arrojar algunos consejos para la solución de problemas / depuración para este tipo de problema, sería muy apreciado.

Usando declaraciones de registro, he verificado lo siguiente:

  1. El Conveter está devolviendo valores correctos, no null .
  2. No tengo Validación de frijol en mis entidades JPA.
  3. El conjunto setLocation(Location location) nunca se llama.

Este es el ejemplo más simple que puedo hacer y simplemente no funcionará:

   

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 la 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 etiqueta anidada durante el procesamiento de la solicitud de envío del formulario.

Como parte de la protección contra las solicitudes manipuladas / pirateadas, JSF reiterará todos los valores de elementos seleccionados disponibles y probará si selectedItem.equals(availableItem) devuelve true para al menos un valor de artículo disponible. Si no coincide el valor de un elemento, obtendrá exactamente este error de validación.

Este proceso está bajo las cubiertas básicamente como abajo, donde bean.getAvailableItems() representa ficticiamente la lista completa de elementos selectos disponibles según lo definido por :

 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, basado en la lógica anterior, este problema lógicamente puede tener al menos las siguientes causas:

  1. El elemento seleccionado falta en la lista de elementos disponibles.
  2. El método equals() de la clase que representa el elemento seleccionado falta o está roto.
  3. Si se trata de un Converter personalizado, ha devuelto el objeto incorrecto en getAsObject() . Quizás es incluso null .

Para resolverlo:

  1. Asegúrese de que se conserva exactamente la misma lista durante la solicitud posterior, especialmente en el caso de múltiples menús en cascada. Hacer que Bean @ViewScoped lugar de @RequestScoped lo arregle 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 , sino en el @PostConstruct o un evento de acción (oyente). Si confía en parámetros de solicitud específicos, deberá almacenarlos explícitamente en el bean @ViewScoped , o volver a pasarlos a solicitudes posteriores, por ejemplo, . Consulte también ¿Cómo elegir el scope del frijol correcto?
  2. Asegúrese de que el método equals() se implemente correctamente. Esto ya se hace correctamente en tipos Java estándar como java.lang.String , java.lang.Number , etc., pero no necesariamente en objetos personalizados / beans / entites. Ver también La forma correcta de implementar es igual a contrato . En caso de que ya esté utilizando String , asegúrese de que la encoding de caracteres de la 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, fallará. Consulte también si la entrada Unicode recuperada a través de los componentes de entrada PrimeFaces se daña .
  3. Depure / registre las acciones de su Converter personalizado y corríjalo según corresponda. Para obtener instrucciones, consulte también Valor de configuración de error de conversión para ‘convertidor nulo’ En caso de que esté utilizando java.util.Date como elementos disponibles con , 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 página wiki selectOneMenu
  • Cómo llenar las opciones de h: selectOneMenu de la base de datos?
  • Hacer múltiples listas desplegables selectOneMenu dependientes / en cascada en JSF

Si alguien puede arrojar algunos consejos para la solución de problemas / depuración para este tipo de problema, sería muy apreciado.

Simplemente haga una pregunta clara y concreta aquí. No haga preguntas demasiado amplias;)

En mi caso, olvidé implementar un método correcto de obtención / configuración. Sucedió porque he cambiado 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 punto 1 de su respuesta:

1. El elemento seleccionado falta en la lista de elementos disponibles. Esto puede suceder si la lista de artículos disponibles es servida por un bean con ámbito de solicitud que no se reinicializa adecuadamente en una solicitud posterior, o realiza incorrectamente el trabajo comercial dentro de un método getter que ocasiona que devuelva una lista diferente de alguna manera.

Esto puede ser un Issue Converter o un problema DTO. Intente resolver esto agregando los métodos hashCode () y equals () en su objeto DTO; En el escenario anterior, puede generar estos métodos dentro de la clase de objeto Ubicación que indican como ‘DTO’ aquí.

Ejemplo:

 @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; } 
  • Tenga en cuenta que el ejemplo anterior es para un ‘id’ de tipo ‘largo’.