Помилка перевірки: значення недійсне


80

У мене проблема з ap: selectOneMenu, незалежно від того, що я роблю, я не можу змусити JSF викликати сеттера в сутності JPA. Не вдається перевірити JSF із цим повідомленням:

form: location: Помилка перевірки: Значення недійсне

Я працюю над кількома іншими класами того ж типу (тобто, приєднуюсь до класів таблиць), але не можу протягом усього життя змусити цей працювати.

Якщо хтось може підказати деякі поради щодо усунення несправностей / налагодження для такого роду проблем, це буде вдячне.

За допомогою операторів журналу я перевірив наступне:

  1. ConveterПовертаюся правильно, що не є nullзначення.
  2. У моїх організаціях JPA немає перевірки Bean.
  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] 

Відповіді:


143

Помилка перевірки із повідомленням "form: location: Помилка перевірки: значення недійсне"

Ця помилка зводиться до того, що вибраний елемент не відповідає жодному з доступних значень вибраного елемента, вказаних будь-яким вкладеним <f:selectItem(s)> тегом під час обробки запиту на подання форми.

Як частина захисту від фальсифікованих / зламаних запитів, JSF повторить всі доступні вибрані значення товару та перевірить, чи 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компоненті або повторно передавати їх у наступних запитах, наприклад <f:param>. Дивіться також Як правильно вибрати сферу використання бобів?
  2. Переконайтеся, що equals()метод впроваджено правильно. Це вже зроблено прямо на стандартних типів Java , таких як java.lang.String, java.lang.Numberі т.д., але не обов'язково на призначені для користувача об'єкти / боби / entites. Див. Також Правильний спосіб реалізації рівного договору . Якщо ви вже використовуєте String, переконайтесь, що кодування символів запиту налаштовано правильно. Якщо він містить спеціальні символи, і JSF налаштований на візуалізацію виводу як UTF-8, але інтерпретувати вхід як, наприклад, ISO-8859-1, тоді він не вдасться. Див. Також ao Вхід Unicode, отриманий через вхідні компоненти PrimeFaces, пошкоджено .
  3. Налагоджуйте / реєструйте дії за вашим замовленням Converterі виправляйте це відповідно. Вказівки див. Також у значенні налаштування помилки перетворення для 'null Converter'. Якщо ви використовуєте java.util.Dateяк доступні елементи <f:convertDateTime>, переконайтеся, що не забули повну частину шаблону. Див. Також "Помилка перевірки: значення не є дійсним" від f: datetimeConverter .

Дивитися також:


Якщо хтось може підказати деякі поради щодо усунення несправностей / налагодження для такого роду проблем, це буде вдячне.

Просто поставте тут чітке і конкретне запитання. Не задавайте занадто широких питань;)


@BalusC: Де саме в коді моджарри equalsвідбувається ця перевірка. Моя ситуація дещо складна. Я створюю власний власний компонент, який дозволяє користувачеві мати складний макет радіо. Це прекрасно працює, якщо у мене є лише одна група радіо (f: selectItems прямо під моїм користувацьким компонентом). Однак, оскільки макет стає більш складним (кілька радіогруп, кожна має свої власні f: selectItems, але всі мають однаковий вибір), я повинен мати f: selectItems всередині ui: repeat, тоді ui: repeat знаходиться під моїм користувацьким компонентом. Потім я зіткнувся з цим питанням. Я хочу побачити код моджарри, який це обробляє
Танг Фам

Також мій f: selectItems має тип String, тому я впевнений, що це не проблема перетворення, я думаю, що це причина, тому що списку f: selectItems немає на етапі перевірки.
Thang Pham

Чи можете ви детальніше розповісти про те, як використовувати f: param для передачі стану керованому компоненту, щоб він міг відтворити "початковий стан" ??? Дякую.
Агусті Санчес,

1
Маючи подібну помилку. Я використовую SelectItemsConverter, і цей компонент знаходиться всередині відключеного набору полів - отже, він також вимкнений. Це відома поведінка?
Gilberto

Якщо ви використовуєте перерахування для елементів, що відображаються, а ваш резервний компонент має тип рядка для встановлення значення в компоненті, а не використовує будь-які перетворювачі, ви отримаєте однакову помилку. Ось так я опинився тут.
Філіп Путенвіла,

2

У моєму випадку я забув застосувати правильні методи get / set. Це сталося тому, що я змінив багато атрибутів у процесі розробки.

Без належного методу отримання JSF не може відновити вибраний предмет, і відбувається те, що сказав BalusC у пункті 1 своєї відповіді:

1. Вибраний елемент відсутній у списку доступних елементів. Це може трапитись, якщо список доступних елементів подається за обсягом запиту, який не належним чином повторно ініціалізується при наступному запиті, або неправильно виконує ділову роботу в методі отримання, що змушує його якимось чином повертати інший список.


1

Це може бути проблема конвертера або проблема DTO. Спробуйте вирішити це, додавши в об'єкт DTO методи hashCode () та equals (); У наведеному вище сценарії ви можете генерувати ці методи в межах класу об'єкта 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;
}
  • Зверніть увагу, що наведений вище приклад стосується "ідентифікатора" типу "довгий".

Як зазначено в №2 у прийнятій та високо оціненій відповіді
Кукельтьє,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.