#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, мне даже нужно было включить аргумент при запуске. Большое спасибо!