Aprendendo Spring: #4 – Criando Converters

E aí Pessoal, tudo bem com vocês?

Estou muito feliz em anunciar que este é 101° post do blog. O blog foi criado em Dezembro de 2015, ainda é um bebê de 1 ano e 3 meses, mas já chegamos nesta marca expressiva. Agradeço a @debbyad pela ajuda, que publicou alguns destes posts e que continue a trazer ótimo conteúdos!

Mas vamos para o que interessa. Hoje vou falar sobre os Converters do Spring. Estas Classes são responsáveis por fazerem a conversão dos valores digitados no formulário para o atributo de um objeto.

Nos meus estudos/hands-on sobre Spring MVC, venho usando o framework Thymeleaf para resolver o V (Viewer) do MVC, e a cada dia estou gostando mais do poder deste framework.

bumblebee-transformersConverters providos pelo Spring

Mas voltando aos converters, o Spring disponibiliza vários deles, desde para converter um simples numérico em String ou data no formato dd/MM/yyyy para um Date.

No entanto, no primeiro submit do formulário, me deparei com a exception abaixo.  Isto me fez descobrir os converters e a necessidade de criar o meu próprio quando necessário.

Failed to convert property value of type java.lang.String to required type java.util.Calendar for property dtNascimento; nested exception is java.lang.IllegalStateException: Cannot convert value of type java.lang.String to required type java.util.Calendar for property dtNascimento: no matching editors or conversion strategy found

Esta exception é lançada quando o Spring não consegue converter uma String de um text field do formulário para o tipo do atributo no Model. Nesta caso, no formulário tinha um campo texto que representa uma data, e na entidade o atributo é do tipo Calendar, como o Spring não sabe converter String em um Calendar, eis o erro.

Mas como resolvermos este problema? Na verdade o Spring sabe converter String em Calendar, ele apenas precisa que configuremos o formato que a data virá do formulário.

Para isso, ele dispõem da anotação @DateTimeFormat. Esta anotação adicionada ao atributo Calendar na entidade, informa ao Spring que o atributo deverá ser convertido conforme o formato padrão que é M/d/yy.

@DateTimeFormat
private Calendar dataNascimento;

Mais apenas isto não é suficiente já que a data no formulário está no formato dd/MM/yyyy. Caso você tente submiter o formulário novamente, usando o formato padrão, você receberá outra exception, algo parecida com isto:

Failed to convert property value of type java.lang.String to required type java.util.Calendar for property dtNascimento; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @org.springframework.format.annotation.DateTimeFormat java.util.Calendar for value 2017-03-01; nested exception is java.lang.IllegalArgumentException: Unable to parse 2017-03-01

Neste caso é necessário informar o formato. Usei o atributo pattern para isto:

@DateTimeFormat(pattern = "dd/MM/yyyy")
private Calendar dataNascimento;

Agora basta submeter o formulário novamente que o Spring fará o restante.

Converter personalizado

Nos meus testes, também me deparei com a necessidade de criar meu próprio converter. No formulário, tem um campo de múltipla escolha do tipo checkbox:

formulariopapeis

E na entidade eu espero receber uma lista de PapelAssociado:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario")
private List<PapelAssociado> papeis;

O Spring não conhece está entidade PapelAssociado, com ele poderia fazer o bind do formulário para a entidade de forma transparente? Isto só foi possível criando meu próprio converter.

Para isto precisamos implementar a interface org.springframework.core.convert.converter.Converter. Abaixo segue minha implementação:

@Component
public class StringPapelAssociadoConverter implements Converter<String, PapelAssociado> {
public PapelAssociado convert(final String pPapel) {
return new PapelAssociado(pPapel);
}
}

Simples não? O que faço aqui é receber a String pPapel (linha 3) e retornar um objeto do tipo PapelAssociado (linha 4). Para o Spring boot reconhecer esta classe como um converter, bastou anota-la como @Component.

Pronto, o Spring conseguirá agora fazer o bind do formulário para a entidade, sem maiores problemas.

Um dica que deixo é, caso você precise fazer o contrário, ou seja, da entidade fazer o bind para o formulário, você terá que criar outro converter, um que receba PapelAssociado e retorne String.

Se gostaram desta dica, dá uma curtida aí!!

Fonte: Spring MVC – Binding Java Backing Objects with Custom Converters

Caso você seja novato em Spring boot como eu e tenha interesse em aprender um pouco mais, sugiro a leitura dos posts anteriores sobre Spring Boot:

Grande abraço.

4 Comentários

  1. […] Aprendendo Spring: #4: Criando Converters […]

    Curtir

  2. Grato pelo artigo. Me ajudou bastante.

    Curtir

    1. Que bom Wagner,
      Fico feliz em ter ajudado!
      Abraço!

      Curtir

  3. Eduardo Ferreira · · Responder

    Muito bom artigo. Clareou as minhas idéias!

    Curtido por 1 pessoa

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: