- Notifications
You must be signed in to change notification settings - Fork 698
Description
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)