Reputation: 829
I'm having the following error when I run the command 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
It seems that after mapstruct has generated the DataMapperImpl.java
class it is not able to find the classes DataMapper
and DataMapperDecoretor
.
The code related to mapstruct is in a xxx.kt
file:
//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
}
}
Regarding the pom
files I have in the root file:
...
<properties>
...
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
</properties>
...
and this is the pom
of the module where I'm using 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>
...
I hid some part of the files with dots and I'm not using the project Lombok (I saw same problems related with it we you are trying to use these projects together).
UPDATE 1:
I noticed that the error is related to the fact that from the generated class DataMapperImpl.java
the package where there are the classes that this generated class should use is not visible. Indeed I see this error:
[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
and of course this package exist!
UPDATE 2:
I'm continuing to investigate on this issue. I tried to make it simpler deleting the DataMapperDecorator and put the DataMapper
, the Data
and the DataDto
class in the same file. Still the same error cannot find symbol: class
for all the three classes. I'm not sure if this is related to the fact that in the DataMapperImpl (the generated class) doesn't have the import of these classes. There are imports just for the standard java libraries such as:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
import javax.annotation.processing.Generated;
EDIT 1:
From the log I can also see the following warning:
[WARNING] 'tools.jar' was not found, kapt may work unreliably
UPDATE 3:
Without mapstruct under target->classes
(using IntelliJ IDEA) I can see the classes of my project. On the other hand when I have introduced mapstruct what I'm seeing is that the mapstruct classes are generated under target->generated-sources->kapt->compile
but under target->classes
I don't see the other classes. Could the mapstruct classes be generated earlier than the other classes of my project causing the compiler to not find the Data
, DataDto
classes?
Upvotes: 5
Views: 8699
Reputation: 6776
I just had to do the following change in kotlin-maven-plugin
.
From:
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
To:
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
Upvotes: 1
Reputation: 63
Addition to @SGiux answer. The order of plugins in pom also matters:
Upvotes: 1
Reputation: 829
SOLVED!
The problem was due to the order of the compilation. By default the java compiler is executed before the kotlin compiler. That why the code generated by mapstruct wasn't able to find the kotlin classes. So it is needed to compiler the koltin classes before and then the java classes.
"The idea is to disable default compile execution and introduce our own to get control over the order in which goals are executed, so that we could run kotlin compiler before java compiler."
https://discuss.kotlinlang.org/t/maven-compiler-plugin-question/5260/4
So the solution came introducing the maven plugin:
https://kotlinlang.org/docs/maven.html#compile-kotlin-and-java-sources
So I added this to my pom file:
<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>
Upvotes: 10
Reputation: 21403
I am not sure how Kotlin works with multiple classes in one source file.
What I would suggest is that you use dedicated files for the decorator and the mapper. That way MapStruct will create the correct code.
MapStruct is a Java annotation processor, we do not know anything about the Kotlin structure. It seems like the packages returned by the java annotation processing API are not correct.
Upvotes: 0