Como configurar o Spring Boot com MapStruct e Lombok

Nesse tutorial vamos ensinar a configurar um projeto Spring Boot com o Lombok e Mapstruct que são duas bibliotecas poderosas para diminuir o código boilerplate.

O que é código boilerplate?

Código boilerplate são trechos de código que são utilizados em vários lugares da aplicação e que tem pouca ou nenhuma alteração, podemos citar no exemplo de uma aplicação Java os getters e setters que são usados para encapsulamento do nosso código orientada a objeto.

Então em um projeto grande apesar de a maioria das IDEs gerarem esse tipo de código na hora da leitura pode ficar bem confuso, porque fazem nossas classes crescerem muito.

Uma outra situação que acontece muito nesses projetos são o uso de classes DTO (Data Transfer Object) o que seriam elas? São classes que utilizamos simplesmente para transferir informação entre outras classes, é muito utilizado quando você pretende isolar internamente suas classes de negócio como as entidades.

E qual o problema nessa abordagem? Na verdade nenhum é até uma boa prática entretanto traz muito trabalho para quem está programando, e o desenvolvedor deveria se preocupar com a regra de negócio, e não escrevendo códigos para atender a convenção da linguagem.

Na passagem de informação entre uma classe e outra acabamos com uma situação semelhante ao exemplo abaixo, onde temos que passar informação método a método.

entity.setValue(dto.getValue());
entity.setFoo(dto.getFoo());
entity.setBar(dto.getBar());
Java

Fazer isso em uma classe que tem dezenas de atributos é muito trabalho, e fazer isso em dezenas de classes que tem dezenas de atributos é ainda pior!

Mas não se preocupe com a configuração que estamos propondo reduzirá todo esse esforço.

Solucionando o problema dos Getters e Setters

Para a solucionar o problema dos getters e setters a comunidade tem usado o Lombok uma biblioteca que gera através de annotations esse códigos que são da convenção. Além dos getters e setters o essa biblioteca ainda possibilita gerar métodos como toString, equals e hashcode, entre outros, simplesmente com annotations.

Solucionando o problema dos DTOs

Para resolver o problema da passagem de informação entre DTOs e quaisquer outras classes, vamos usar o MapStruct, essa biblioteca é uma ferramenta muito poderosa, que gera o código necessário para passar valores usando o encapsulamento padrão do Java, exatamente o código do nosso exemplo acima automaticamente.

Com a solução proposta vamos reduzir muito o código boilerplate da nossa aplicação, vamos ao tutorial.

Configurando o projeto Spring Boot

Vamos começar a configurar o projeto, essa é a parte mais simples, podemos criar o nosso projeto através do Spring Initializr, você pode colocar as dependências que seu projeto necessitar, mas é necessário adicionar o Lombok também nas suas dependências.

Após adicionar todas as dependências você pode baixar o arquivo compactado e extrair na pasta de trabalho.

Com o seu projeto descompactado, pode importar ele na sua IDE de preferência, analisando e o seu arquivo pom.xml deve se parecer com esse, principalmente as configurações no plugin de build.

Nossa configuração vai ser basicamente alterar as dependências e configurações de build do nosso pom.xml.

Configurando o pom.xml

Vamos adicionar o MapStruct e o seu processor como dependência no nosso projeto, e precisamos alterar os parâmetros no plugin de build para que as bibliotecas possam gerar o código necessário em tempo de compilação do projeto.

Adicionando as propriedades no pom.xml

Vamos adicionar 3 propriedades na tag properties do nosso pom.xml nelas vamos declarar as versões das bibliotecas que vamos utilizar.

<properties>
	<java.version>11</java.version>
	<org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
	<org.projectlombok.version>1.18.24</org.projectlombok.version>
	<compiler-plugin.version>3.8.1</compiler-plugin.version>
</properties>
pom.xml

Adicionando as dependência do MapStruct e do Processor

Vamos adicionar duas dependências no nosso projeto, segue o exemplo.

<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<scope>provided</scope>
</dependency>
<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct</artifactId>
	<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-processor</artifactId>
	<version>1.4.1.Final</version>
	<scope>provided</scope>
</dependency>
pom.xml

Agora que temos todas as dependências necessárias no pom.xml precisamos configurar o plugin de build, e passar a configuração que vai possibilitar que todo o código gerado por ambas bibliotecas aconteça em tempo de build e não em tempo de execução da nossa aplicação.

<build>
  <plugins>
	<plugin>
	    <groupId>org.apache.maven.plugins</groupId>
	    <artifactId>maven-compiler-plugin</artifactId>
	    <configuration>
		<source>${java.version}</source>
		<target>${java.version}</target>
		<annotationProcessorPaths>
		    <path>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>${org.projectlombok.version}</version>
		    </path>
		    <path>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok-mapstruct-binding</artifactId>
			<version>0.2.0</version>
		    </path>
		    <path>
			<groupId>org.mapstruct</groupId>
			<artifactId>mapstruct-processor</artifactId>
			<version>${org.mapstruct.version}</version>
		    </path>
		</annotationProcessorPaths>
		<compilerArgs>
		    <compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
		</compilerArgs>
	    </configuration>
	</plugin>
	...demais plugins
    </plugins>
</build>
pom.xml

Resultado final do pom.xml após a cofiguração

Com todas as configurações finalizadas, seu projeto está pronto para execução, caso queira comparar com ficou o arquivo pom.xml pode fazer com o nosso projeto base hospedado no Github, clique no link para visualizar.

Agora é necessário que as dependências configuradas no pom.xml sejam baixadas e instaladas no nosso projeto para que o mesmo funcione corretamente, podemos fazer isso através do comando:

mvn install
Terminal

As vezes é necessário forçar a geração dos artefatos do projeto, com as novas dependências, e podemos fazer isso através do comando:

mvn clean package
TErminal

Caso queira conhecer mais sobre comandos do Maven acesse nosso tutorial clicando aqui.

Depois de aguardar toda a instalação e gerar os pacotes você pode iniciar o projeto, pode ser feito através da sua IDE ou através do comando no terminal.

mvn spring-boot:run
Terminal

E agora como aplico no código?

Bom a partir de agora o código fica muito mais simples, vamos dar alguns exemplos, para gerar códigos como getters e setters, podemos usar as annotations.

Nesse exemplo a seguir estamos gerando não só os getters e setters como também sobrescrevendo o método toString, equals e hashcode;


@Getter
@Setter
@ToString
@EqualsAndHashCode
public class Example {

    private String foo;
    private String bar;
}
Example.java

E como fica a passagem de informação entre classes? Bom essa fica muito mais fácil ainda o que você precisa fazer é criar uma interface e anotá-la com @Mapper e fazer a assinatura dos método de conversão, se os nomes dos atributos forem iguais em ambas as classes basta criar o método, caso os atributos forem diferentes é necessário mapear, abaixo vamos mostrar os dois exemplos.

Exemplo com atributos com nomes idênticos

@Mapper
public interface ProjectMapper {

	Project toEntity(ProjectRequest request);
	
	ProjectResponse toResponse(Project project);
}
ProjectMapper.java

Exemplo com nomes de atributos diferentes

@Mapper
public interface ProjectMapper {

	@Mapping(source = "projectName", target = "name")
	@Mapping(source = "teamName", target = "team")
	Project toEntity(ProjectRequest request);
	
	@Mapping(source = "name", target = "projectName")
	@Mapping(source = "team", target = "teamName")
	@Mapping(source = "date", target = "creationDate")
	ProjectResponse toResponse(Project project);
}
ProjectMapper.java

Plugins para o Eclipse

A instalação de alguns plugins pode facilitar ainda mais a codificação, no caso do Lombok o plugin é necessário, para que você consiga usufruir da biblioteca, já o MapStruct o plugin se torna opcional mas é interessante de usar pois facilitar muito a vida do desenvolvedor.

MapStruct

Para quem está usando o Eclipse IDE, você pode encontrar no marketplace a extensão do MapStruct que te ajuda a mapear os atributos, esse plugin é opcional você não precisa dele para o mapstruct funcionar corretamente, mas com ele é muito mais fácil mapear as classes com atributos que possui nomes diferentes, pois na hora de setar o source e target, será exibido o nome de cada atributo das classes.

MapStruct Eclipse Plugin
Exibe a tela do marketplace do Eclipse IDE com o plugin do Mapstruct secionado.

Lombok

Para o correto funcionamento do Lombok, você precisa ter o seu plugin configurado corretamente na sua IDE, pois ele necessita do plugin para exibir o código que é gerado automaticamente, já que você utilizar esses métodos gerados durante a codificação, se você não possui o plugin instalado temos um tutorial passo a passo de como fazer clicando aqui.

Exemplo

Criamos um projeto com a configuração que foi mostrada aqui nesse artigo e disponibilizamos no Github do Artefato X. Além de estar toda a configuração ainda possui um exemplo prático do uso das duas bibliotecas.

Links uteis

Mauricio Lima
Mauricio Lima

Bacharel em Ciência da Computação, profissional dedicado ao desenvolvimento de software e entusiasta da tecnologia.

Artigos: 65