jiangwensi
jiangwensi

Reputation: 193

MapStruct mapper returns empty mapped object

I'm trying to use MapStruct to map convert between dto and entity objects, however the generated mapper implementation only returns empty mapped object.

BeerMapperImpl

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-11-05T07:42:21+0800",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 11 (Oracle Corporation)"
)
@Component
public class BeerMapperImpl implements BeerMapper {

    @Override
    public BeerDto beerToBeerDto(Beer beer) {
        if ( beer == null ) {
            return null;
        }

        BeerDto beerDto = new BeerDto();

        return beerDto;
    }
}

Below are my codes.

pom.xml

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.3.0.Final</version>
</dependency>

.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <annotationProcessorPaths>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>1.3.0.Final</version>
            </path>
            <path>
                <groupId>
                    org.projectlombok
                </groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </path>
        </annotationProcessorPaths>
        <compilerArgs>
            <compilerArg>
                -Amapstruct.defaultComponentModel=spring
            </compilerArg>
        </compilerArgs>
    </configuration>
</plugin>

BeerMapper.java

@Mapper(uses = {DateMapper.class})
public interface BeerMapper {
    BeerDto beerToBeerDto(Beer beer);
    Beer beerDtoToBeer(Beer dto);
}

Anyone can help to advise what might go wrong in my codes? Thanks!

Upvotes: 17

Views: 11907

Answers (8)

Yan Frankovski
Yan Frankovski

Reputation: 61

In case that you already have lombok-mapstruct-binding dependency and still get the same empty result:

Make sure use didn't forget to add @Setter, @Getter and constructor annotation from lombok to your target class.

Mapstrcut seems to quietly skip fields that it can't set or get without even a warning.

Upvotes: 0

When using mapstruct with lombok, the position of the dependencies plays role on how mapstruct generates mapper implementation. just like > Yassir Khaldi already explained with the getters and setters logic of both mapstruct and lombok. especially if you are using gradle, ensure that the lombok dependency comes before mastruct dependency

***
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
***

Upvotes: 0

jhonromanoft
jhonromanoft

Reputation: 1

As official documentation suggest, newer versions of lombok require an aditional anotation processor dependency so you would need to add a new annotation processor like so (maven)

<path>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok-mapstruct-binding</artifactId>
  <version>***</version>
</path>

make sure you add the latest version compatible with your gradle build

for gradle users it will be something like this

annotationProcessor 'org.projectlombok:lombok-mapstruct-binding'

this way it will work with no problem in new versions of spring

Upvotes: 0

Rostyslav Pryimak
Rostyslav Pryimak

Reputation: 11

To the dto I added a @AllArgsConstructor, after removing it - works fine. Stupid, but works. The order of dependencies and paths was good, and spring boot version was older then proposed to downgrade

Upvotes: 0

Yassir Khaldi
Yassir Khaldi

Reputation: 1762

I have found the solution without having to downgrade spring boot. The problem was that I was using lombok to generate getters and setters, on the other side mapstruct looks for getters and setters in your objects to populate them, but in this case it couldn't find them simply because during the compilation mapstruct was running before lombok could generate them.

The solution is simply to write the configuration of lombok before the configuration of mapstruct in your pom.xml file to execute lombok in first place. Make sure to run clean compile to delete old files.

Working configuration of maven-compiler-plugin:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.8.1</version>
  <configuration>
    <source>1.8</source>
    <target>1.8</target>
    <annotationProcessorPaths>
      <!--Project Lombok compile preprocessor-->
      <path>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
      </path>
      <!--Maps Struct compile preprocessor-->
      <path>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>${mapstruct-ver}</version>
      </path>
    </annotationProcessorPaths>
  </configuration>
</plugin>

Upvotes: 48

Brad Jones
Brad Jones

Reputation: 101

I've encountered a similar problem where all the values in the object created by the mapstruct mapping had null values when the original object was populated. When I checked the generated mapper in target the generated implementation did not contain an actual mapping. I found that this was easily fixed when I made a small change to the Mapper in my project and saved it. The mapper in target was re-generated with the mapping in place. I'm not sure why the mapper was generated incorrectly but this was a qick fix that worked for me.

Upvotes: 0

Guram Kankava
Guram Kankava

Reputation: 61

I removed annotation Processor Paths tag and declared bot lombok and mapstruct as dependency.

link with similar issue: MapStruct and Lombok not working together

Upvotes: 1

jiangwensi
jiangwensi

Reputation: 193

I resolved this issue after downgrading spring boot starter from 2.3.5.RELEASE to 2.1.5.RELEASE.

Upvotes: 1

Related Questions