Skip to content

Thread-safetey issue in annotation detection in BasicPersistentEntity [DATACMNS-1210] #1649

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

Closed
spring-projects-issues opened this issue Nov 11, 2017 · 1 comment
Assignees
Labels
in: mapping Mapping and conversion infrastructure in: repository Repositories abstraction type: bug A general bug

Comments

@spring-projects-issues
Copy link

Philipp Röben opened DATACMNS-1210 and commented

I found the problem using spring-data-redis but it I think it could apply to all spring-data projects
I was not able to file a bug in spring-data-mapping because there was no assignee.

You can reproduce the issue easily:

@Test
    void testThreadsafe(@Autowired MyPOJORepository repository){
        List<MyPOJO> all = new ArrayList<>();
        for(int i=0; i<10; i++){
            MyPOJO pojo = new MyPOJO();
            pojo.setMyProp("test"+i);
            all.add(pojo);
        }
        all.parallelStream().forEach( p -> repository.save(p));
    }

MyPOJO is a normal POJO annotated with Redis/Spring Data annotations:

@RedisHash("myPojo")
public class MyPOJO {
    @Id
    private String myProp;
... rest omitted

the Repository is quite simple:

public interface MyPOJORepository extends CrudRepository<MyPOJO, String> {}

When firing up the test, I get:

Caused by: java.util.ConcurrentModificationException
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1139)
	at org.springframework.data.mapping.model.BasicPersistentEntity.doFindAnnotation(BasicPersistentEntity.java:394)
	at org.springframework.data.mapping.model.BasicPersistentEntity.findAnnotation(BasicPersistentEntity.java:379)
	at org.springframework.data.redis.core.mapping.RedisMappingContext$ConfigAwareTimeToLiveAccessor.resolveDefaultTimeOut(RedisMappingContext.java:293)
	at org.springframework.data.redis.core.mapping.RedisMappingContext$ConfigAwareTimeToLiveAccessor.getTimeToLive(RedisMappingContext.java:220)
	at org.springframework.data.redis.core.convert.MappingRedisConverter.write(MappingRedisConverter.java:392)
	at org.springframework.data.redis.core.convert.MappingRedisConverter.write(MappingRedisConverter.java:118)
	at org.springframework.data.redis.core.RedisKeyValueAdapter.put(RedisKeyValueAdapter.java:206)
	at org.springframework.data.keyvalue.core.KeyValueTemplate.lambda$update$1(KeyValueTemplate.java:204)
	at org.springframework.data.keyvalue.core.KeyValueTemplate.execute(KeyValueTemplate.java:343)
	... 30 more

In Sourcecode you can see that in BasicPersistenceEntity:

this.annotationCache = new HashMap<>();

... is just a simple map, no ConcurrentHashmap and no other means of making this part threadsafe.

When I do the Test in single Thread mode there is no problem.

Basically this means all the Spring Data Repositories are not threadsafe!


Affects: 2.0.1 (Kay SR1)

Issue Links:

  • DATACMNS-1364 BasicPersistentEntity.getPersistentProperty(…) returns the unchecked value in ConcurrentReferenceHashMap

Referenced from: pull request #259, and commits 309cdc5, 24c1b82, 8026f8a, 8185885

Backported to: 2.0.2 (Kay SR2)

@spring-projects-issues
Copy link
Author

Philipp Röben commented

Thanks guys for fixong this so quickly!
(y)

@spring-projects-issues spring-projects-issues added type: bug A general bug in: repository Repositories abstraction in: mapping Mapping and conversion infrastructure labels Dec 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: mapping Mapping and conversion infrastructure in: repository Repositories abstraction type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants