Can't build maven jhipster project with lombok - maven

./mvnw and mvn clean install fail when adding lombok dependency but run successfully when launched from Intellij IDE
Find the error below :
INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] src/main/java/web/rest/core/service/impl/ProductServiceImpl.java:[18,29] cannot find symbol
symbol: method builder()
location: class com.test.one.web.rest.core.model.Product
Here is the POJO
import lombok.Builder;
import lombok.Data;
#Data
#Builder
public class Product {
private String name;
}

The maven project Jhipster generated uses a annotationProcessorPaths in the maven compile plugin, that's why it cannot look up the latest lombok unless we specify lombok as one of the annotation processor.
Working code is as followed.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<!-- For JPA static metamodel generation -->
<path>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</path>
</annotationProcessorPaths>
</configuration>

I managed to work with the following combination of versions:
maven-compiler-plugin: 3.3
lombok: 1.16.18 (latest)
So for example, a pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
</plugin>

Related

Mapstruct mapping not working if the field is private [duplicate]

Tech Stack being used :
Java 8
MapStruct : 1.2.0.Final
Lombok: 1.16.18
IDE: IntelliJ - Lombok Plugin already installed
Initially, I faced issues when I removed getters and setters and added #Getter and #Setter annotation, mapstruct is not able to find the property and says: Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?
I came to know that Lombok 1.16.14 or newer along with MapStruct 1.2.0.Beta1 or newer are compatible and can work together, but my versions are newer then the desired still the issue is arising.
One more solution that I have already tried is running Lombok's Delombok plugin, but still, the same issue is arising.
Below are the project files :
The Entity Object: One.java:
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
public class One {
private int id;
private Integer version;
private int projectId;
private String title;
private String code;
private int sortOrder;
}
The DTO Object: OneDTO.java :
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
public class OneDto {
private int id;
private Integer version;
private int projectId;
private String title;
private String code;
private int sortOrder;
}
Mapper Class : OneMapper.java
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import com.vg.once.dto.OneDto;
import com.vg.once.entity.One;
#Mapper
public interface OneMapper {
#Mapping(target="id", source="one.id")
OneDto createOne (One one);
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vg</groupId>
<artifactId>mapstruct</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Mapstruct-test</name>
<properties>
<java.version>1.8</java.version>
<org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
<org.projectlombok.version>1.16.18</org.projectlombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.18.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/java</sourceDirectory>
<addOutputDirectory>false</addOutputDirectory>
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
<encoding>UTF-8</encoding>
<skip>false</skip>
<verbose>false</verbose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Build Trace:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Mapstruct-test 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- lombok-maven-plugin:1.16.18.1:delombok (default) # mapstruct ---
[INFO] Delombok complete.
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) # mapstruct ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.6.1:compile (default-compile) # mapstruct ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to /home/vivekgupta/Documents/workspaces/mapstruct-test/mapstruct/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /home/vivekgupta/Documents/workspaces/mapstruct-test/mapstruct/src/main/java/com/vg/once/mapper/OneMapper.java:[12,9] Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.637 s
[INFO] Finished at: 2017-12-06T19:23:53+05:30
[INFO] Final Memory: 19M/235M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project mapstruct: Compilation failure
[ERROR] /home/vivekgupta/Documents/workspaces/mapstruct-test/mapstruct/src/main/java/com/vg/once/mapper/OneMapper.java:[12,9] Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
please share how can i get this working using both Lombok and MapStruct together?
The reason why it does not work is because Maven only uses the MapStruct processor and not the Lombok one. The annotationProcessorPaths tells maven which processors it should use.
The delombok does nothing as you are ending up with 2 files per class and I think that the maven compiler does not see them.
You have 2 options:
Option 1: Add the lombok dependency in the annotationProcessorPaths
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<!-- This is needed when using Lombok 1.18.16 and above -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
<!-- Mapstruct should follow the lombok path(s) -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Option 2:
Add the mapstruct-processor dependency to your dependencies and remove the annotationProcessorPaths. This way the maven compiler will pick up all the annotation processors that are in your dependencies.
I would advise in using Option 1, as with that you can be certain that you are not using some MapStruct transitive dependencies and internal classes in your code.
Edit:
To make sure that the IntelliJ annotation processing also works you will have to add the mapstruct-processor as a provided dependency due to IDEA-150621. IntelliJ in the moment does not use the annotationProcessorPaths from Maven to configure the project correctly.
Edit 2:
Add information and comment about lombok-mapstruct-binding needed from Lombok 1.18.16.
Just in case if somebody is looking for how to configure it using Gradle:
dependencies {
// Lombok
compileOnly 'org.projectlombok:lombok:1.18.2'
annotationProcessor 'org.projectlombok:lombok:1.18.2'
// MapStruct
compileOnly 'org.mapstruct:mapstruct-jdk8:1.2.0.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.2.0.Final'
}
After multiple attempts in my Spring Boot Maven project, the following finally worked:
Configuration of pom.xml:
The properties section:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<version.lombok>1.18.18</version.lombok>
<version.mapstruct>1.4.2.Final</version.mapstruct>
<version.mapstruct-lombok>0.2.0</version.mapstruct-lombok>
</properties>
The dependencies section:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${version.lombok}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${version.mapstruct}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${version.mapstruct-lombok}</version>
</dependency>
The build plugins section:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>9</source>
<target>9</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${version.mapstruct}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${version.lombok}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${version.mapstruct-lombok}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Hope this helps, my mapper before did not map the field values, but now these are mapper between the source and the target + the nested list of elements in each is also being mapped along with field values.
For me solution was realy simple.
The order of the processors was important.
In my case mapstruct processor was defined before lombok processor. In case with bad order mapstruct does not generate mappings, just create instance of result class (i saw that in generated implementation).
My plugin configuration with right order:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>15</source>
<target>15</target>
<compilerArgs>--enable-preview</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
And of course you need to add dependencies:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
I had similar issues. Turned out my MapStruct version was outdated!
I used MapStruct version 1.1.0.Final, but for Lombok support at least 1.2.0.Final is required.
If anyone is reading this when using the latest Lombok and Mapstruct library versions:-
If you are using Lombok 1.18.16 or newer then you also need to add lombok-mapstruct-binding in order to make Lombok and MapStruct work together.
https://mapstruct.org/faq/#Can-I-use-MapStruct-together-with-Project-Lombok
I feel a right way to declare versions in pom.xml is to refer to something like this for versions instead of manually specifying versions of everything. e.g. maven-compiler-plugin.version, lombok.version is already present there
properties block -
<properties>
<java.version>11</java.version>
<mapstruct.version>1.4.2.Final</mapstruct.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>
dependencies block -
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<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>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</dependency>
<!-- ... -->
</dependencies>
build block -
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
For issues after upgrading Intellij to 2020.3 version, following solution worked for me.
Use lombok version: 1.18.16, lombok-mapstruct-binding: 0.2.0
<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.2.0</version>
</dependency>
Change the order of the lombok and mapstruct plugin path in annotation processing section of plugins:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>11</source>
<target>11</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
Apparently this is how you are supposed to load multiple annotation processors in Gradle
dependencies {
implementation "org.mapstruct:mapstruct:1.4.2.Final", "org.projectlombok:lombok:1.18.20"
annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final", "org.projectlombok:lombok:1.18.20", "org.projectlombok:lombok-mapstruct-binding:0.2.0"
}
If someone is still looking for this answer, I faced a similar issue with JOOQ + MapStruct Integration. The answer is the order of paths matters
IntellijIdea 2020.2.3
Java 8
Spring Framework 2.4.0
My build snippet
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<!-- This is needed when using Lombok 1.8.16 and above -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${org.lombok-mapstruct-binding.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
</plugins>
</build>
The mapstruct was just returning a null instance. Recently I upgraded the Intellij version to 2020.3, and spring boot 2.4.0, and landed into this situation.
When I changed the spring version to 2.3.o.RELEASE, I could see after compilation is that mapstruct was building the mappings properly.
Going through the post that mapstruct has recently updated.. but it will take time.. :) so, for now, I moved from maven to Gradle project and all working absolutely fine.. sounds weird but true...
I would be thankful if anyone would post what exactly the right issue and what's the solution.
For people who uses build gradle, this is the .gradle file I successfully created
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation "org.projectlombok:lombok-mapstruct-binding:${gradleMapstructVersion}"
implementation "org.mapstruct:mapstruct:${mapstructVersion}"
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
}
The things is that, as said above, we have to use the org.projectlombok:lombok-mapstruct-binding in order to use mapstruct with lombok
I agree that the order does play its role, also when using gradle. In my case it was failing as soon I was adding subprojects { ... dependencyManagement{}} to the parent build.gradle in a multimodule setup.
If you have reached till here, that means none of the above solutions worked for you. Finally what worked for me was:
The following order of annotation processor in pom.xml
<annotationProcessorPaths>
...
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
...
</annotationProcessorPaths>
The following setting of Annotation Processors in Intellij IDEA Preferences. Make sure your project is in the right profile. In my case the profile is Annotation Profile for Alippo and project is alippo. I really don't know how the configuration made the difference.
For Spring-Boot the simplest configuration with exclude processing code from result jar:
pom.xml
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
....
</dependencies>
<build>
<plugins>
<!-- exclude from jar-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
</exclude>
<exclude>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
Without lombok-mapstruct-binding it also works fine.
Maybe somebody comments, what for does it needed?
It is enough to add the following dependencies:
implementation("org.mapstruct:mapstruct:1.4.2.Final")
annotationProcessor("org.mapstruct:mapstruct-processor:1.4.2.Final")
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok-mapstruct-binding:0.2.0")
Format: Gradle(Kotlin)

Not able to get the lombok features in STS

I am using STS on windows. I have added lombok.jar into my project.
I have access to the annotations but the getters and setters aren't generated. I get the same errors I would get if I tried accessing a getter or setter method that doesn't exist. What could I be missing?
Here are the code snips
Bean:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Employee {
private String name;
private String address;
private String location;
}
Pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
Lombok is a code generator. It doesn't need to be included as part of your built target, as such it should be included in your maven as a provided dependency:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
You also need to make sure the annotation processor is setup to run as part of the maven build. (Also in the above link)
I don't use eclipse, but you probably also want to install the lombok plugin for eclipse so that eclipse knows the getters and setters are not in the code files but will be generated.

Issue on maven(pom.xml) settings on QueryDsl, MapStruct, Lombok and intellij

My Problem -
QueryDsl and MapStruct only generate classes on maven install but i want it to re-generate on source code change (with springboot devtool auto restart). now it does nothing on source code change other than restart
My pom.xml as below
....
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
.....
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/annotations</outputDirectory>
<processors>
<processor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</processor>
<processor>org.mapstruct.ap.MappingProcessor</processor>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</processors>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Intellij Setting
Annotation Processors
My Proccess -
Before Spring-boot Start i have to clean then install maven due to Qclass and MapperImpl. Also after maven install because of Qclass error, got to check "Module output directory" on "Store generated sources relative to:"
and everytime i change mapstruct mapper file i have do above things yet again which is very annoying
i have tried this solution but it didnt work .. :X
stackover flow solution
Please help
Thx :)
The best way to achieve that is to use the annotationProcessorPaths from the maven-compiler. It will do the job during the compilation phase of the project.
IntelliJ already configures the build appropriately based on the maven-compiler and will be able to detect your processors. I also know that in IntelliJ IDEA 2020.3 they are going to do some improvement around the processors that would improve the user experience.

How to configure for Spring Boot Configuration Annotation Processor using #ConfigurationProperties on IntelliJ?

On IntelliJ, I am getting a Spring Boot Configuration Annotation Processor not configured for having #ConfigurationProperties. Below is my class:
#Configuration
#ConfigurationProperties(prefix = "abc")
#Data
#RefreshScope
class Config {
String propA;
String propB;
...
}
I am not sure what's causing this and when I click on the wrench for settings, I do not see any options to configure for metadata files.
I faced the same problem with IntelliJ IDEA 2020.2 and Maven 3.6.2. The solution was to explicitly set the annotation processor in the maven-compiler-plugin settings. I found the answer here:
https://stackoverflow.com/a/48028193/9989732
https://stackoverflow.com/a/64031211/9989732
The full configuration:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.4.2</version>
<optional>true</optional>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<annotationProcessorPaths>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.4.2</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
I resolved it by adding the following dependency to my pom file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.6.RELEASE</version>
<optional>true</optional>
</dependency>
You can easily generate your own configuration meta-data file from items annotated with #ConfigurationProperties by using the spring-boot-configuration-processor jar. The jar includes a Java annotation processor which is invoked as your project is compiled. To use the processor, simply include spring-boot-configuration-processor as an optional dependency, for example with Maven you would add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
For Gradle, like Maven, we need to add The appropriate annotation processor. To do so, add a line to the dependencies section in your build.gradle file.
dependencies {
...
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor:'
...
}

MapStruct - #Mapper annotation don't create bean

I downloaded application from this source https://github.com/springframeworkguru/spring5-mvc-rest/tree/vendor-api
And I have a problem with MapStruct.
#Mapper
public interface CategoryMapper {
CategoryMapper INSTANCE = Mappers.getMapper(CategoryMapper.class);
CategoryDTO categoryToCategoryDTO(Category category);
}
#Data
public class CategoryDTO {
private Long id;
private String name;
}
domain class:
#Data
#Entity
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
Service class:
#Service
public class CategoryServiceImpl implements CategoryService {
private final CategoryMapper categoryMapper;
private final CategoryRepository categoryRepository;
public CategoryServiceImpl(CategoryMapper categoryMapper, CategoryRepository categoryRepository) {
this.categoryMapper = categoryMapper;
this.categoryRepository = categoryRepository;
}
}
And in pom.xml dependency, I paste only two::
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<org.mapstruct.version>1.2.0.CR2</org.mapstruct.version>
</properties>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
And plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
Description:
Parameter 0 of constructor in
guru.springfamework.services.CategoryServiceImpl required a bean of type 'guru.springfamework.api.v1.mapper.CategoryMapper' that could not be found.
Action:
Consider defining a bean of type 'guru.springfamework.api.v1.mapper.CategoryMapper' in your configuration.
I think that in my Intellij annotation #Mapper don't create a bean for mapper.
I didn't change code from John GitHub.
Any idea?
I tried to change path generated source to target but this doesn't help
Thanks for help.
I resolved the error by doing
mvn clean install
Also add this to your pom
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
In order to use mappers as beans and use #Autowired, just declare mappers as #Mapper(componentModel = "spring"). Then just inject it wherever you need this.
The issue is that using the #Mapper construct will generate a class without
the #Component annotation by default.
You are probably not using Maven to compile your project. Make sure to run a Maven clean and install, or pass in the compiler arguments mapstruct.defaultComponentModel=spring manually.
Since you are using:
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
This will tell MapStruct to generate a Spring Component.
If you check your compiled target class, and open it up in a decompiler (if your IDE supports this), there should be a CategoryMapperImpl that is annotated with #Component.
In your Mapper class, use #Mapper(componentModel = "spring") instead of just #Mapper
and run mvn clean install, that's it! you're done!
and the alternative to it, is to define compiler arguments in plugin of pom.xml like below!
<plugin>
<configuration>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
I had the same problem. In Gradle I solved it by adding new dependency:
compileOnly('org.mapstruct:mapstruct-processor:1.3.0.Beta2')
And all necessary dependencies should be as follows:
compile('org.mapstruct:mapstruct:1.3.0.Beta2')
compileOnly('org.mapstruct:mapstruct-processor:1.3.0.Beta2')
annotationProcessor('org.mapstruct:mapstruct-processor:1.3.0.Beta2')
It worked for me when I added the annotationProcessor for both dependencies.
annotationProcessor group: 'org.mapstruct', name: 'mapstruct', version: '1.4.2.Final'
implementation group: 'org.mapstruct', name: 'mapstruct', version: '1.4.2.Final'
annotationProcessor group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.4.2.Final'
implementation group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.4.2.Final'
Also, made sure using
#Mapper(componentModel = "spring")
public interface MyMapper {
For me it was the missing componentModel in the #Mapper annotation on the interface / abstract class.
So this didn't work:
#Mapper
But this worked:
#Mapper(componentModel = "spring")
I presume that this is not working in IntelliJ only. There is a known issue, where IntelliJ actually does not pick up the annotation processors from the maven compiler annotationProcessorPaths (see IDEA-150621 for more info).
On top of that the examples in the linked repository are against MapStruct best practices. When the spring componentModel is used then Mappers.getMapper should never be used. The reason is that the factory will not be able to construct the mapper correctly as it should be constructed via spring. Also the compiler argument mapstruct.defaultComponentModel can break integration with IDE, as it is not being picked up (you would need to set it in the IntelliJ settings as well)
This was working for me:
POM Dependencies:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<scope>provided</scope>
</dependency>
POM Plugins:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Having componentModel = "spring" parameter in #MapStruct annotation.
Run mvn clean on your project.
I don't think you really need the following compiler argument declaration in your POM, because ``componentModel = "spring"` should be enough.
<plugin>
<configuration>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
I've taken these code snippets from a microservice application project generated by JHipster.
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
Added these both dependencies solved my problem, processor needed for creating beans (https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor), if the red line on the constructor bothers you (it does not bother compiler) #Autowired(required = false) add this.
I resolved this by first installing MAVEN_HOME in environment variables then do a mvn clean install. I've found out that I was running my project in eclipse and then Intellij without installing maven.
You have to enable your annotation processor in you IntelliJ from,
Settings -> Build, Execution, Deployment -> Compiler -> Annotation
Processors and click on checkbox of Enable annotation processing.
You first have to use the Mapper like this
To use mappers as beans and use **#Autowired**,
just declare mappers as #Mapper(componentModel = "spring").
Then just inject it wherever you need this.
Also every time you create a new mapper class always remember to do mvn clean install.
It will create the implementation file of you mapper interface in the target folder and then you can run your Spring project.
Please, add in your mapper class.
#Mapper(componentModel = "spring")
So,
Instead of #Mapper add #Mapper(componentModel = "spring")

Resources