Erro de validação: o valor não é válido

Eu tenho um problema com ap: selectOneMenu, não importa o que eu faço, não consigo fazer com que o JSF chame o setter na entidade JPA. A validação do JSF falha com esta mensagem:

formulário: localização: Erro de validação: o valor não é válido

Eu tenho este trabalho em várias outras classs do mesmo tipo (ou seja, juntar as classs de tabela), mas não pode para a vida de mim conseguir este trabalho.

Se alguém puder lançar algumas dicas de solução de problemas / debugging para esse tipo de problema, seria muito apreciado.

Usando as instruções de log, verifiquei o seguinte:

  1. O Conveter está retornando valores corretos e não null .
  2. Eu não tenho nenhuma validação de bean em minhas entidades JPA.
  3. O setter setLocation(Location location) nunca é chamado.

Este é o exemplo mais simples que posso fazer e simplesmente não funciona:

   

Conversor:

 @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()); } } 

Saída do console:

 // 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] 

A validação falha com a mensagem “formulário: localização: erro de validação: o valor não é válido”

Esse erro se resume a que o item selecionado não corresponde a nenhum dos valores de item de seleção disponíveis especificados por qualquer tag aninhada durante o processamento da solicitação de envio de formulário.

Como parte da proteção contra solicitações adulteradas / violadas, o JSF reiterará todos os valores de itens selecionados disponíveis e testará se selectedItem.equals(availableItem) retornar true para pelo menos um valor de item disponível. Se nenhum valor de item corresponder, você receberá exatamente esse erro de validação.

Este processo está sob as capas basicamente como abaixo, em que bean.getAvailableItems() representa de forma fictícia toda a lista de itens selecionados disponíveis conforme 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"); } 

Portanto, com base na lógica acima, esse problema pode logicamente ter pelo menos as seguintes causas:

  1. O item selecionado está faltando na lista de itens disponíveis.
  2. O método equals() da class que representa o item selecionado está ausente ou quebrado.
  3. Se um Converter personalizado estiver envolvido, ele retornou o object errado em getAsObject() . Talvez seja mesmo null .

Para resolvê-lo:

  1. Certifique-se de que exatamente a mesma lista tenha sido preservada durante a solicitação subsequente, especialmente no caso de vários menus em cascata. Tornar o bean @ViewScoped vez de @RequestScoped deve corrigi-lo na maioria dos casos. Além disso, certifique-se de não executar a lógica de negócios no método getter de , mas em @PostConstruct ou de um evento de ação (listener). Se você estiver confiando em parâmetros de solicitação específicos, precisará armazená-los explicitamente no bean @ViewScoped ou repassá-los em solicitações subsequentes, por exemplo, . Veja também Como escolher o escopo correto do bean?
  2. Certifique-se de que o método equals() esteja implementado corretamente. Isso já é feito diretamente em tipos Java padrão, como java.lang.String , java.lang.Number , etc, mas não necessariamente em objects personalizados / beans / entites. Veja também Maneira correta de implementar o contrato de iguais . Caso você já esteja usando o String , verifique se a codificação do caractere de solicitação está configurada corretamente. Se contiver caracteres especiais e o JSF estiver configurado para renderizar a saída como UTF-8, mas interpretar a input como, por exemplo, ISO-8859-1, ela falhará. Veja também a input Unicode recuperada via componentes de input PrimeFaces corrompidos .
  3. Depure / registre as ações do seu Converter personalizado e corrija-o de acordo. Para obter orientações, consulte também Valor da configuração de erro de conversão para ‘null Converter’ Caso você esteja usando java.util.Date como itens disponíveis com , certifique-se de não esquecer a parte do tempo integral no padrão . Consulte também “Erro de validação: o valor não é válido” erro de f: datetimeConverter .

Veja também:

  • Nossa página wiki selectOneMenu
  • Como preencher as opções de h: selectOneMenu do database?
  • Faça várias listas suspensas selectOneMenu dependentes / em cascata no JSF

Se alguém puder lançar algumas dicas de solução de problemas / debugging para esse tipo de problema, seria muito apreciado.

Basta fazer uma pergunta clara e concreta aqui. Não faça perguntas muito amplas;)

No meu caso, esqueci de implementar os methods get / set corretos. Aconteceu porque mudei muitos atributos ao longo do desenvolvimento.

Sem um método get adequado, o JSF não pode recuperar o item selecionado, e acontece o que a BalusC disse no item 1 de sua resposta:

1 O item selecionado está faltando na lista de itens disponíveis. Isso pode acontecer se a lista de itens disponíveis for atendida por um bean com escopo de solicitação que não é reinicializado corretamente na solicitação subseqüente ou estiver executando incorretamente o trabalho de negócios dentro de um método getter, fazendo com que ele retorne uma lista diferente de alguma forma.

Isso pode ser um problema de conversor ou outro problema de DTO. Tente resolver isso, adicionando os methods hashCode () e equals () ao seu object DTO; No cenário acima, você pode gerar esses methods dentro da class de object Location, que indica como ‘DTO’ aqui.

Exemplo:

 @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; } 
  • Por favor, note que o exemplo acima é para um ‘id’ do tipo ‘long’.