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