I have a multiplatform project with a modal class, User.
User.kt
class User {
val id = -1
val username = ""
val age = -1
val nickname = ""
}
I also have expected and actual annotations
Annotation.kt [Common Module]
expect annotation class NodeEntity
expect annotation class Id
expect annotation class GeneratedValue
More over, I have their actual implementation
Annotation.kt [JVM Module]
actual typealias ValueFor = org.neo4j.ogm.annotation.ValueFor
actual typealias NodeEntity = org.neo4j.ogm.annotation.NodeEntity
actual typealias Id = org.neo4j.ogm.annotation.Id
actual typealias GeneratedValue = org.neo4j.ogm.annotation.GeneratedValue
actual typealias Relationship = org.neo4j.ogm.annotation.Relationship
I then went back and annotated my User.kt
@NodeEntity
class User {
@Id
@GeneratedValue
val id = -1
val username = ""
val age = -1
val nickname = ""
}
But When I compile it, I get this error
Task :compileKotlinJvm FAILED
e: ...User.kt: (13, 2): This class does not have a constructor
e: ...User.kt: (21, 6): This class does not have a constructor
e: ...User.kt: (22, 6): This class does not have a constructor
What Am I doing wrong?
N:B. Attempts done
FYI: My build.gradle already has the noArg in place, so that the User.kt class is compiled with a no argument public constructor
Your expect annotations probably need explicit parenthesis.
expect annotation class SharedImmutable()
actual typealias SharedImmutable = kotlin.native.SharedImmutable
I experienced a similar issue, but seemingly like the OP, I already included the explicit parenthesis. My particular issue had to do with the Java Library, in the Java Source Set, not being available to another Gradle Sub-project that was depending on it.
TL;DR
Assert that you are properly exposing the platform-specific dependencies. For instance, properly using implementation and api in the build.gradle files.
Elaborating on my scenario
I had a Gradle multi-project build:
Project
AppSubProject
LibrarySubProject
Where AppSubProject depended on LibrarySubProject. Both Gradle Sub-projects were Kotlin Multi-platform Modules.
In LibrarySubProject, there was an exposed Annotation Class:
Common Source Set:
expect annotation class Inject()
JVM Source Set:
actual typealias Inject = javax.inject.Inject
The Kotlin Common Inject annotation was available to AppSubProject since it depended on the LibrarySubProject.
AppSubProject/build.gradle:
...
commonMain {
dependencies {
implementation project(":LibrarySubProject")
...
The Cause of the Issue
In the LibrarySubProject/build.gradle file I wasn't exposing the JVM dependency:
...
jvmMain {
dependencies {
implementation "javax.inject:javax.inject:1"
...
As you can see, I was using implementation instead of api. So when I used the annotation on a constructor of a class in AppSubProject:
class Example @Inject constructor()
and when I built the AppSubProject, it couldn't resolve the JVM dependency, and was cryptically giving me the following error:
e: Example.kt: This class does not have a constructor
The Solution
The solution was simply to expose the JVM dependency so that it could be resolved in the other module. So changing the implementation to api resolved the issue.
...
jvmMain {
dependencies {
api "javax.inject:javax.inject:1"
...
Summation
If you experience this issue, assert the following: