How to use Mapstruct in Kotlin Spring Boot with the injection of Spring Boot Services and Repositories

When passing a DTO to the Spring Boot REST controller, some relationships between entities are represented by using the id / unique property instead of the entire object. We can make the conversion and error handling easier by injecting Spring Boot services and repositories into the Mapstruct mapper to avoid repetitive code.

3LexW
3 min readAug 25, 2022

First, I would like to thank Muhammad Usama and Antonello Zanini's articles on the introduction of using Spring Boot with the Mapstruct library. Please check out their articles, which I referenced a lot in the source code:

The source code for the demonstration is on my GitHub. Feel free to check them out.

Installing MapStruct to project

Sync the Gradle dependencies and install the Mapstruct packages.

Setting up Entities and the Repository to inject

We first set up two classes, AppUser and Department . Each user belongs to one department.

We then set up the DepartmentRepository for us to inject, you can choose to inject the service layer into the mapper. The demonstration is only for simplification.

Setting up the Dto

Create the UserDto as the mapping target

Setting up the Mapper

First, we define the mapper class as an abstract class, annotate with @Mapper(componentModel = "spring")

Then, inject the previously created DepartmentRepository, create a lateinit var and perform dependency inject with with @Autowired .

Now, on the actual mapper, use @Named annotation to annotate a method that uses the DepartmentRepository to obtain the department id.

Finally, create an abstract function that maps the DTO to the entity and marks with the @Mapping annotation when converting the department name since the names between the source and target classes are not the same.

Use the qualifiedByName property of the @Mapping annotation class such that the department's information conversion will be using the function we just created.

Finally, run the Gradle tasks to create the implementation classes of the mapper.

#With in the working directory./gradlew clean
./gradlew kaptKotlin

Perform Testing

Of course, we would like to create some tests to ensure that the mappers are good enough for us to implement.

First, we create some seed data by creating a new file: src/test/resources/import.sql . Then, add the following SQL statement:

insert into department (department_id, department_name) values ('DEPT_A', 'Department A');

Then, we set up the test class by using @SpringBootTest. By using @Autowired , we inject the mapper into the test class.

The first test tests if the Dto can be converted to the entity by the mapper if the department id can be found in the database:

The second test tests if an error will be thrown if the department id does not exist in the database:

Thank you for your reading, and happy coding.

--

--

No responses yet