Reputation: 43
My application maintains a cache of list of users and it is evicted when any new user is created. I am getting Concurrent Modification exception while evicting the cache.
Stack trace :
java.util.ConcurrentModificationException: null
at java.util.HashMap.forEach(HashMap.java:1292)
at org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.releaseResources(ResourceRegistryStandardImpl.java:323)
at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.afterTransaction(AbstractLogicalConnectionImplementor.java:60)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.afterTransaction(LogicalConnectionManagedImpl.java:167)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.afterCompletion(LogicalConnectionManagedImpl.java:291)
at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:95)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:282)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:627)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:633)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:386)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at com.mytestapp.service.impl.MyCacheManager$$EnhancerBySpringCGLIB$$6a5d7f13.resetTeamListCache(<generated>)
at
com.mytestapp.webapp.listener.StartupListener.refreshContext(StartupListener.java:199)
at com.mytestapp..webapp.controller.admin.SystemUserManagementController.saveSystemUserData(SystemUserManagementController.java:529)
In my controller the code is as follows :
systemUserProfileManager.saveSystemUserProfile(userBasicInfo); // async call
StartupListener.refreshContext(request.getSession().getServletContext()); // cache evict
refreshContextMethod in StartupListener :
public static void refreshContext(ServletContext context) {
ApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(context);
MyCacheManager myCacheManager = (MyCacheManager) ctx
.getBean(myCacheManager);
LOG.debug("Processing started for refreshing Servlet Context/ Cache!");
// RESET All Cache
myCacheManager.resetTeamListCache();
LOG.debug("Processing completed for refreshing Servlet Context/ Cache!");
}
resetTeamListCache method in MyCacheManager :
@CacheEvict(value = CacheConstants.SALES_TEAM_LIST, allEntries = true)
public void resetTeamListCache() {
// Intentionally blank
}
Upvotes: 4
Views: 850
Reputation: 138
This information is outdated; however, it took me several days to identify this issue.
This error can potentially block the Hikari connection and the connection stays as "active", leading to application failure at some point. The root cause lies in the cache.
In my particular scenario, I had configured the cache manager, but despite disabling 'spring.cache.type=none,' the cache continued to function inexplicably.
public CacheManager cacheManager() {
ConcurrentMapCacheManager manager = new ConcurrentMapCacheManager();
manager.setAllowNullValues(false);
return manager;
}
My Service layer had also cache evict which caused then the exception and blocked connection to dabase.
@Cacheable(value = "item", key = "#item.name", unless = "#result == null")
Upvotes: 0
Reputation: 16440
The error suggests that you are using the same Hibernate Session in multiple threads concurrently. The hash map, which according to the exception is iterated, does not change within the process of iteration, so the only way this can happen is if you have a concurrency problem in your application.
Upvotes: 2