Aprimorando Data Transfer Object (DTO) em Kotlin com MapStruct
- #Kotlin
- #Java
A otimização na transferência e no gerenciamento de dados é crucial no desenvolvimento de software, e o Data Transfer Object (DTO) é um padrão de projeto empregado para transferir dados entre diferentes camadas de uma aplicação. Neste artigo, será apresentado a configuração técnica de DTO em Kotlin, utilizando ferramentas como o kotlin-maven-plugin e o mapstruct-processor, e como efetuar essa configuração de forma eficiente.
Exemplo Prático
Imagine um cenário onde certos campos são calculados pelo sistema. Em uma operação de POST, não é desejável que o cliente envie esses campos calculados.
No entanto, faz sentido retornar essas informações ao cliente, para que ele compreenda o que foi calculado e armazenado na tabela.
Nesse contexto, criamos estruturas distintas: Request (dados de entrada), Response (dados retornados ao cliente) e Model (entidades do banco de dados).
Vantagens do DTO
- Redução de Chamadas: Minimiza a sobrecarga de comunicação em aplicações distribuídas.
- Encapsulamento: Facilita a transferência segura de dados, apenas informações essenciais serão expostas.
- Simplificação de Serialização: Torna mais fácil a conversão de objetos para formatos como JSON ou XML, fundamentais para APIs RESTful
Pasta Autogerada target e MapperImpl
Quando o build do Maven é executado, códigos são gerados automaticamente na pasta target. Dentro desta pasta, encontram-se implementações como MapperImpl, geradas pelo MapStruct. Essas implementações são importantes, pois servem como uma ponte entre as classes de entidades e DTOs, facilitando a conversão e manipulação de dados.
Desafios
Ao utilizar bibliotecas Java para DTO em Kotlin, podem surgir desafios como a exceção BeanCreationException, problemas com o reconhecimento da classe MapperImpl pelos arquivos autogerados do Maven ou até a falta de geração desta classe.
Resolução
Configurar corretamente o kotlin-maven-plugin é crucial para superar esses desafios. Esse plugin assegura a interoperabilidade entre Kotlin e Java, e o componente kaptKotlin permite a adição do annotationProcessorPaths. Isso instrui o compilador a usar o MapStruct para gerar código de implementação com base nas anotações definidas em interfaces de mapeamento.
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal> <!-- You can skip the <goals> element
if you enable extensions for the plugin -->
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal> <!-- You can skip the <goals> element
if you enable extensions for the plugin -->
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>kaptKotlin</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.3.Final</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
</executions>
</plugin>
Implementação do MapStruct em Kotlin
Com a configuração correta, é possível adicionar implementações de mapeamento comumente utilizado em Java, como a interface para definir os métodos a serem utilizados e a classe *MapperImpl será gerada corretamente!
@Mapper
interface ClientMapper {
fun toClientResponse(client: Client): ClientResponse
fun toClient(clientRequest: ClientRequest): Client
}
E a configuração comumente utilizada do Mapper:
@Configuration
open class MapStructConfig {
@Bean
open fun clientMapper(): ClientMapper {
return Mappers.getMapper(ClientMapper::class.java)
}
}
Fontes: Kotlin Documentation