【问题标题】:Mapstruct - cannot find symbol [Kotlin + Maven]Mapstruct - 找不到符号 [Kotlin + Maven]
【发布时间】:2021-10-19 11:59:10
【问题描述】:

运行命令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

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

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

...
    <properties>
    ... 
        <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
    </properties>
...

这是我正在使用 mapstruct 的模块的pom

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

我用点隐藏了文件的某些部分,并且我没有使用 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

当然这个包是存在的!

更新 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;

编辑 1

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

[WARNING] 'tools.jar' was not found, kapt may work unreliably

更新 3

target-&gt;classes 下没有 mapstruct(使用 IntelliJ IDEA)我可以看到我的项目的类。另一方面,当我介绍 mapstruct 时,我看到的是 mapstruct 类是在 target-&gt;generated-sources-&gt;kapt-&gt;compile 下生成的,但在 target-&gt;classes 下我看不到其他类。是否会比我项目的其他类更早生成 mapstruct 类,导致编译器找不到 DataDataDto 类?

【问题讨论】:

    标签: maven kotlin mapstruct


    【解决方案1】:

    已解决!

    问题出在编译顺序上。默认情况下,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>
    

    【讨论】:

      【解决方案2】:

      我不确定 Kotlin 如何在一个源文件中处理多个类。

      我的建议是为装饰器和映射器使用专用文件。这样 MapStruct 将创建正确的代码。

      MapStruct 是一个 Java 注释处理器,我们对 Kotlin 结构一无所知。 java注解处理API返回的包好像不正确。

      【讨论】:

      • mmh 我试图将它们放在两个不同的文件中,但我对这些类有相同的错误。实际上我对 Data 和 DataDto 有同样的错误(找不到符号错误)
      猜你喜欢
      • 1970-01-01
      • 2014-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      相关资源
      最近更新 更多