GH-3243: sync computeIfAbsent in StoredProcExec

Fixes https://github.com/spring-projects/spring-integration/issues/3243

It turns out that `ConcurrentModificationException` is thrown from the
`HashMap.computeIfAbsent(HashMap.java:1134)` since Java 9 when the map is
modified concurrently independently from the key we try to modify

* Check for the value presence before computing
* `synchronized(this.jdbcCallOperationsMap)` around `computeIfAbsent()`
when `get() == null`

**Cherry-pick to 5.2.x**
This commit is contained in:
Artem Bilan
2020-04-07 14:35:55 -04:00
committed by Gary Russell
parent cd64a0902e
commit 2d7e47355b

View File

@@ -62,6 +62,8 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean {
private final DataSource dataSource;
private final Object jdbcCallOperationsMapMonitor = new Object();
private Map<String, RowMapper<?>> returningResultSetRowMappers = new HashMap<>(0);
private EvaluationContext evaluationContext;
@@ -296,7 +298,14 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean {
}
private SimpleJdbcCallOperations obtainSimpleJdbcCall(String storedProcedureName) {
return this.jdbcCallOperationsMap.computeIfAbsent(storedProcedureName, this::createSimpleJdbcCall);
SimpleJdbcCallOperations operations = this.jdbcCallOperationsMap.get(storedProcedureName);
if (operations == null) {
synchronized (this.jdbcCallOperationsMapMonitor) {
operations =
this.jdbcCallOperationsMap.computeIfAbsent(storedProcedureName, this::createSimpleJdbcCall);
}
}
return operations;
}
//~~~~~Setters for Properties~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~