-
-
Notifications
You must be signed in to change notification settings - Fork 919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ordering of mapstruct and lombok gradle annotationProcessor seems to matter #1581
Comments
The order should not matter. However, I think that the problem with the builders is projectlombok/lombok#1538. During compilation we can't see the builder and the builder methods from Lombok. If you split the Lombok and MapSruct mappers into 2 different modules then it is going to work. You can chime in on the linked Lombok issue. What do you mean with
|
Some of these classes are de/serialized using the Jackson library. This is done using a combination of @JsonDeserializer annotation on the enclosing class and optionally the JsonPOJOBuilder on the builder class. By default Jackson expects builder class methods to have "with" as the prefix but this can be overridden to have no prefix by using annotating the builder with @JsonPOJOBuilder(withPrefix = ""). This means of course that to use the JsonPOJOBuilder annotation you need to supply the class declaration and have lombok add the rest of the details. Using this approach also matches Mapstructs DefaultAccessorNamingStrategy behaviour which also doesn't expect any prefix. As I said in the initial comment, it probably make no difference but I thought I'd supply as much contextual info as possible, just in case. An example: package au.com.agic.api.travel.dto.request;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@JsonDeserialize(builder = TravelDatesRequest.Builder.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@Builder(builderClassName = "Builder")
public final class TravelDatesRequest {
private final LocalDate departureDate;
private final LocalDate returnDate;
@JsonPOJOBuilder(withPrefix = "")
public static final class Builder {
}
} |
Thanks for providing more information. I'll dig into it to see what is happening. It seems that when you declare your builder there is something affecting the issue I linked. In any case I am fairly certain that the actual problem is the fact that MapStruct does not see the accessors of the builder, due to Lombok not exposing them |
Hi @filiphr , |
@kaweston I checked this and for some reason when mapstruct is before lombok then we see all the builder methods, but when we are after lombok then we don't see the builder methods, but we do see the getters. I can't explain this. This is with the latest (1.18.6) version. @AnkushNakaskar if you swap the order is it working? Which Lombok version are you using? |
It does matter. @filiphr
// before
annotationProcessor("org.projectlombok:lombok")
annotationProcessor("org.mapstruct:mapstruct-processor:${Versions.mapstructVersion}")
// after
annotationProcessor("org.mapstruct:mapstruct-processor:${Versions.mapstructVersion}")
annotationProcessor("org.projectlombok:lombok")
// before
Task = new Task();
return task;
// after
TaskBuilder task = Task.builder();
task.id( source.getId() );
task.serialNumber( source.getSerialNumber() );
return task.build(); Lombok: 1.18.10 |
@hydra1983 the order should not matter. I would suggest upgrading Lombok and also adding the I am going to close this until someone can provide an example project where this is reproducible |
@filiphr I faced the same issue and fixed it with some Gradle tricks. Unfortunately, I can't provide you with an example because it's not an open-source project and Gradle config is really complex. |
@remal FYI, this is my gradle kotlin configuration and it works fine. The order do matters. // mapstruct + lombok
compileOnly("org.projectlombok:lombok:${Versions.lombokVersion}")
compileOnly("org.mapstruct:mapstruct:${Versions.mapstructVersion}")
annotationProcessor("org.projectlombok:lombok:${Versions.lombokVersion}")
annotationProcessor("org.mapstruct:mapstruct-processor:${Versions.mapstructVersion}")
annotationProcessor("org.projectlombok:lombok-mapstruct-binding:${Versions.lombokMapStructBindingVersion}") java -version
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-b01)
Eclipse OpenJ9 VM (build openj9-0.21.0, JRE 1.8.0 Mac OS X amd64-64-Bit Compressed References 20200728_646 (JIT enabled, AOT enabled)
OpenJ9 - 34cf4c075
OMR - 113e54219
JCL - c82ff0c20f based on jdk8u265-b01) ./gradlew --version
------------------------------------------------------------
Gradle 7.3.3
------------------------------------------------------------
Build time: 2021-12-22 12:37:54 UTC
Revision: 6f556c80f945dc54b50e0be633da6c62dbe8dc71
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 1.8.0_265 (Eclipse OpenJ9 openj9-0.21.0)
OS: Mac OS X 10.15.7 x86_64 const val mapstructVersion = "1.4.2.Final"
const val lombokVersion = "1.18.22"
const val lombokMapStructBindingVersion = "0.2.0" |
Is there no further discussion? i've experienced same issue with @hydra1983 and solved problem by |
@hydra1983 I had to create my own Lombok Gradle plugin to fix it: https://github.com/remal-gradle-plugins/lombok |
Cool, I will have a try. Thanks a lot. |
In a work project I have to ensure that the lombok annotationProcessor directive is listed after mapstruct otherwise various errors occur. Identical behaviour whether running gradle from command line or via the gradle window in Intellij.
Sample of errors encountered. Not sure if this matters but both TravelWhatIfPrice and ContactDetails use lombok Builder annotations although the Builder class are already defined without methods so that I can use the Jackson library's @JsonPOJOBuilder(withPrefix="") annotation to match with lombok's setter naming convention.
......CsApi2TravelWhatIfPricesMapper.java:11: error: au.com.agic.api.travel.domain.TravelWhatIfPrice does not have an accessible parameterless constructor.
TravelWhatIfPrice toModel(final CsApi2TravelWhatIfPrice csApi2TravelWhatIfPrice);
....... CsApi2ContactDetailsMapper.java:23: error: Property "id" has no write accessor in au.com.agic.api.travel.domain.ContactDetails.
@mapping(target = "id", source = "id")
The text was updated successfully, but these errors were encountered: