JSF 2.0 — selectOneMenu по умолчанию равен 0, когда пустой

#jsf-2 #drop-down-menu #java-ee-6 #converter #selectonemenu

#jsf-2 #выпадающее меню #java-ee-6 #преобразователи #selectonemenu

Вопрос:

Для моего проекта я хочу реализовать поле со списком с h:selectOneMenu. Я прочитал много сообщений о том, как правильно обрабатывать selectOneMenu и как реализовать пользовательский конвертер. Поле со списком должно сохранять идентификатор (длинный) из другой таблицы БД (с именем fk_ID), для которого установлено ограничение. Пока все, кажется, функционирует так, как планировалось. Теперь к моей проблеме:

Столбец fk_ID является необязательным, поэтому первым параметром в выпадающем списке является f: SelectItem без значения, помеченного как «выбрать …». Когда я сохраняю форму и изменяю значение, все в порядке, за исключением того, что я возвращаю ему значение «выбрать …». Ошибка, которую я получаю, является нарушением целостности ограничения.

Я тоже обнаружил проблему: конвертер возвращает null, как и предполагалось, но компонент получает длинный 0.

XHTML:

 <h:selectOneMenu value="#{userBean.selectedModel.fk_id}"
    id="combobox">
    <f:selectItem itemLabel="choose ..." />
    <f:selectItems
        value="#{userBean.items}"
        var="item"
        itemLabel="#{item.value}"
        itemValue="#{item.id}"
    />
    <f:converter converterId="userConverter" />
</h:selectOneMenu>
  

Пользовательский конвертер:

 @FacesConverter(value = "userConverter")
public class UserConverter implements Converter {
    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
        if (arg2 != null amp;amp; !arg2.equals("null"))
            return Long.valueOf(arg2);

        return null;
    }
    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
        return String.valueOf(arg2);
    }
}
  

Компонент (очень короткая версия):

 @Named(value = "userBean")
public class UserController implements Serializable {

    @Getter
    @Setter
    private UserModel selectedModel;

    @Getter
    @Setter
    private List<UserModel> items;

    public void saveModel() {
        selectedModel = userService.saveModel(selectedModel);
    }
}
  

Проблема в том, что fk_id имеет длину 0, но должен быть нулевым. Я могу решить проблему, написав

 if (selectedModel.getFk_id() == 0)
    selectedModel.setFk_id(null);
  

но это не то решение, которое меня устраивает.

Мой вопрос: почему значение null, которое возвращает конвертер, является длинным 0 внутри метода saveModel()?

Ответ №1:

Этот конвертер не нужен и не имеет смысла (я бы ожидал, что UserConverter для преобразования между User и String , а не между Long и String ). Удалите его.

Теперь вам нужно указать JSF интерпретировать отправленные значения пустой строки как null . Добавьте следующее в свой web.xml :

 <context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>
  

Это должно решить проблему в большинстве контейнеров. Но если вы используете Tomcat или его форк / клон (JBoss AS, WebSphere AS и т.д.) И / или контейнер использует реализацию Apache EL parser, то вам также необходимо добавить следующий аргумент к аргументам запуска виртуальной машины:

 -Dorg.apache.el.parser.COERCE_TO_ZERO=false
  

Это не позволит анализатору Apache EL привести отправленное значение к значению по умолчанию для примитива, даже если вы используете тип оболочки примитива в качестве свойства.

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


Не связанный с конкретной проблемой, у вас там нет выпадающего списка. Это всего лишь простой выпадающий список. Поле со списком — это редактируемый выпадающий список. Правильно сформулируйте свои условия 😉

Комментарии:

1. Действительно, выпадающий список 😉 . Проблема была решена именно так, как вы сказали. Поскольку я использую сервер Tomcat, мне даже нужно было включить аргумент при запуске. Большое спасибо!