-
Notifications
You must be signed in to change notification settings - Fork 668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generated Kotlin PropertyAccessor uses wrong copy method [DATACMNS-1391] #1827
Comments
Oliver Drotbohm commented Looks like we need to be more defensive about the |
Marian Jureczko commented I am not sure what exactly was going on there. When decompiling CatalogueTags_Accessor_jcjqjz.setProperty(), there was nothing wrong, i.e. the correct copy method was called. But, with a black box approach, when there is an additional copy method with different arguments (DateTimeRange in my case), the additional one is called in place of the data class default one (accepting all class fields) when trying to set version of a new entity to 0. At least that is the only explanation I could come up with to justify the unsuccessful Int to DateTimeRange casting |
Mark Paluch commented The culprit here is an optimization that we made for single-property classes (value types). We attempt to find a We should guard the optimization with a check on the parameter type and make sure the entity consists of a single property to use the |
Mark Paluch commented I moved this ticket to Spring Data Commons as the fix will happen here |
Mark Paluch commented I pushed a change to a bugfix branch and we have a snapshot build available It would be cool if you could give the snapshots a try (use version |
Marcin Sokołowski commented Another problem occurred, I've prepared some minimal working example here: https://github.com/sokolek/DATACMNS-1391 Method org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory#findPublicCopyMethod:1466 sometimes picks In result following Exception is thrown:
java.lang.RuntimeException: java.lang.IllegalArgumentException: Cannot resolve parameter name id to a index in method copy!
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.createAccessorClass(ClassGeneratingPropertyAccessorFactory.java:206)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.potentiallyCreateAndRegisterPersistentPropertyAccessorClass(ClassGeneratingPropertyAccessorFactory.java:190)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.getPropertyAccessor(ClassGeneratingPropertyAccessorFactory.java:100)
at org.springframework.data.mapping.model.BasicPersistentEntity.getPropertyAccessor(BasicPersistentEntity.java:455)
at org.springframework.data.mapping.model.PersistentEntityIsNewStrategy.lambda$new$0(PersistentEntityIsNewStrategy.java:48)
at org.springframework.data.mapping.model.PersistentEntityIsNewStrategy.isNew(PersistentEntityIsNewStrategy.java:95)
at org.springframework.data.mapping.model.BasicPersistentEntity.isNew(BasicPersistentEntity.java:483)
at org.springframework.data.repository.core.support.PersistentEntityInformation.isNew(PersistentEntityInformation.java:44)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:80)
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.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608)
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:185)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.MethodInvocationValidator.invoke(MethodInvocationValidator.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy94.save(Unknown Source)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:338)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:197)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy94.save(Unknown Source)
at com.mytest.MyTest.send new dtc product(MyTest.kt:39)
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:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
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.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: Cannot resolve parameter name id to a index in method copy!
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$KotlinCopyByProperty.findIndex(ClassGeneratingPropertyAccessorFactory.java:1562)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$KotlinCopyByProperty.<init>(ClassGeneratingPropertyAccessorFactory.java:1549)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$KotlinDefaultCopyMethod.forProperty(ClassGeneratingPropertyAccessorFactory.java:1531)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.visitKotlinCopy(ClassGeneratingPropertyAccessorFactory.java:1103)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.visitSetProperty0(ClassGeneratingPropertyAccessorFactory.java:1014)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.visitSetPropertySwitch(ClassGeneratingPropertyAccessorFactory.java:986)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.visitSetProperty(ClassGeneratingPropertyAccessorFactory.java:936)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.generateBytecode(ClassGeneratingPropertyAccessorFactory.java:350)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory$PropertyAccessorClassGenerator.generateCustomAccessorClass(ClassGeneratingPropertyAccessorFactory.java:326)
at org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory.createAccessorClass(ClassGeneratingPropertyAccessorFactory.java:204)
... 73 more |
Mark Paluch commented Thanks a lot. I'll have a look |
Mark Paluch commented I pushed another change to fix the issue. Care to give it a spin? ( |
Marcin Sokołowski commented Thanks for quick response. It works for the current setup, but it won't if the name of the arguments in overloaded copy method will be the same as the actual property names. See current master on https://github.com/sokolek/DATACMNS-1391/ The problem is caused by the logic in filtering at Let me ask just one more question, why not just always use |
Mark Paluch commented We have different approaches and cases where we need to distinguish between the public and the synthetic methods. Using reflection, we're using Kotlin's reflection API to invoke methods and to let Kotlin reflection apply defaulting. To do so, we need to lookup a So we need to find the generated |
Mark Paluch commented We aligned the copy method discovery to use the primary constructor signature. A new build is available |
Marcin Sokołowski commented Now it works like a charm |
Mark Paluch commented Thanks a lot for verifying the patch. Creating a pull request so we can include the change in our upcoming release |
Marian Jureczko opened DATACMNS-1391 and commented
Given (in kotlin):
When:
Then:
Affects: 2.1 RC2 (Lovelace)
Attachments:
Referenced from: pull request #312
1 votes, 4 watchers
The text was updated successfully, but these errors were encountered: