Com a API Date-Time do Java 8 novos objetos de representação e tratamento de data e tempo foram introduzidos no cotidiano de desenvolvedores que recorriam à implementações diversas, como o Joda Time.
Como caraterística desta API pode ser destacados a facilidade na utilização o que não era presente nas versões anteriores com os objetos java.util.Date e java.sql.Date.
Entretanto a versão JSF 2.2 ainda não proporciona a conversão nativa desses objetos. O que já incorporado na próxima versão, 2.3, programada para ser lançada em 2017 junto a Java EE 8.
Assim, para utilizar os objetos LocalDate e LocalDateTime é necessário criar conversores JSF e atribuí-los ao conversor da tag <h:outputText>. Abaixo o exemplo de utilização.
Os converters devem implementar a interface javax.faces.convert.Converter e ser anotados com javax.faces.convert.FacesConverter, onde é definido o nome (id).
@FacesConverter("localDateTimeFacesConverter")
public class LocalDateTimeFacesConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String stringValue) {
if (null == stringValue || stringValue.isEmpty()) {
return null;
}
LocalDateTime localDateTime = null;
try {
localDateTime = LocalDateTime.parse(
stringValue.trim(),
DateTimeFormatter.ofPattern(“dd/MM/yyyy hh:mm:ss”).withZone(ZoneId.systemDefault()));
} catch (DateTimeParseException e) {
throw new ConverterException(“O formato da data e hora deve ser 13/11/2015 12:00:00.”);
}
return localDateTime;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object localDateTimeValue) {
if (null == localDateTimeValue) {
return “”;
}
return ((LocalDateTime) localDateTimeValue)
.format(DateTimeFormatter.ofPattern(“dd/MM/yyyy hh:mm:ss”)
.withZone(ZoneId.systemDefault()));
}
}
@FacesConverter("localDateFacesConverter")
public class LocalDateFacesConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String stringValue) {
if (null == stringValue || stringValue.isEmpty()) {
return null;
}
LocalDate localDate;
try {
localDate = LocalDate.parse(
stringValue,
DateTimeFormatter.ofPattern(“dd/MM/yyyy”));
} catch (DateTimeParseException e) {
throw new ConverterException(“O ano deve conter 4 dígitos. Exemplo: 13/11/2015.”);
}
return localDate;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object localDateValue) {
if (null == localDateValue) {
return “”;
}
return ((LocalDate) localDateValue).format(DateTimeFormatter.ofPattern(“dd/MM/yyyy”));
}
}
Os Converters apenas fazem a conversão do objeto para String e vice-versa, não há maiores problemas na implementação. Caso o parse para o padrão definido gere uma exceção esta é lançada como ConverterException e exibida ao usuário. No entanto nos testes e em implementações dessa lógica esta mensagem não chega ao na view e deve ser definido o atributo converterMessage da tag <h:inputText>.
<code><label for=”inputAdmissao”>Data de admissão <span class=”required”>*</span></label>
<h:inputText
class=”form-control input-sm m-bot15″
id=”inputAdmissao”
pt:placeholder=”Admissao ”
value=”#{cadastroFuncionarioBean.funcionario.dataDeAdmissao}”
required=”true”
requiredMessage=”É necessário informar a data de admissão.”
converterMessage=”A data deve estar no formato dd/MM/aaaa”>
<f:converter
converterId=”localDateFacesConverter”
for=”inputAdmissao”/>
<f:ajax
event=”blur”
render=”m_inputAdmissao” />
</h:inputText> </code>
A novidade que a versão do JSF 2.3 traz é a adição de type attributes para as classes java.time.LocalDate e java.time.LocalDateTime, respectivamente localDate e localTime. :-p
<code>
<
h:inputText
value
=
"#{myBean.startTime}"
>
<
f:convertDateTime
type
=
"localDateTime"
/>
</
h:inputText
>
<
h:outputText
value
=
"#{myBean.endDate}"
>
<
f:convertDateTime
type
=
"localDate"
pattern
=
"dd.MM.uu"
/>
</
h:outputText
>
</code>
É isso. E para saber mais das novidades da nova versão do JSF segue esse link What’s new in JSF 2.3?.