spring-data-commons icon indicating copy to clipboard operation
spring-data-commons copied to clipboard

Projection is not allowed if filter criteria fields do not exist in the projection DTO kotlin data classes

Open sunny-chung opened this issue 9 months ago • 0 comments

I have a Spring data repository like this:

interface ChatMessageRepository : BaseRepository<ChatMessage> {

    suspend fun findByChannelIdAndActive(
        channelId: String,
        active: Boolean
    ): List<ChatMessageResource>
}

@NoRepositoryBean
interface BaseRepository<T : BaseEntity> : CoroutineCrudRepository<T, String> {
    suspend fun findByActive(isActive: Boolean): List<T>

    suspend fun findByIdAndActive(id: String, isActive: Boolean): T?

    suspend fun countByIdAndActive(id: String, isActive: Boolean): Int
}

Classes like this:

@Table(name = "chat__message")
data class ChatMessage(
    val channelId: String,
    val senderId: String,
    val content: String
) : BaseEntity()

abstract class BaseEntity {
    @Id
    var id: String = UUID.randomUUID().toString()

    var isActive: Boolean = true

    @CreatedDate
    var createAt: Instant? = null
}

data class ChatMessageResource(
    val senderId: String,
    val content: String,
    val createAt: Instant
)

Exception would be thrown on Spring Boot startup:

2023-09-26T11:55:38.434+08:00 ERROR [,,] 1 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'messageApi': Unsatisfied dependency expressed through field 'chatMessageRepository': Error creating bean with name 'chatMessageRepository' defined in com.example.repository.ChatMessageRepository defined in @EnableR2dbcRepositories declared on R2dbcRepositoriesAutoConfigureRegistrar.EnableR2dbcRepositoriesConfiguration: Could not create query for public abstract java.lang.Object com.example.repository.ChatMessageRepository.findByChannelIdAndActive(java.lang.String,boolean,kotlin.coroutines.Continuation); Reason: Failed to create query for method public abstract java.lang.Object com.example.repository.ChatMessageRepository.findByChannelIdAndActive(java.lang.String,boolean,kotlin.coroutines.Continuation); No property 'channelId' found for type 'ChatMessageResource'
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:716) ~[spring-beans-6.0.11.jar!/:6.0.11]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:696) ~[spring-beans-6.0.11.jar!/:6.0.11]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.0.11.jar!/:6.0.11]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:483) ~[spring-beans-6.0.11.jar!/:6.0.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1416) ~[spring-beans-6.0.11.jar!/:6.0.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:597) ~[spring-beans-6.0.11.jar!/:6.0.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.11.jar!/:6.0.11]

...

Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract java.lang.Object com.example.repository.ChatMessageRepository.findByChannelIdAndActive(java.lang.String,boolean,kotlin.coroutines.Continuation); No property 'channelId' found for type 'ChatMessageResource'
	at org.springframework.data.r2dbc.repository.query.PartTreeR2dbcQuery.<init>(PartTreeR2dbcQuery.java:74) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
	at org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory$R2dbcQueryLookupStrategy.resolveQuery(R2dbcRepositoryFactory.java:179) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:111) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	... 50 common frames omitted
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'channelId' found for type 'ChatMessageResource'
	at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:90) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:405) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:381) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:334) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na]
	at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:316) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:299) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:242) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
	at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:243) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:372) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
	at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:373) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:96) ~[spring-data-commons-3.1.2.jar!/:3.1.2]
	at org.springframework.data.r2dbc.repository.query.PartTreeR2dbcQuery.<init>(PartTreeR2dbcQuery.java:70) ~[spring-data-r2dbc-3.1.2.jar!/:3.1.2]
	... 52 common frames omitted

If I do not use projection, the application is working fine.

Please let me know if anything I could help.

Versions: Kotlin 1.8.22 JVM Target 17 Spring Data Commons 3.1.2 Spring Data R2dbc 3.1.2

sunny-chung avatar Sep 26 '23 04:09 sunny-chung