micronaut-projects / micronaut-data

Ahead of Time Data Repositories
Apache License 2.0
467 stars 198 forks source link

Using reserved keyword (but escaped) as property name throws cryptic exception #963

Open asarkar opened 3 years ago

asarkar commented 3 years ago

Task List

Actual Behaviour

Given the following Kotlin class:

@Entity
@Table(name = "test_suite")
data class TestSuite(
    @Id
    @GeneratedValue
    val id: Long = 0,
    // other properties
    val `package`: String? = null
)

Following exception is thrown at runtime.

io.micronaut.data.exceptions.MappingException: Constructor argument [p6_1743952419] for type [com.mycompany.persistence.TestSuite] must have an associated getter
    at io.micronaut.data.model.runtime.RuntimePersistentEntity.<init>(RuntimePersistentEntity.java:105)
    at io.micronaut.data.model.runtime.RuntimePersistentEntity.<init>(RuntimePersistentEntity.java:55)

Turns out renaming the package field to something else magically fixes this problem.

Expected Behaviour

It's completely legit in Kotlin to use a reserved keyword for a variable name as long as it's escaped, so this code should work. Also, there's no way to actually tell what the real issue is based on the error message, so the message should be improved.

graemerocher commented 3 years ago

Not sure if this is fixable to be honest. The name supplied by KAPT is p6_1743952419 and it provides no way to figure out the real name of the property.

asarkar commented 3 years ago

@graemerocher Any idea how the exception can be avoided in the first place?

graemerocher commented 3 years ago

Well we could maybe fail compilation if we detect parameters that match the pattern, but seems like a hack.

One option would be to have some way to customise the getter/setter name for a property like:

@BeanProperty(getter="getPackage")
val `package`: String? = null

Though it seems overkill just to solve this problem which can be fixed simply by doing something like:

@Entity
@Table(name = "test_suite")
data class TestSuite(
    @Id
    @GeneratedValue
    val id: Long = 0,
    // other properties
    @Column(name="package")
    val packageName: String? = null
)

Ultimately it is not our fault Kotlin allows crazy things Java doesn't :)