Я хочу сделать вкладку "Календарь" в форме JSF необязательной. Когда пользователь не сообщает о рождении, поле "Календарь" должно оставаться равным нулю.
Мой код:
@Model
public class Registration {
private User user = new User();
public void register() {
// stuff
}
//getUser
}
Класс модели:
public class User {
//other fields
private Calendar birth;
// gets and sets
}
Страница:
<h:outputLabel for="birth" value="Birth Date" />
<h:inputText id="birth" value="#{registration.user.birth.time}" >
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>
Проблема до сих пор заключается в <f:convertDateTime>
, которая зависит от getTime()
для Calendar
чтобы сделать преобразование. Он выдает NPE (исключение Null Pointer) при исполнении. Я знаю, что если я инициализирую рождение, проблема решена, но я действительно хочу, чтобы поле было нулевым, когда пользователь не заполнил поле.
Любые мысли о способе достижения этого?
Хорошо, я отправлю это для потомков. Я думаю, что это сработает:
@FacesConverter("CustomCalendarConverter")
public class CalConverter implements Converter{
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if(value != null && !value.toString().isEmpty()){
try {
String pattern = (String) component.getAttributes().get("pattern");
Calendar calendar = Calendar.getInstance();
calendar.setTime(new SimpleDateFormat(pattern).parse(value));
return calendar;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return null;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if(value != null && !value.toString().isEmpty()){
Calendar cal = (Calendar) value;
String pattern = (String) component.getAttributes().get("pattern");
return new SimpleDateFormat(pattern).format(cal.getTime());
}
else return null;
}
}
И точка зрения должна быть:
<h:outputLabel for="birth" value="Birth Date" />
<h:inputText id="birth" value="#{registration.user.birth}">
<f:converter converterId="CustomCalendarConverter" />
<f:attribute name="pattern" value="dd/MM/yyyy" />
</h:inputText>
Вы также можете создать составной компонент, например, <custom:inputCalendar>
.
Проблема не связана с преобразованием, а с выражением:
#{registration.user.birth.time}
Infact это код DateTimeConverter
:
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
...
Object returnValue = null;
DateFormat parser = null;
try {
// If the specified value is null or zero-length, return null
if (value == null) {
return (null);
}
value = value.trim();
if (value.length() < 1) {
return (null);
}
...
returnValue = parser.parse(value);
} catch (ParseException e) {
...
}
return returnValue;
}
Как вы можете заметить, нулевые и пустые значения управляются правильно. Но когда применяются значения, birth.time
выражение birth.time
, но ссылка на birth
равна нулю, поэтому, когда birth.time
сеттер по времени называется, вы получаете NPE.
Возможным решением является привязка поля birth
к прямому виду java.util.Date
, который является типом, управляемым DateTimeConverter
, как DateTimeConverter
ниже:
public class User {
//other fields
private Date birth;
// gets and sets
}