Spring-data 2.1 get "UnsupportedOperationException: No accessor to set property" with kotlin Spring-data 2.1 get "UnsupportedOperationException: No accessor to set property" with kotlin mongodb mongodb

Spring-data 2.1 get "UnsupportedOperationException: No accessor to set property" with kotlin


Spring Data in 2.1. has changed the way in which it deals with final fields in entities. It no longer uses reflection to override the immutability of the fields, which in general is good. There are a few ways to cope with the problem.

They are described here: https://jira.spring.io/browse/DATACMNS-1374?focusedCommentId=182289&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-182289

Here's what the Spring guys recommend:

  1. Add a @PersistenceConstructor to construct the entity that sets immutable fields.
  2. Add wither methods (MyEntity withXxx(…)) to create a new instance that contains the changed property value.
  3. Alternatively: Use Kotlin's data class feature. This will basically do the same as wither methods.

So for you should work something like this:

@Documentdata class MeAccount(val id: String, val accountEntries: List<Price>) : Setting()


Just for the record because I have not found same question about spring data for apache cassandra and the documentation recommendate using only @Value to avoid boilerplate for inmutable variation of @Data on DTOs, but following that example spring throws UnsupportedOperationException, to solve this the dto must have lombok experimental @Wither to work.

Repository

<T> List<T> findByActive(Class<T> class);

DTO

@Valuepublic class PersonDTO {    private UUID id;    private Boolean active;}

Test - call

    List<PersonDTO> personList  = personService.findByActive(PersonDTO.class);

g

java.lang.UnsupportedOperationException: No accessor to set property private final java.lang.Boolean com.x.dto.PersonDTO.active!    at com.x.dto.PersonDTO_Accessor_y82uew.setProperty(Unknown Source)    at org.springframework.data.cassandra.repository.query.DtoInstantiatingConverter.lambda$convert$0(DtoInstantiatingConverter.java:107)    at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:369)    at org.springframework.data.cassandra.repository.query.DtoInstantiatingConverter.convert(DtoInstantiatingConverter.java:101)    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:224)    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.lambda$and$0(ResultProcessor.java:210)    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:224)    at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:152)    at org.springframework.data.cassandra.repository.query.CassandraQueryExecution$ResultProcessingConverter.convert(CassandraQueryExecution.java:267)    at org.springframework.data.cassandra.repository.query.CassandraQueryExecution$ResultProcessingExecution.execute(CassandraQueryExecution.java:232)    at org.springframework.data.cassandra.repository.query.AbstractCassandraQuery.execute(AbstractCassandraQuery.java:103)    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605)    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595)    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)    at com.sun.proxy.$Proxy145.findByActive(Unknown Source)    at com.x.service.impl.PersonServiceImpl.findByActive(PersonServiceImpl.java:22)    at com.x.PersonRepositoryTest.findByActive(PersonRepositoryTest.java:78)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:498)    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Spring Data for Apache Cassandra - Reference Documentation

Avoid boilerplate code for projection DTOs You can dramatically simplify the code for a DTO by using Project Lombok, which provides an @Value annotation (not to be confused with Spring’s @Value annotation shown in the earlier interface examples). If you use Project Lombok’s @Value annotation, the sample DTO shown earlier would become the following:

@Value@Wither //added - not included in documentationclass NamesOnly {    String firstname, lastname;}

Dynamic Projections So far, we have used the projection type as the return type or element type of a collection. However, you might want to select the type to be used at invocation time (which makes it dynamic). To apply dynamic projections, use a query method such as the one shown in the following example:

Example 86. A repository using a dynamic projection parameter

interface PersonRepository extends Repository<Person, UUID> {  <T> Collection<T> findByLastname(String lastname, Class<T> type);}