Aprendendo Spring: #4 – Criando Converters

Tempo de leitura: menos de 1 minuto

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.

https://gist.github.com/edermfl/077bf18767db3ffff794f170578006f8

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:

https://gist.github.com/edermfl/24c93d6ed3c623e7491344b937326bf1

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:

https://gist.github.com/edermfl/7b67d9817e232a7703d3a6ac454acd66

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:

https://gist.github.com/edermfl/514b5b891c29d0904f672c2aaaa91e57

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. Que bom Wagner,
      Fico feliz em ter ajudado!
      Abraço!

      Responder

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *