Lombok: [BUG] Mapstruct + Lombok failed to generate implementation of mappers

Created on 24 Oct 2020  路  6Comments  路  Source: projectlombok/lombok

Describe the bug
I was upgrading dependencies in my project and then upgrades JDK version (from 14 to 15), so i need to upgrade lombok dependency to version 1.18.16. As described in README, I added lombok-mapstruct-binding.

After this I have some problems with generated mapstruct mappers. It looks like mapstruct cannot bind to lombok generated setters. I've tried downgrade back to jdk14, but nothing changed.

Below you can see examples.

example of my pom.xml :

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.4.1.Final</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>0.1.0</version>
        </dependency>
       ...
       other dependencies
       ...
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>15</release>
                    <compilerVersion>javac15</compilerVersion>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.4.1.Final</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.16</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            ...
        <plugins>

My entity:

public class Offer {

    private Long   id;
    private Long   offerId;
    private String  title;

   ... 
   manually added constructors, getters and setters
   ...

My dto:

@Data
public class OfferDTO {
    private Long    id;
    private Long    offerId;
    private String  title;
}

MapStract mapper:

@Mapper(componentModel = "spring")
public interface OfferMapper {

    OfferDTO toDto(Offer entity);
}

Generated implementation of mapper:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-10-24T11:55:45+0300",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 15 (AdoptOpenJDK)"
)
@Component
public class OfferMapperImpl implements OfferMapper {

    @Override
    public OfferDTO toDto(Offer entity) {
        if ( entity == null ) {
            return null;
        }

        OfferDTO offerDTO = new OfferDTO();

        return offerDTO;
    }
}

As you can see, mapstruct just creates new object, and there no mapping at all.

Expected behavior
If I manually adds setters on OfferDTO it works as expected, example:
OfferDTO:

public class OfferDTO {
    private Long    id;
    private Long    offerId;
    private String  title;

    public void setId(Long id) {
        this.id = id;
    }

    public void setOfferId(Long id) {
        this.offerId = id;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

MapperImpl:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-10-24T12:10:35+0300",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 15 (AdoptOpenJDK)"
)
@Component
public class OfferMapperImpl implements OfferMapper {

    @Override
    public OfferDTO toDto(Offer entity) {
        if ( entity == null ) {
            return null;
        }

        OfferDTO offerDTO = new OfferDTO();

        offerDTO.setId( entity.getId() );
        offerDTO.setOfferId( entity.getOfferId() );
        offerDTO.setTitle( entity.getTitle() );

        return offerDTO;
    }
}

Version info:

  • Lombok version: 1.18.16

    • Mapstruct version: 1.4.1.Final (1.3.1.Final too)

  • Platform: javac15 (javac14 too)

Maybe I am doing something wrong ? Is there any workaround ?

Most helpful comment

鉁旓笍 Look like I can handle this!
you should add lombok-mapstruct-binding not as dependency, but as annotation processor's path
like this:

<path>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok-mapstruct-binding</artifactId>
  <version>${lombok-mapstruct-binding.version}</version>
</path>

All 6 comments

I was caught this error as well when upgrade to 1.18.14/1.18.16,but degrade to 1.18.12,it works fine

Same problem with JDK 11. This started to break as of Lombok version 1.18.14, up to version 1.18.12 everything is working OK.

Same problem here also. As the latest Spring Boot Parent (2.3.5) also uses lombok 1.18.16 I suspect a lot of other people will also run into this.

Hello, I just faced it tomorrow on a SpringBoot project with Mapstruct 1.4.1.Final. I can confirm downgrading to 1.18.12 solves the problem.

Describe the bug
I was upgrading dependencies in my project and then upgrades JDK version (from 14 to 15), so i need to upgrade lombok dependency to version 1.18.16. As described in README, I added lombok-mapstruct-binding.

After this I have some problems with generated mapstruct mappers. It looks like mapstruct cannot bind to lombok generated setters. I've tried downgrade back to jdk14, but nothing changed.

Below you can see examples.

example of my pom.xml :

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.4.1.Final</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>0.1.0</version>
        </dependency>
       ...
       other dependencies
       ...
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>15</release>
                    <compilerVersion>javac15</compilerVersion>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.4.1.Final</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.16</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            ...
        <plugins>

My entity:

public class Offer {

    private Long   id;
    private Long   offerId;
    private String  title;

   ... 
   manually added constructors, getters and setters
   ...

My dto:

@Data
public class OfferDTO {
    private Long    id;
    private Long    offerId;
    private String  title;
}

MapStract mapper:

@Mapper(componentModel = "spring")
public interface OfferMapper {

    OfferDTO toDto(Offer entity);
}

Generated implementation of mapper:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-10-24T11:55:45+0300",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 15 (AdoptOpenJDK)"
)
@Component
public class OfferMapperImpl implements OfferMapper {

    @Override
    public OfferDTO toDto(Offer entity) {
        if ( entity == null ) {
            return null;
        }

        OfferDTO offerDTO = new OfferDTO();

        return offerDTO;
    }
}

As you can see, mapstruct just creates new object, and there no mapping at all.

Expected behavior
If I manually adds setters on OfferDTO it works as expected, example:
OfferDTO:

public class OfferDTO {
    private Long    id;
    private Long    offerId;
    private String  title;

    public void setId(Long id) {
        this.id = id;
    }

    public void setOfferId(Long id) {
        this.offerId = id;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

MapperImpl:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-10-24T12:10:35+0300",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 15 (AdoptOpenJDK)"
)
@Component
public class OfferMapperImpl implements OfferMapper {

    @Override
    public OfferDTO toDto(Offer entity) {
        if ( entity == null ) {
            return null;
        }

        OfferDTO offerDTO = new OfferDTO();

        offerDTO.setId( entity.getId() );
        offerDTO.setOfferId( entity.getOfferId() );
        offerDTO.setTitle( entity.getTitle() );

        return offerDTO;
    }
}

Version info:

* Lombok version: 1.18.16

* Mapstruct version: 1.4.1.Final (1.3.1.Final too)

* Platform: javac15 (javac14 too)

Maybe I am doing something wrong ? Is there any workaround ?

<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.4.1.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.1.Final</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.1.0</version> </dependency> ... other dependencies ... <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>15</release> <compilerVersion>javac15</compilerVersion> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.1.Final</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.1.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> ... <plugins>

Have u try this锛烮 caught the problem with jdk8 cause lombok-mapstruct-binding compiled by jdk11 and set compile target to 1.9 in buildScripts/mapstructBinding.ant.xml

see

2616

鉁旓笍 Look like I can handle this!
you should add lombok-mapstruct-binding not as dependency, but as annotation processor's path
like this:

<path>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok-mapstruct-binding</artifactId>
  <version>${lombok-mapstruct-binding.version}</version>
</path>
Was this page helpful?
0 / 5 - 0 ratings