2

So, I am using mapstruct api in my maven project.

Here is my application pom.xml configuration:

<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>
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>org.mapstruct.examples.lombok</groupId>
    <artifactId>mapstruct-examples-lombok</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
        <org.projectlombok.version>1.18.16</org.projectlombok.version>
        <lombok-mapstruct-binding.version>0.1.0</lombok-mapstruct-binding.version>
    </properties>

    <dependencies>

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <!-- lombok dependencies should not end up on classpath -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- IntelliJ pre 2018.1.1 requires the mapstruct processor to be present as provided dependency -->
<!--        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
            <scope>provided</scope>
        </dependency>-->

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
            <version>4.13.1</version>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <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>
                        <!-- See https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html -->
                        <!-- Classpath elements to supply as annotation processor path. If specified, the compiler   -->
                        <!-- will detect annotation processors only in those classpath elements. If omitted, the     -->
                        <!-- default classpath is used to detect annotation processors. The detection itself depends -->
                        <!-- on the configuration of annotationProcessors.                                           -->
                        <!--                                                                                         -->
                        <!-- According to this documentation, the provided dependency processor is not considered!   -->
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${org.mapstruct.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${org.projectlombok.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok-mapstruct-binding</artifactId>
                                <version>${lombok-mapstruct-binding.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
         <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>1.8</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
               <source>target/generate-sources</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

My Pojo classes:

SimpleSource.java

public class SimpleSource {
    private String name;
    private String description;
    // getters and setters
}

SimpleDestination.java

public class SimpleDestination {
    private String name;
    private String description;
    // getters and setters
}

Mapper interface:

SimpleSourceDestinationMapper.java

@Mapper
public interface SimpleSourceDestinationMapper {
    SimpleDestination sourceToDestination(SimpleSource source);
    SimpleSource destinationToSource(SimpleDestination destination);
}

It generates proper implementation class:

SimpleSourceDestinationMapperImpl.java(generated)

public class SimpleSourceDestinationMapperImpl implements SimpleSourceDestinationMapper {
    @Override
    public SimpleDestination sourceToDestination(SimpleSource source) {
        if ( source == null ) {
            return null;
        }
        SimpleDestination simpleDestination = new SimpleDestination();
        simpleDestination.setName( source.getName() );
        simpleDestination.setDescription( source.getDescription() );
        return simpleDestination;
    }
    @Override
    public SimpleSource destinationToSource(SimpleDestination destination){
        if ( destination == null ) {
            return null;
        }
        SimpleSource simpleSource = new SimpleSource();
        simpleSource.setName( destination.getName() );
        simpleSource.setDescription( destination.getDescription() );
        return simpleSource;
    }
}

Everything is working fine when I run command mvn clean install/mvn clean test.

But when I run mvn test / mvn install it is failing with below error.(Note: if we run mvn install/mvn test for the first time, it works because target folder is not present for the first time before build).

So if I run the mvn test / mvn install again when target folder is present, I get the below error.

mapstructapt\src\main\java\SimpleSourceDestinationMapper.java:9: error: Internal error in the mapping processor: java.lang.RuntimeException: javax.annotation.processing.FilerException: Attempt to recreate a file for type SimpleSourceDestinationMapperImpl at org.mapstruct.ap.internal.processor.MapperRenderingProcessor.createSourceFile(MapperRenderingProcessor.java:67) at org.mapstruct.ap.internal.processor.MapperRenderingProcessor.writeToSourceFile(MapperRenderingProcessor.java:52) at org.mapstruct.ap.internal.processor.MapperRenderingProcessor.process(MapperRenderingProcessor.java:42) at org.mapstruct.ap.internal.processor.MapperRenderingProcessor.process(MapperRenderingProcessor.java:37) at org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:223) at org.mapstruct.ap.MappingProcessor.processMapperTypeElement(MappingProcessor.java:203)

Not sure what is happening with mapstruct/maven. So need some help to solve this issue.

EDIT:

My pom.xml configuration is similar to the accepted answer suggested in below post. MapStruct and Lombok not working together

I donot have any issues with lombok and mapstruct integration and my only issue is when running maven command like mvn test or mvn install which won't clean the target folder and then mapstruct trying to recreate the implementation files.

happytohelp
  • 305
  • 3
  • 14
  • 1
    Does this answer your question? [MapStruct and Lombok not working together](https://stackoverflow.com/questions/47676369/mapstruct-and-lombok-not-working-together). Check the lombok-mapstruct-binding version – Filip Jan 09 '21 at 12:21

3 Answers3

1

I have been struggling with this problem for a long time and finally found a solution that works for me:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.8.1</version>
  <configuration>
    <source>11</source>
    <target>11</target>
    <generatedSourcesDirectory>${project.build.directory}/generated-sources</generatedSourcesDirectory>
    <annotationProcessorPaths>
      <path>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</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.2.Final</version>
      </path>
    </annotationProcessorPaths>
  </configuration>
</plugin>

I added generatedSourcesDirectory parameter and it started to work. Default value is ${project.build.directory}/generated-sources/annotations and I had other sources generated for example by querydsl outside annotations directory. I decided to remove this path element and it helped.

matejko219
  • 1,601
  • 10
  • 14
0

I donot have any issues with lombok and mapstruct integration and my only issue is when running maven command like mvn test or mvn install which won't clean the target folder and then mapstruct trying to recreate the implementation files.

So, use maven's option clean. It will clear your target folder.
-> mvn clean install for example.

It seems you don't have issue finally...

  • 1
    This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32410198) – Evil Washing Machine Aug 09 '22 at 14:24
0

I had a similar problem. I believe it was caused by multiple plugins generating code, their output directories and maven-compiler-plugin having useIncrementalCompilation set to true. In my case setting useIncrementalCompilation to false worked but it is not recommended.

In my case the plugins I was using and their respective output directories were as follows:

Plugin Output directory
avro-maven-plugin ${project.build.directory}/generated-sources
maven-compiler-plugin ${project.build.directory}/generated-sources/annotations
apt-maven-plugin ${project.build.directory}/generated-sources/java

I suspect the issue was avro-maven-plugin outputting to maven-compiler-plugin output parent directory. Setting each plugin for its own sibling directory worked.

Plugin Output directory
avro-maven-plugin ${project.build.directory}/generated-sources/avro
maven-compiler-plugin ${project.build.directory}/generated-sources/annotations
apt-maven-plugin ${project.build.directory}/generated-sources/java
znaya
  • 321
  • 4
  • 13