MapStruct и Lombok не работают вместе

Используемый технический стек:

Java 8 MapStruct: 1.2.0.Final Lombok: 1.16.18 IDE: IntelliJ - Плагин Lombok уже установлен

  • Первоначально у меня возникли проблемы, когда я удалил геттеры и сеттеры и добавил аннотации @Getter и @Setter, mapstruct не может найти свойство и говорит: Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?
  • Я узнал, что Lombok 1.16.14 или новее вместе с MapStruct 1.2.0.Beta1 или новее совместимы и могут работать вместе, но мои версии новее, чем желаемые, но проблема все еще возникает.
  • Еще одно решение, которое я уже пробовал, - это запуск плагина Lombok Delombok, но все же возникает та же проблема.

Ниже представлены файлы проекта:

Объект Entity: 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;

}

Объект DTO: 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: 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>

Трассировка сборки:

[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

пожалуйста, поделитесь, как я могу заставить это работать, используя вместе Lombok и MapStruct?


person Vivek Gupta    schedule 06.12.2017    source источник


Ответы (10)


Причина, по которой это не работает, заключается в том, что Maven использует только процессор MapStruct, а не Lombok. annotationProcessorPaths сообщает maven, какие процессоры следует использовать.

Delombok ничего не делает, так как вы получаете 2 файла на класс, и я думаю, что компилятор maven их не видит.

У вас есть 2 варианта:

Вариант 1. Добавьте зависимость ломбока в 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>

Вариант 2:

Добавьте mapstruct-processor зависимость к своим зависимостям и удалите annotationProcessorPaths. Таким образом, компилятор maven подберет все обработчики аннотаций, которые находятся в ваших зависимостях.

Я бы посоветовал использовать вариант 1, так как вы можете быть уверены, что не используете в своем коде MapStruct транзитивные зависимости и внутренние классы.

Редактировать:

Чтобы убедиться, что обработка аннотаций IntelliJ также работает, вам нужно будет добавить mapstruct-processor в качестве зависимости provided из-за IDEA-150621. IntelliJ в настоящий момент не использует annotationProcessorPaths от Maven для правильной настройки проекта.

Изменить 2:

Добавьте информацию и комментарий о lombok-mapstruct-binding, необходимых для Lombok 1.18.16.

person Filip    schedule 06.12.2017
comment
Я думаю, что сначала должен быть ломбок, а затем mapstruct-processor - person Don Srinath; 12.11.2018
comment
Порядок не должен иметь значения. Мы явно работали над этим с командой Lombok. - person Filip; 12.11.2018
comment
Я думаю, что эту информацию необходимо добавить в FAQ по mapstructs. Их примерный проект работает без процессоров аннотаций, определенных в разделе сборки mavens, но я думаю, они могли бы упомянуть об этом там (мне потребовалось некоторое время, чтобы найти решение здесь). - person thunderhook; 02.02.2019
comment
Хороший улов @Filip, я поддерживаю этот ответ (y). спасибо - person Farouk; 23.03.2019
comment
Вот полный пример из MapStructs GitHub (Gradle и Maven): github .com / mapstruct / mapstruct-examples / blob / master / - person ysfaran; 07.08.2020
comment
Подтверждено то же поведение на IntelliJ 2020.2.3 на этот раз (не забывайте, что это указано в зависимости) - person pazfernando; 31.10.2020
comment
Спасибо за комментарий о привязке lombok-mapstruct (mapstruct.org/faq/). Доступная версия: 0.2.0. Только одно <!-- This is needed when using Lombok 1.8.16 and above --> = ›<!-- This is needed when using Lombok 1.18.16 and above --> - person Nemolovich; 07.12.2020
comment
lombok-mapstruct-binding решил мои проблемы. Большое спасибо! - person Eduard Dubilyer; 24.01.2021
comment
Вариант 1 решил эту проблему для меня, но только когда я поместил путь mapstruct перед lombok. - person kykrueger; 25.01.2021
comment
добавление Lombok до того, как процессор Mapstruct работал для меня, а также @DonSrinath - person w32-mydoom; 10.03.2021
comment
Кажется, порядок важен. Добавление Lombok до процессора Mapstruct тоже помогло мне. - person mazend; 21.03.2021
comment
Вариант 2 у меня не работает с Lombok 1.18.18 - person heroin; 05.04.2021
comment
Для людей, которые пытались изменить порядок зависимостей, но не удалось решить эту проблему, попробуйте изменить версию lombok. - person Amine ABBAOUI; 13.04.2021
comment
Для нас имел значение порядок путей к процессору аннотаций, иначе mapstruct проигнорировал построитель и попытался использовать недоступный all-args-constructor. Для mapstruct 1.4.2.Final и lombok 1.18.20 нам сначала пришлось использовать mapstruct-processor . порядок lombok и lombok-mapstruct-binding не имел значения. - person thunderhook; 10.05.2021
comment
Для варианта 1 при использовании gradle используйте annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0", чтобы решить проблему. - person Suketu Bhuta; 01.06.2021

На всякий случай, если кто-то ищет, как его настроить с помощью 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'

}
person Alexander    schedule 19.10.2018

Для меня решение было действительно простым.

Порядок процессоров был важен.

В моем случае процессор mapstruct был определен раньше процессора lombok. В случае с плохим порядком mapstruct не генерирует сопоставления, просто создайте экземпляр класса результата (я видел это в сгенерированной реализации).

Конфигурация моего плагина в правильном порядке:

<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>

И, конечно же, нужно добавить зависимости:

<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>
person Alex    schedule 26.11.2020

У меня были похожие проблемы. Оказалось, что моя версия MapStruct устарела!

Я использовал MapStruct версии 1.1.0.Final, но для поддержки Lombok требуется как минимум 1.2.0.Final.

person Laess3r    schedule 23.01.2019

После нескольких попыток в моем проекте Spring Boot Maven следующее, наконец, сработало:

Конфигурация pom.xml:

  1. Раздел свойств:
    <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>
  1. Раздел зависимостей:
    <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>
  1. Раздел плагинов сборки:
    <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>

Надеюсь, это поможет, мой картограф раньше не отображал значения полей, но теперь это сопоставитель между источником и целью + вложенный список элементов в каждом также отображается вместе со значениями полей.

person Mihnea    schedule 25.03.2021

Если кто-то все еще ищет этот ответ, я столкнулся с аналогичной проблемой с интеграцией JOOQ + MapStruct. Ответ - порядок путей имеет значение

  • IntellijIdea 2020.2.3
  • Java 8
  • Spring Framework 2.4.0

Мой фрагмент сборки

<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>
person Hard Coder    schedule 19.11.2020

Mapstruct просто возвращал нулевой экземпляр. Недавно я обновил версию Intellij до 2020.3 и весеннюю загрузку 2.4.0 и попал в эту ситуацию.

Когда я изменил весеннюю версию на 2.3.o.RELEASE, после компиляции я увидел, что mapstruct правильно строит сопоставления.

Просматривая сообщение, которое недавно обновил mapstruct ... но это займет время ... :) Итак, сейчас я перешел от maven к проекту Gradle, и все работает абсолютно нормально ... звучит странно, но это правда ...

Буду благодарен, если кто-нибудь опубликует, какая именно проблема и каково ее решение.

person Kartikeswar Mallik    schedule 10.12.2020

Для проблем после обновления Intellij до версии 2020.3 у меня сработало следующее решение. Используйте версию lombok: 1.18.16, привязку lombok-mapstruct: 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>

Измените порядок путей к плагинам lombok и mapstruct в разделе обработки аннотаций плагинов:

<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>
person Ankit    schedule 29.12.2020

Если кто-нибудь читает это при использовании последних версий библиотек Lombok и Mapstruct: -

Если вы используете Lombok 1.18.16 или новее, вам также необходимо добавить lombok-mapstruct-binding, чтобы Lombok и MapStruct работали вместе.

https://mapstruct.org/faq/#Can-I-use-MapStruct-toght-with-Project-Lombok

person firstpostcommenter    schedule 10.07.2021

Я согласен с тем, что порядок играет свою роль также при использовании gradle. В моем случае это не удалось, как только я добавил subprojects { ... dependencyManagement{}} к родительскому build.gradle в настройке с несколькими модулями.

person chris polzer    schedule 03.12.2020