Reputation: 1227
MapStruct is unable to create an implementation when I'm trying to map object with a private default constructor, but with a (lombok generated) builder.
SomeMapperImpl.java:[20,27] SomeDto() is not public in com.example.mapstructdemo.dto.SomeDto; cannot be accessed from outside package
Dto:
@Value
@Builder
public class SomeDto {
}
Model:
@Value
@Builder
public class SomeModel {
}
Mapper interface:
@Mapper
public interface SomeMapper {
SomeDto map(SomeModel someModel);
SomeModel map(SomeDto someDto);
}
fragment from Pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<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.2.0</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.1.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
The generated implementation:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-01-29T13:47:46+0100",
comments = "version: 1.4.1.Final, compiler: javac, environment: Java 11.0.9.1 (Ubuntu)"
)
public class SomeMapperImpl implements SomeMapper {
@Override
public SomeDto map(SomeModel someModel) {
if ( someModel == null ) {
return null;
}
SomeDto someDto = new SomeDto();
return someDto;
}
@Override
public SomeModel map(SomeDto someDto) {
if ( someDto == null ) {
return null;
}
SomeModel someModel = new SomeModel();
return someModel;
}
}
What can I do to help mapstruct find the builder?
To reproduce the problem, clone this repo https://github.com/rmvanderspek/mapstruct-demo and mvn verify.
Upvotes: 13
Views: 25357
Reputation: 1469
I've spent a couple of hours figuring this out:
Just in case you are not using Lombok @Builder
to set up the builder pattern for your object.
Make sure your builder method is public
and static
:
public static SectionBuilder builder() {
return new SectionBuilder();
}
Upvotes: 1
Reputation: 1382
I put the lombok artifact below the mapstruct and mapstruct-processor artifact in the dependencies and it started working.
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</dependency>
</dependencies>
Upvotes: 1
Reputation: 4048
I've played around with your demo sources, and it turns out that placing Mapstruct first in the compiler plugin sources fixes the issue. I don't know why this works, it feels counterintuitive to me, but this is what one of the developers of Mapstruct suggested in a similar issue posted on Lombok's Github.
So in your case:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.mapstruct-processor.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.lombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${org.projectlombok.ombok-mapstruct-binding.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Upvotes: 19