Mapstruct - 找不到符号 [Kotlin + Maven]

Chu*_*k94 5 maven kotlin mapstruct

当我运行命令时出现以下错误mvn clean install

[ERROR] /Users/xxx/xxx/xxx/xxx.xxx/target/generated-sources/kapt/compile/com/xxx/xxx/xxx/xxx/DataMapperImpl.java:[10,40] cannot find symbol
[ERROR]   symbol: class DataMapperDecorator
[ERROR] /Users/xxx/xxx/xxx/xxx.xxx/target/generated-sources/kapt/compile/com/xxx/xxx/xxx/xxx/DataMapperImpl.java:[10,74] cannot find symbol
[ERROR]   symbol: class DataMapper
[ERROR] /Users/xxx/xxx/xxx/xxx.xxx/xxx/generated-sources/kapt/compile/com/xxx/xxx/xxx/api/DataMapperImpl.java:[12,19] cannot find symbol
[ERROR]   symbol:   class DataMapper
[ERROR]   location: class com.xxx.xxx.xxx.xxx.DataMapperImpl
Run Code Online (Sandbox Code Playgroud)

似乎在 mapstruct 生成DataMapperImpl.java类后,它无法找到类DataMapperDataMapperDecoretor

与mapstruct相关的代码在一个xxx.kt文件中:

//Other stuff
...

@Mapper
@DecoratedWith(DataMapperDecorator::class)
interface DataMapper {
    @Mappings(
        Mapping(source = "data.value", target = "dataValue"),
        Mapping(source = "data.current.value", target = "currentValue"),
    )
    fun toDto(data: Data) : RefDataDto
}

abstract class DataMapperDecorator : DataMapper {
    @Autowired
    private val delegate: DataMapper? = null

    override fun toDto(data: Data): dataDto {
        val dataDto = delegate!!.toDto(data)
        dataDto.primaryValue = data.primaryValue?.let { CurrencyUtil.toMajor(it) }
        return dataDto
    }
}
Run Code Online (Sandbox Code Playgroud)

关于pom我在根文件中的文件:

...
    <properties>
    ... 
        <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
    </properties>
...
Run Code Online (Sandbox Code Playgroud)

这是pom我使用 mapstruct 的模块的:

...
        <build>
            <finalName>${project.artifactId}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>compile</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                            <configuration>
                                <sourceDirs>
                                    <sourceDir>src/main/kotlin</sourceDir>
                                </sourceDirs>
                            </configuration>
                        </execution>
                        <execution>
                            <id>test-compile</id>
                            <goals>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>kapt</id>
                            <goals>
                                <goal>kapt</goal>
                            </goals>
                            <configuration>
                                <annotationProcessorPaths>
                                    <annotationProcessorPath>
                                        <groupId>org.mapstruct</groupId>
                                        <artifactId>mapstruct-processor</artifactId>
                                        <version>${org.mapstruct.version}</version>
                                    </annotationProcessorPath>
                                </annotationProcessorPaths>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                ...
            </plugins>
...
Run Code Online (Sandbox Code Playgroud)

我用点隐藏了文件的某些部分,并且我没有使用 Lombok 项目(我看到了与它相关的相同问题,我们您正在尝试一起使用这些项目)。

更新1

我注意到该错误与以下事实有关:从生成的类中,DataMapperImpl.java该生成的类应使用的类所在的包不可见。事实上我看到了这个错误:

[ERROR] /Users/xxx/xxx/xxx/xxx.xxx/xxx/generated-sources/kapt/compile/com/xxx/xxx/xxx/xxx/RefDataMapperImpl.java:[3,47] package com.my.package.application.domain does not exist
Run Code Online (Sandbox Code Playgroud)

当然这个包是存在的!

更新2

我正在继续调查这个问题。我试图让删除 DataMapperDecorator 变得更简单,并将DataMapperDataDataDto类放在同一个文件中。cannot find symbol: class所有三个类仍然存在相同的错误。我不确定这是否与 DataMapperImpl (生成的类)中没有导入这些类这一事实有关。有一些仅适用于标准 java 库的导入,例如:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
import javax.annotation.processing.Generated;
Run Code Online (Sandbox Code Playgroud)

编辑1

从日志中我还可以看到以下警告:

[WARNING] 'tools.jar' was not found, kapt may work unreliably
Run Code Online (Sandbox Code Playgroud)

更新3

如果没有(使用 IntelliJ IDEA)下的 mapstruct,target->classes我可以看到我的项目的类。另一方面,当我引入 Mapstruct 时,我看到的是 Mapstruct 类是在下面生成的,target->generated-sources->kapt->compile但在下面target->classes我看不到其他类。映射结构类是否会比项目的其他类更早生成,导致编译器找不到Data,DataDto类?

Chu*_*k94 10

解决了!

该问题是由于编译顺序造成的。默认情况下,java 编译器在 kotlin 编译器之前执行。这就是为什么 mapstruct 生成的代码无法找到 kotlin 类的原因。因此需要先编译koltin类,然后再编译java类。

“我们的想法是禁用默认编译执行并引入我们自己的编译器来控制目标的执行顺序,这样我们就可以在 java 编译器之前运行 kotlin 编译器。”

https://discuss.kotlinlang.org/t/maven-compiler-plugin-question/5260/4

所以解决方案是引入maven插件:

https://kotlinlang.org/docs/maven.html#compile-kotlin-and-java-sources

所以我将其添加到我的 pom 文件中:

             <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <executions>
                    <!-- Replacing default-compile as it is treated specially by maven -->
                    <execution>
                        <id>default-compile</id>
                        <phase>none</phase>
                    </execution>
                    <!-- Replacing default-testCompile as it is treated specially by maven -->
                    <execution>
                        <id>default-testCompile</id>
                        <phase>none</phase>
                    </execution>
                    <execution>
                        <id>java-compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>java-test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
Run Code Online (Sandbox Code Playgroud)