Article image

GL

Gleice Lisbino17/01/2024 15:45
Compartilhe

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

  1. Redução de Chamadas: Minimiza a sobrecarga de comunicação em aplicações distribuídas.
  2. Encapsulamento: Facilita a transferência segura de dados, apenas informações essenciais serão expostas.
  3. 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

Compartilhe
Comentários (0)