{"id":585,"date":"2013-11-16T01:34:25","date_gmt":"2013-11-16T04:34:25","guid":{"rendered":"https:\/\/www.semeru.com.br\/blog\/?p=585"},"modified":"2022-12-20T21:28:13","modified_gmt":"2022-12-21T00:28:13","slug":"fazendo-parser-de-objetos-com-o-dozer","status":"publish","type":"post","link":"https:\/\/www.semeru.com.br\/blog\/fazendo-parser-de-objetos-com-o-dozer\/","title":{"rendered":"Fazendo parser de objetos com o Dozer."},"content":{"rendered":"<p><a href=\"https:\/\/www.semeru.com.br\/blog\/fazendo-parser-de-objetos-com-o-dozer\/dozer\/\" rel=\"attachment wp-att-590\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-590\" src=\"https:\/\/www.semeru.com.br\/blog\/wp-content\/uploads\/2013\/10\/dozer.png\" alt=\"dozer\" width=\"116\" height=\"84\"><\/a><\/p>\n<p>O framework Dozer \u00e9 um parser de um POJO para outro POJO, o que significa dizer que ele copia automaticamente, de forma recursiva, dados de um objeto para outro.<\/p>\n<p>O Dozer supporta mapear propriedades simples, tipos complexos, mapeamento bidirecional, mapeamento implicito-explicito, suporta tamb\u00e9m o mapeamento de cole\u00e7\u00f5es de atributos.<\/p>\n<p>O Dozer suporta n\u00e3o somente o mapeamento entre nomes de atributos mas tamb\u00e9m faz convers\u00f5es entre tipos. Para cen\u00e1rios mais complexos o Dozer permite realizar convers\u00f5es customizadas atrav\u00e9s de arquivos XML.<\/p>\n<p>O mapper \u00e9 indicado sempre que voc\u00ea precisa copiar as informa\u00e7\u00f5es de um POJO para outro. A maioria dos atributos podem ser mapeados automaticamente pelo Dozer atrav\u00e9s de reflex\u00e3o, mas, como j\u00e1 foi comentado, qualquer mapeamento customizado pode ser feito atrav\u00e9s de arquivos XML. O mapeamento \u00e9 bi-direcional somente o relacionamento entre as classes precisa ser definido. Se qualquer nome de alguma propriedade em ambos os objetos forem iguais voc\u00ea n\u00e3o precisar\u00e1 fazer nenhum mapeamento adicional para mapear essas propriedades.<\/p>\n<p>A figura abaixo representa um exemplo em que \u00e9 recomend\u00e1vel utilizar o Dozer em uma arquitetura. Note que ele \u00e9 tipicamente usado nas entradas e sa\u00eddas da aplica\u00e7\u00e3o. O Dozer garante que seus objetos de dom\u00ednio interno n\u00e3o sejam vistos pelas camadas de apresenta\u00e7\u00e3o ou por consumidores externos. Ele tamb\u00e9m pode ajudar a mapear seus objetos de dom\u00ednio para chamadas externas de API&#8217;s e vice versa.<\/p>\n<p>Em outras palavras, ao inv\u00e9s de voc\u00ea expor suas entidades JPA, por exemplo, o que indiretamente tornaria p\u00fablicas informa\u00e7\u00f5es de sua base de dados, voc\u00ea cria um POJO similar \u00e0s suas entidades JPA, s\u00f3 que sem as anota\u00e7\u00f5es, e exp\u00f5e esse POJO para os clientes de sua aplica\u00e7\u00e3o. Entre o POJO exposto e o a entidade JPA voc\u00ea poderia utilizar um framework como o Dozer e parsear dados de suas entidades JPA para o POJO exposto e vice e versa, encapsulando informa\u00e7\u00f5es importantes de sua aplica\u00e7\u00e3o.<br \/>\n<a href=\"https:\/\/www.semeru.com.br\/blog\/fazendo-parser-de-objetos-com-o-dozer\/architecture\/\" rel=\"attachment wp-att-594\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-594\" src=\"https:\/\/www.semeru.com.br\/blog\/wp-content\/uploads\/2013\/10\/architecture.gif\" alt=\"architecture\" width=\"733\" height=\"580\"><\/a><br \/>\n<strong>O Parser &#8211; &#8220;DozerParser&#8221;<\/strong><\/p>\n<p>No nosso exemplo temos um Parser gen\u00e9rico fazendo convers\u00e3o de dois POJOS simples. Inicialmente criamos uma inst\u00e2ncia do Mapper, posteriormente temos dois m\u00e9todos respons\u00e1veis por parsear um objeto e uma lista de objetos respectivamente.<br \/>\nNote que eles recebem objetos gen\u00e9ricos, o que significa que voc\u00ea pode usar da forma como est\u00e1 em um projeto seu que j\u00e1 vai funcionar. Logo abaixo temos um terceiro m\u00e9todo que \u00e9 quem efetivamente faz a invoca\u00e7\u00e3o ao Dozer e este por sua vez realiza o parse.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage br.com.semeru.dozer.converter;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.dozer.DozerBeanMapper;\nimport org.dozer.Mapper;\n\npublic class DozerParser {\n\n    private static final Mapper dozerMapper = new DozerBeanMapper();\n\n    public static &lt;o, d=&quot;&quot;&gt; D parseObjectInputToObjectOutput(O  originalObject, Class&lt;d&gt; destinationObject) {\n        return parser(destinationObject, originalObject);\n    }\n\n    public static &lt;o, d=&quot;&quot;&gt; List&lt;d&gt; parserListObjectInputToObjectOutput(List&lt;o&gt; originalObjects, Class&lt;d&gt; destinationObject) {\n        List&lt;d&gt; destinationObjects = new ArrayList&lt;d&gt;();\n        for (Object originalObject : originalObjects) {\n            destinationObjects.add(parser(destinationObject, originalObject));\n        }\n        return destinationObjects;\n    }\n\n    private static &lt;d&gt; D parser(Class&lt;d&gt; destinationObject, Object originalObject) {\n        return dozerMapper.map(originalObject, destinationObject);\n    }\n}\n<\/pre>\n<p><strong>O objeto de origem &#8211; &#8220;InputObject&#8221;<\/strong><\/p>\n<p>Aqui temos um objeto de entrada, que \u00e9 um POJO simples.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage br.com.semeru.dozer.objects;\n\nimport java.io.Serializable;\n\npublic class InputObject implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private String name;\n    private Integer age;\n\n    \/\/ Getters, setters, equals e hashCode omitidos\n}\n<\/pre>\n<p><strong>O objeto de destino &#8211; &#8220;OutputObject&#8221;<\/strong><\/p>\n<p>Aqui temos o segundo POJO para onde os dados do objeto de entrada ser\u00e3o copiados. Note que a extrutura dos POJO&#8217;s devem ser iguais. Caso contr\u00e1rio voc\u00ea deveria personalizar o parser de acordo com a sua necessidade usando arquivos XML.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage br.com.semeru.dozer.objects;\n\nimport java.io.Serializable;\n\npublic class OutputObject implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private String name;\n    private Integer age;\n\n    \/\/ Getters, setters, equals e hashCode omitidos\n}\n<\/pre>\n<p><strong>A classe de Mock &#8211; &#8220;MockInputObject&#8221;<\/strong><\/p>\n<p>Aqui temos uma classe de Mock que cria uma inst\u00e2ncia do POJO de entrada e popula-o com informa\u00e7\u00f5es simulando um acesso \u00e0 uma base de dados por exemplo.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage br.com.semeru.dozer.mocks;\n\nimport br.com.semeru.dozer.objects.InputObject;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MockInputObject {\n\n    private InputObject inputObject = new InputObject();\n\n    public InputObject mockInput() {\n        inputObject.setName(&quot;Name Test&quot;);\n        inputObject.setAge(21);\n        return inputObject;\n    }\n\n    public List&lt;inputobject&gt; mockInputList() {\n        List&lt;inputobject&gt; inputObjects = new ArrayList&lt;inputobject&gt;();\n        for (int i = 0; i &amp;lt; 3; i++) {\n            inputObjects.add(mockInput(i));\n        }\n        return inputObjects;\n    }\n\n    private InputObject mockInput(Integer number) {\n        inputObject.setName(&quot;Name Test &quot; + number);\n        inputObject.setAge(20 + number);\n        return inputObject;\n    }\n}\n<\/pre>\n<p><strong>Os testes &#8211; &#8220;DozerParserTest&#8221;<\/strong><\/p>\n<p>Por fim temos os testes unit\u00e1rios que s\u00e3o respons\u00e1veis por verificar o comportamento do parser pasando as instancias mockadas pela classe acima pelo nosso parser e realizando asser\u00e7\u00f5es nos resultados.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage br.com.semeru.dozer.converter;\n\nimport br.com.semeru.dozer.mocks.MockInputObject;\nimport java.util.List;\n\nimport junit.framework.Assert;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport br.com.semeru.dozer.objects.OutputObject;\n\npublic class DozerParserTest {\n\n    MockInputObject inputObject;\n\n    @Before\n    public void setUp() {\n        inputObject = new MockInputObject();\n    }\n\n    @Test\n    public void parseObjectInputToreObjectOutputTest() {\n        OutputObject output = DozerParser.parseObjectInputToObjectOutput(inputObject.mockInput(), OutputObject.class);\n        Assert.assertEquals(&quot;Name Test&quot;, output.getName());\n        Assert.assertTrue(output.getAge() == 21);\n    }\n\n    @Test\n    public void parserListObjectInputToObjectOutputTest() {\n        List&lt;outputobject&gt; output = DozerParser.parserListObjectInputToObjectOutput(inputObject.mockInputList(), OutputObject.class);\n        Assert.assertEquals(&quot;Name Test 2&quot;, output.get(0).getName());\n        Assert.assertTrue(output.get(0).getAge() == 22);\n    }\n}\n<\/pre>\n<p>Enfim o Dozer \u00e9 uma \u00f3tima op\u00e7\u00e3o de parser de um POJO para outro sendo tamb\u00e9m bastante simples de se usar. Como alternativa ao Dozer temos o Orika que faz as mesmas tarefas que o Dozer. No meu Github voc\u00ea pode ver um exemplo b\u00e1sico de utiliza\u00e7\u00e3o do <a title=\"Dozer\" href=\"https:\/\/github.com\/leandrocgsi\/simple-dozer-example\">Dozer<\/a> e do <a title=\"Orika\" href=\"https:\/\/github.com\/leandrocgsi\/simple-orika-example\">Orika<\/a>. Bom proveito e fa\u00e7a bons estudos.<\/p>\n<h2>Treinamentos relacionados com este post<\/h2>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_rest_spring_java\" target=\"_blank\" rel=\"noopener\"><\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" title=\"REST API's RESTFul do 0 \u00e0  AWS com Spring Boot 3, Java e Docker\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/07-rest-spring-java.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_microservices_java\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Microservices do 0 com Spring Cloud, Spring Boot e Docker\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/14-microservices-java.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_rest_spring_kotlin\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"REST API's RESTFul do 0 \u00e0 AWS com Spring Boot 3, Kotlin e Docker\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/18-rest-spring-kotlin.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_ms_kotlin\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Microsservi\u00e7os do 0 com Spring Cloud, Kotlin e Docker\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/22-ms-kotlin.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_docker\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Docker do 0 \u00e0 Maestria: Cont\u00eaineres Desmistificados mais 3 B\u00d4NUS\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/09-docker.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_docker_para_aws\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Docker para Amazon AWS Implante Apps Java e .NET com Travis CI\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/10-docker-to-aws.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_kotlin\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Kotlin para DEVs Java: Aprenda a Linguagem Padr\u00e3o do Android\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/20-kotlin.png\"><br \/>\n<\/a><\/p>\n<p><\/outputobject><\/inputobject><\/inputobject><\/inputobject><\/d><\/d><\/d><\/d><\/d><\/o><\/d><\/o,><\/d><\/o,><\/p>\n<div align=\"right\"><div class=\"sharexyWidgetNoindexUniqueClassName\"><div id=\"shr_90462006\"><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>O framework Dozer \u00e9 um parser de um POJO para outro POJO, o que significa dizer que ele copia automaticamente, de forma recursiva, dados de um objeto para outro. O Dozer supporta mapear propriedades simples, tipos complexos, mapeamento bidirecional, mapeamento implicito-explicito, suporta tamb\u00e9m o mapeamento de cole\u00e7\u00f5es de atributos. O Dozer suporta n\u00e3o somente o [&#8230;]<\/p>\n<div align=\"right\">\n<div class=\"sharexyWidgetNoindexUniqueClassName\">\n<div id=\"shr_90462006\"><\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[109,110,111],"tags":[198,199,200],"_links":{"self":[{"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/posts\/585"}],"collection":[{"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/comments?post=585"}],"version-history":[{"count":21,"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/posts\/585\/revisions"}],"predecessor-version":[{"id":1441,"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/posts\/585\/revisions\/1441"}],"wp:attachment":[{"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/media?parent=585"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/categories?post=585"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.semeru.com.br\/blog\/wp-json\/wp\/v2\/tags?post=585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}