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

Я использую managedBean userHome в requestScope, в котором объект "пользователь" будет сохраняться. У пользователя есть столбец лидера, который отображается в отношении ManyToOne. Мой код выглядит следующим образом:

@ManagedBean
@RequestScoped
public class UserHome {
    private User user = new User();
        // Getters and Setters

    private List<SelectItem> selectItems = new ArrayList<SelectItem>();

    public UserHome() {
        for(User user: availableLeaders) {
            selectItems.add(new SelectItem(user.getName(), user));
        }
    }

    public void persis();
}

User.java

public class User {
    @Id
    @Column
    private Integer id;

    @Column
    privat String name;

    @ManyToOne
    private User leader;
}

Я пытаюсь получить значение этого лидера через h:selectOneMenu, как этот

<h:selectOneMenu value="#{userHome.user.leader}" converter="userConverter">
    <f:selectItems value="#{userHome.selectItems}"/>
</h:selectOneMenu>

Мой конвертер выглядит следующим образом

@FacesConverter(forClass = User.class, value="userConverter")
public class UserConverter implements Converter {

    private  Map<String, User> userValues = new HashMap<String, User>();

    public UserConverter() {
        init();
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
            String value) {
        return userValues.get(value);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        System.out.println("RAJASEKARAN "+value);
        return ((User)value).getName();
    }

    public void init() {
        UserHome userHome = new UserHome();
        for(User user:userHome.availableLeaders()) {
            userValues.put(user.getName(), user);
        }
    }
}

При попытке сохранить пользователя я получаю сообщение об ошибке UserEdit: j_idt18: Ошибка проверки: значение недействительно

Ответ 1

Добавление в ответ BalusC: после обратной передачи вам нужно убедиться, что экземпляры пользователя либо точно такие же, как и для рендеринга выбранных элементов, или что вы реализуете равные для своего класса User.

Код не показывает, откуда приходит availableLeaders, но если он извлекается из БД по требованию, тогда конвертер не будет преобразовываться в тот же экземпляр объекта, который в списке, разрешенном JSF через #{userHome.selectItems}.

После преобразования JSF проверит, может ли преобразованный экземпляр быть найден в этом списке с помощью метода equals().

Ответ 2

Вы построили SelectItem неверный путь. Согласно документации class, первый аргумент должен представлять значение элемента (которое должно быть преобразовано и представлено), а второй аргумент должен представлять (который должен отображаться в списке). Но вы указали их наоборот.

Исправьте его соответствующим образом:

selectItems.add(new SelectItem(user, user.getName()));

Если это еще не устраняет проблему, значит, метод equals() класса User не реализован (правильно). JSF будет использовать его для проверки выбранного User по отношению к любому из значений элемента списка после преобразования.


Несвязанный к конкретной проблеме, может быть полезно знать, что <f:selectItems> в JSF2 предлагает вам возможность создать список без необходимости создания списка SelectItem вручную. Вот пример, который достигает точно такой же:

<f:selectItems value="#{userHome.availableLeaders}" var="user" 
    itemValue="#{user}" itemLabel="#{user.name}" />

Это позволяет избавиться от дополнительного свойства selectItems и цикла в конструкторе bean.