Skip to content
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

Redeclared save(Iterable) results in wrong method overload to be invoked eventually [DATACMNS-943] #1398

Closed
spring-projects-issues opened this issue Oct 4, 2016 · 6 comments
Assignees
Labels
in: repository Repositories abstraction type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link

Niranjan Kurra opened DATACMNS-943 and commented

I have upgrade my project from spring boot 1.3.1 to 1.4.1.

After the update the code seems to behave fine in windows with java 1.8.0_45 64bit

But in jenkins server (on linux) with the same java version the code breaks with this exception

org.springframework.beans.NotReadablePropertyException: Invalid property 'id' of bean class [java.util.Arrays$ArrayList]: Could not find field for property during fallback access!
	at org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper.getPropertyValue(DirectFieldAccessFallbackBeanWrapper.java:56)
	at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.getId(JpaMetamodelEntityInformation.java:149)
	at org.springframework.data.repository.core.support.AbstractEntityInformation.isNew(AbstractEntityInformation.java:51)
	at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.isNew(JpaMetamodelEntityInformation.java:225)
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:505)
	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:497)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at 

The invoking call is ```
myRepository.save(Arrays.asList(new MyEntity(1, "foo"), new MyEntity(2, "bar")));


Affects: 1.12.5 (Hopper SR5)

Attachments:

Issue Links:

  • DATACMNS-1023 Redeclared reactive delete(Serializable) results in wrong method overload to be invoked eventually

  • DATACMNS-945 Prefer direct matches on reactive repository query method overloads

Backported to: 1.13 RC1 (Ingalls), 1.12.6 (Hopper SR6), 1.11.7 (Gosling SR7)

1 votes, 5 watchers

@spring-projects-issues
Copy link
Author

Adam Michalik commented

I'm running into the same issue in the following setup.

Spring Boot 1.4.2, Spring Core 4.3.4, Spring Data Commons 1.12.5, Spring Data MongoDB 1.9.5.

public interface IterableSaveRepository extends MongoRepository<Dummy, String> {
    @Override
    <S extends Dummy> List<S> save(Iterable<S> entites);
}
@Document(collection = "dummy")
public class Dummy {
    @Id
    private String id;
    // constructors, getters, setters etc.
}
import java.util.List;

import com.github.fakemongo.Fongo;
import com.mongodb.Mongo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.test.context.junit4.SpringRunner;

import static com.google.common.collect.Lists.*;
import static org.assertj.core.api.Assertions.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class IterableSaveRepositoryTest {

    @Autowired
    private IterableSaveRepository repository;

    @Test
    public void queryByApplicationNumberAndFilePath() {
        repository.save(newArrayList(new Dummy("test")));

        List<Dummy> items = repository.findAll();

        assertThat(items).containsOnly(new Dummy("test"));
    }

    @Configuration
    @EnableMongoRepositories
    static class Config extends AbstractMongoConfiguration {

        @Override
        protected String getDatabaseName() {
            return "test";
        }

        @Override
        public Mongo mongo() throws Exception {
            return new Fongo("inmemory-mongodb").getMongo();
        }
    }
}

The IterableSaveRepository.save(Iterable) is a valid override of MongoRepository.save(Iterable) according to the compiler, but having it there in IterableSaveRepository causes an exception when repository.save(newArrayList(new Dummy("test"))); is invoked:

java.lang.IllegalArgumentException: Target bean is not of type of the persistent entity!

	at org.springframework.util.Assert.isTrue(Assert.java:68)
	at org.springframework.data.mapping.model.BasicPersistentEntity.getIdentifierAccessor(BasicPersistentEntity.java:411)
	at org.springframework.data.repository.core.support.PersistentEntityInformation.getId(PersistentEntityInformation.java:51)
	at org.springframework.data.repository.core.support.AbstractEntityInformation.isNew(AbstractEntityInformation.java:51)
	at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:77)
	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.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy35.save(Unknown Source)
	at test.IterableSaveRepositoryTest.queryByApplicationNumberAndFilePath(IterableSaveRepositoryTest.java:28)
...

When I remove the overriding method from IterableSaveRepository then all works fine.

I've narrowed it down to DefaultRepositoryInformation#matchesGenericType where ResolvableType.forType(type).isAssignableFrom(parameterType) returns true when I have the save(Iterable) overridden in my repository and false otherwise.

My aim was to not inherit from MongoRepository but just from Repository and hand-pick the methods I want to have in my interface

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

Any chance we can get a sample project that's reproducing that error? Ideally something that fails when executing mvn clean test

@spring-projects-issues
Copy link
Author

Adam Michalik commented

Here's a sample project corresponding to my previous comment. Right now the IterableSaveRepositoryTest fails and IterableSaveRepository overrides save(Iterable<S> entites). Comment-out the IterableSaveRepository.save(Iterable) and the test passes

@spring-projects-issues
Copy link
Author

Adam Michalik commented

To be precise, the issue occurs also when the save(Iterable) method does not override a method from a superinterface (MongoRepository in this case) but is simply added to the repository interface that inherits from the basic org.springframework.data.repository.Repository. I've updated the sample project with IterableSaveRepository2(Test) that show this behaviour

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

This should be fixed. Feel free to give the snapshots a try

@spring-projects-issues
Copy link
Author

Adam Michalik commented

Confirmed with 1.12.6.BUILD-SNAPSHOT that it works fine. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: repository Repositories abstraction type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants