Kotlin: why hibernate entity class is final even if I use kotlin-maven plugin all?

Viewed 602

I'm working on kotlin/spring-mvc/jpa project and trying to create lazy ManyToOne association, but it fails. I tried to investigate this problem and after some hours of debugging realized, that my entity classes are final, but as we know, hibernate expects that entity classes are not final, so the proxies can be created for them.

I'm using kotlin-maven-plugin and expect that it will make my entity classes open implicitly, which doesn't happen.

If I explicitly mark my entities and it's properties as open, then lazy feature is working, so it seems that problem only with final status of entity class.

Here is my maven configuration. Some not related dependencies are omited, by I can share it if needed.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://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.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>my.group</groupId>
    <artifactId>my.artifact</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>myappp</name>
    <description>My app</description>

    <properties>
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
        <java.version>11</java.version>
        <kotlin.version>1.4.20</kotlin.version>
    </properties>

    <dependencies
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>com.github.gantsign.maven</groupId>
                <artifactId>ktlint-maven-plugin</artifactId>
                <version>1.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <configuration>
                    <compilerPlugins>
                        <plugin>jpa</plugin>
                        <plugin>no-arg</plugin>
                        <plugin>spring</plugin>
                    </compilerPlugins>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                        <arg>-Xjvm-default=enable</arg>
                    </args>
                </configuration>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>kapt</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>kapt</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/main/kotlin</sourceDir>
                            </sourceDirs>
                            <annotationProcessorPaths>
                                <annotationProcessorPath>
                                    <groupId>com.querydsl</groupId>
                                    <artifactId>querydsl-apt</artifactId>
                                    <version>${querydsl.version}</version>
                                    <classifier>jpa</classifier>
                                </annotationProcessorPath>
                            </annotationProcessorPaths>
                        </configuration>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/test/kotlin</sourceDir>
                                <sourceDir>target/generated-sources/kapt/test</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-noarg</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

Then I run mvnw compile to get generated querydsl QEntities and some other stuff. And start application via Intellij Idea. In debugger I can check that my entity classes are final via Modifier.isFinal(entityClass.getModifiers()).

I assume that it's the problem with kapt, kotlin-maven-plugin and querydsl annotation processor, but can't understand what is happening and how to fix it.

Are there any ideas how to make kotlin-maven-plugin make my entities open and don't throw away querydsl features?

Note: it still generates no-args constructor for entities

1 Answers

Finally find out hot to solve this issue. According to this link kotlin-maven-plugin jpa adds only default constructor for entities, but does not make entities open. So i changed plugin configuration to next one and it worked:

<plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <configuration>
                    <compilerPlugins>
                        <plugin>jpa</plugin>
                        <plugin>all-open</plugin>
                        <plugin>spring</plugin>
                    </compilerPlugins>
                    <pluginOptions>
                        <option>all-open:annotation=javax.persistence.Entity</option>
                        <option>all-open:annotation=javax.persistence.Embeddable</option>
                        <option>all-open:annotation=javax.persistence.MappedSuperclass</option>
                    </pluginOptions>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                        <arg>-Xjvm-default=enable</arg>
                    </args>
                </configuration>
                <executions>
                    <execution>
                        <id>kapt</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>kapt</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/main/kotlin</sourceDir>
                            </sourceDirs>
                            <annotationProcessorPaths>
                                <annotationProcessorPath>
                                    <groupId>com.querydsl</groupId>
                                    <artifactId>querydsl-apt</artifactId>
                                    <version>${querydsl.version}</version>
                                    <classifier>jpa</classifier>
                                </annotationProcessorPath>
                            </annotationProcessorPaths>
                        </configuration>
                    </execution>
                    <execution>
                        <id>compile</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/test/kotlin</sourceDir>
                                <sourceDir>target/generated-sources/kapt/test</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-noarg</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
Related