Skip to content

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

@spring-projects-issues

Description

@spring-projects-issues

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)

Metadata

Metadata

Labels

in: mappingMapping and conversion infrastructurein: repositoryRepositories abstractiontype: bugA general bug

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions