micronaut-data icon indicating copy to clipboard operation
micronaut-data copied to clipboard

Error when kotlin data class contains a property start with "is"

Open todoubaba opened this issue 3 years ago • 11 comments

Task List

  • [x] Steps to reproduce provided
  • [x] Stacktrace (if present) provided
  • [ ] Example that reproduces the problem uploaded to Github
  • [ ] Full description of the issue provided (see below)

Steps to Reproduce

  1. Create a kotlin app
  2. Add entity, repository, controller class
@Entity
data class Room(
    @Id
    var id: Int,
    var name: String,
    var isPublic: Boolean,
)

@Repository
interface RoomRepository: JpaRepository<Room, Int>

@Controller("/rooms")
class RoomController(private val roomRepository: RoomRepository) {
    @Get
    fun index(): List<Room> {
        return roomRepository.findAll()
    }
}
  1. Request the endpoint
curl localhost:5000/rooms
{"message":"Internal Server Error: Constructor argument [isPublic] for type [upgrade.kotlin.Room] must have an associated getter","_links":{"self":{"href":"/rooms","templated":false}}}

Expected Behaviour

No exception. It works in Micronaut 2.3.4.

Actual Behaviour

14:36:59.149 [default-nioEventLoopGroup-1-5] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Constructor argument [isPublic] for type [upgrade.kotlin.Room] must have an associated getter
io.micronaut.data.exceptions.MappingException: Constructor argument [isPublic] for type [upgrade.kotlin.Room] 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)
	at io.micronaut.data.runtime.support.DefaultRuntimeEntityRegistry$1.<init>(DefaultRuntimeEntityRegistry.java:73)
	at io.micronaut.data.runtime.support.DefaultRuntimeEntityRegistry.newEntity(DefaultRuntimeEntityRegistry.java:73)
	at io.micronaut.data.runtime.support.DefaultRuntimeEntityRegistry.getEntity(DefaultRuntimeEntityRegistry.java:64)
	at io.micronaut.data.hibernate.event.EventIntegrator.lambda$integrate$b7f772e6$1(EventIntegrator.java:152)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
	at org.hibernate.internal.FastSessionServices.firePostLoadEvent(FastSessionServices.java:295)
	at org.hibernate.engine.internal.TwoPhaseLoad.postLoad(TwoPhaseLoad.java:512)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1231)
	at org.hibernate.loader.Loader.processResultSet(Loader.java:1001)
	at org.hibernate.loader.Loader.doQuery(Loader.java:959)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
	at org.hibernate.loader.Loader.doList(Loader.java:2850)
	at org.hibernate.loader.Loader.doList(Loader.java:2832)
	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2664)
	at org.hibernate.loader.Loader.list(Loader.java:2659)
	at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400)
	at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
	at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1414)
	at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1625)
	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1593)
	at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.list(CriteriaQueryTypeQueryAdapter.java:96)
	at io.micronaut.data.hibernate.operations.HibernateJpaOperations.lambda$findAll$2(HibernateJpaOperations.java:267)
	at io.micronaut.transaction.support.AbstractSynchronousTransactionManager.executeRead(AbstractSynchronousTransactionManager.java:155)
	at io.micronaut.data.hibernate.operations.HibernateJpaOperations.findAll(HibernateJpaOperations.java:262)
	at io.micronaut.data.runtime.intercept.DefaultFindAllInterceptor.intercept(DefaultFindAllInterceptor.java:63)
	at io.micronaut.data.runtime.intercept.DefaultFindAllInterceptor.intercept(DefaultFindAllInterceptor.java:36)
	at io.micronaut.data.intercept.DataIntroductionAdvice.intercept(DataIntroductionAdvice.java:80)
	at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:96)
	at io.micronaut.validation.ValidatingInterceptor.intercept(ValidatingInterceptor.java:137)
	at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:96)
	at upgrade.kotlin.RoomRepository$Intercepted.findAll(Unknown Source)
	at upgrade.kotlin.RoomController.index(RoomController.kt:10)
	at upgrade.kotlin.$RoomControllerDefinition$$exec1.invokeInternal(Unknown Source)
	at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:151)
	at io.micronaut.context.DefaultBeanContext$4.invoke(DefaultBeanContext.java:482)
	at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:255)
	at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:118)
	at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$12(RoutingInBoundHandler.java:1397)
	at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:35)
	at io.reactivex.Flowable.subscribe(Flowable.java:14935)
	at io.reactivex.Flowable.subscribe(Flowable.java:14882)
	at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:57)
	at io.reactivex.Flowable.subscribe(Flowable.java:14935)
	at io.reactivex.Flowable.subscribe(Flowable.java:14882)
	at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:42)
	at io.reactivex.Flowable.subscribe(Flowable.java:14935)
	at io.reactivex.Flowable.subscribe(Flowable.java:14882)
	at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:57)
	at io.reactivex.Flowable.subscribe(Flowable.java:14935)
	at io.reactivex.Flowable.subscribe(Flowable.java:14882)
	at io.micronaut.http.server.context.ServerRequestContextFilter.lambda$doFilter$0(ServerRequestContextFilter.java:62)
	at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
	at io.reactivex.Flowable.subscribe(Flowable.java:14935)
	at io.reactivex.Flowable.subscribe(Flowable.java:14885)
	at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildExecutableRoute$8(RoutingInBoundHandler.java:1102)
	at io.micronaut.web.router.DefaultUriRouteMatch$1.execute(DefaultUriRouteMatch.java:80)
	at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:118)
	at io.micronaut.http.server.netty.RoutingInBoundHandler.handleRouteMatch(RoutingInBoundHandler.java:726)
	at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:588)
	at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:151)
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:102)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.micronaut.http.netty.stream.HttpStreamsHandler.channelRead(HttpStreamsHandler.java:199)
	at io.micronaut.http.netty.stream.HttpStreamsServerHandler.channelRead(HttpStreamsServerHandler.java:121)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
	at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
	at io.netty.handler.codec.http.HttpServerKeepAliveHandler.channelRead(HttpServerKeepAliveHandler.java:64)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.flow.FlowControlHandler.dequeue(FlowControlHandler.java:200)
	at io.netty.handler.flow.FlowControlHandler.channelRead(FlowControlHandler.java:162)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

Environment Information

  • Operating System: Windows 10
  • Micronaut Version: 2.4.0
  • JDK Version: 1.8

todoubaba avatar Mar 11 '21 06:03 todoubaba

To reproduce the issue, insert some data to the room table。 Temp workaround is moving the isPublic constructor parameter to the class body:

@Entity
data class Room(
    @Id
    var id: Int,
    var name: String,
) {
    var isPublic: Boolean = true
}

todoubaba avatar Mar 11 '21 06:03 todoubaba

This also happens for non data classes. The following will cause the same issue.

@Entity
class SomeClass(
  @Id
  val id: Long,
  isPublic: Boolean,
 ) {
  var isPublic: Boolean = isPublic
  set(isPublic) = ...
}

And can be workaround when renaming the constructor parameter from isPublic to canBePublic

@Entity
class SomeClass(
  @Id
  val id: Long,
  canBePublic: Boolean,
 ) {
  var isPublic: Boolean = canBePublic
    set(isPublic) = ...
}

eratio08 avatar Apr 09 '21 07:04 eratio08

I just hit this the other day. Here is a quick workaround if you hadn't already figured it out.

@Entity
data class Room(
    @Id
    var id: Int,
    var name: String,
   @field:MappedProperty("isPublic")
    var public: Boolean,
)

charlie-harvey avatar Apr 13 '21 20:04 charlie-harvey

Just for reference, the same issue in different module: https://github.com/micronaut-projects/micronaut-openapi/issues/616

morki avatar Jan 18 '22 14:01 morki

I just got the same issue. Just keeping the issue active.

ggwzrd avatar Feb 04 '22 10:02 ggwzrd

i can confirm, issue still exists on micronaut 3.3.0 and micronaut-data 3.2.2

dobe avatar Feb 09 '22 14:02 dobe

@graemerocher is this something that will be resolved by KSP?

morki avatar Feb 09 '22 14:02 morki

A workaround for this is:

@get:JvmName("getIsImportant")
val isImportant: Boolean

rawilder avatar Mar 14 '22 20:03 rawilder

@rawilder Very useful workaround—thanks for posting that!

barm avatar Mar 15 '22 01:03 barm

bump

vinmorel avatar Mar 17 '22 16:03 vinmorel

Attempted fix and discussion about such going on here: https://github.com/micronaut-projects/micronaut-core/pull/7058

rawilder avatar Mar 17 '22 17:03 rawilder