Ошибка проверки: значение недействительно

У меня есть проблема с a p:selectOneMenu, независимо от того, что я делаю, я не могу заставить JSF вызвать установщик для сущности JPA. Проверка JSF не проходит с этим сообщением:

форма: местоположение: Ошибка проверки: значение недействительно

У меня это работает на нескольких других классах того же типа (то есть, присоединиться к классам таблицы), но я не могу на всю жизнь заставить этот работать.

Если кто-то может дать несколько советов по устранению неполадок / отладке для такого рода проблемы, это будет очень ценно.

Используя отчеты журнала, я проверил следующее:

  1. Conveter возвращается правильно, не null ценности.
  2. У меня нет проверки бинов в моих объектах JPA.
  3. Сеттер setLocation(Location location) никогда не называется.

Это самый простой пример, который я могу сделать, и он просто не будет работать:

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

Преобразователь:

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

Консольный вывод:

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

3 ответа

Решение

Сбой проверки с сообщением "форма: местоположение: Ошибка проверки: значение недопустимо"

Эта ошибка сводится к тому, что выбранный элемент не соответствует ни одному из доступных значений элемента выбора, указанных любым вложенным <f:selectItem(s)> тег во время обработки формы отправить запрос.

В рамках защиты от несанкционированных / взломанных запросов JSF будет повторять все доступные значения элемента select и проверять, selectedItem.equals(availableItem) возвращается true по крайней мере для одного доступного значения элемента. Если не найдено ни одного значения элемента, вы получите именно эту ошибку проверки.

Этот процесс в основном, как показано ниже, в соответствии с bean.getAvailableItems() вымышленно представляет весь список доступных элементов выбора, как определено <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");
}

Таким образом, исходя из вышеуказанной логики, эта проблема может логически иметь по крайней мере следующие причины:

  1. Выбранный элемент отсутствует в списке доступных элементов.
  2. equals() метод класса, представляющего выбранный элемент, отсутствует или не работает.
  3. Если обычай Converter участвует, то он вернул не тот объект в getAsObject(), Возможно это даже null,

Чтобы решить это:

  1. Убедитесь, что точно такой же список был сохранен во время последующего запроса, особенно в случае нескольких каскадных меню. Делая боб @ViewScoped вместо @RequestScoped следует исправить это в большинстве случаев. Также убедитесь, что вы не выполняете бизнес-логику в методе получения <f:selectItem(s)>, но вместо этого в @PostConstruct или метод события (слушателя). Если вы полагаетесь на конкретные параметры запроса, вам нужно явно сохранить их в @ViewScoped bean-компонент или повторно передать его при последующих запросах, например: <f:param>, Смотрите также Как правильно выбрать сферу применения бобов?
  2. Убедитесь, что equals() Метод реализован правильно. Это уже сделано правильно на стандартных типах Java, таких как java.lang.String, java.lang.Number и т. д., но не обязательно для пользовательских объектов / bean / entites. Смотрите также Правильный способ реализации контракта равных. Если вы уже используете String, убедитесь, что кодировка символов запроса настроена правильно. Если он содержит специальные символы и JSF настроен на рендеринг вывода как UTF-8, но интерпретирует ввод как, например, ISO-8859-1, то произойдет сбой. Смотрите также, что ввод Unicode, полученный через PrimeFaces, приводит к повреждению компонентов ввода.
  3. Отладка / запись действий вашего кастома Converter и исправить это соответственно. Инструкции см. Также в значении параметра "Ошибка преобразования" для "нулевого конвертера". Если вы используете java.util.Date как доступные предметы с <f:convertDateTime> Убедитесь, что вы не забыли полностью занятую часть в паттерне. См. Также "Ошибка проверки: значение недопустимо" от f: datetimeConverter.

Смотрите также:


Если кто-то может дать несколько советов по устранению неполадок / отладке для такого рода проблемы, это будет очень ценно.

Просто задайте четкий и конкретный вопрос здесь. Не задавайте слишком широких вопросов;)

В моем случае я забыл реализовать правильные методы get/set. Это произошло потому, что я изменил много атрибутов в процессе разработки.

Без надлежащего метода get JSF не может восстановить выбранный вами предмет, и происходит то, что BalusC сказал в пункте 1 своего ответа:

1 Выбранный элемент отсутствует в списке доступных элементов. Это может произойти, если список доступных элементов обслуживается bean-объектом области действия запроса, который не был правильно переинициализирован при последующем запросе, или неправильно выполняет бизнес-работу в методе получения, что заставляет его каким-либо образом возвращать другой список.

Это может быть проблема с конвертером или проблема с DTO. Попробуйте решить эту проблему, добавив методы hashCode() и equals() в ваш объект DTO; В приведенном выше сценарии вы можете сгенерировать эти методы в классе объекта Location, который обозначается здесь как "DTO".

Пример:

@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;
}
  • Обратите внимание, что приведенный выше пример предназначен для идентификатора типа long.
Другие вопросы по тегам