I am usingJava Spring Configuration and few beans are referencing one bean. It seems that all beans are trying to initialize properties() bean at same time because getting ConcurrentModificationException on startup of service (not always. getting this error 1 out of 1000 times)-
ERR [main ] - org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'genericTaskExecutor' defined in class path resource [com/test/SpringConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.concurrent.Executor]: Factory method 'threadPoolTaskExecutor' threw exception; nested exception is java.util.ConcurrentModificationException
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:483)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:893)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:142)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:95)
at Main.start(Main.java:27)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.concurrent.Executor]: Factory method 'threadPoolTaskExecutor' threw exception; nested exception is java.util.ConcurrentModificationException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:650)
... 16 more
Caused by: java.util.ConcurrentModificationException
at java.util.Hashtable$Enumerator.next(Hashtable.java:1387)
at java.util.Hashtable.putAll(Hashtable.java:523)
at com.test.SpringConfiguration.properties(DependencySpringConfiguration.java:43)
at com.test.SpringConfiguration.threadPoolTaskExecutor(DependencySpringConfiguration.java:69)
at com.test.SpringConfiguration$$EnhancerBySpringCGLIB$$c6bbb94b.CGLIB$threadPoolTaskExecutor$0(<generated>)
at com.test.SpringConfiguration$$EnhancerBySpringCGLIB$$c6bbb94b$$FastClassBySpringCGLIB$$87cff70.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at com.test.SpringConfiguration$$EnhancerBySpringCGLIB$$c6bbb94b.threadPoolTaskExecutor(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 17 more
Following are bean definitions. My code is giving error on "properties.putAll(System.getProperties())" call. I am unable to find what I am missing in Spring Configuration because exception is coming rarely so must be race condition between beans initialization -
@Configuration
@EnableScheduling
public class DependencySpringConfiguration {
@Bean
public static Properties properties() {
Properties properties = new Properties();
properties.putAll(System.getProperties());
//do some formatting on properties data
return properties;
}
@Bean(name = "genericTaskExecutor")
@Primary
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int corePoolSize = NumberUtils.toInt(properties().getProperty("generic-executor.core-pool.size"), 10);
log.info("Initial pool size for 'genericTaskExecutor' is {}", corePoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(50);
executor.setThreadNamePrefix("GenericTaskExecutor-");
executor.initialize();
return executor;
}
@Bean(name = "legacy")
public Executor legacyThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int corePoolSize = NumberUtils.toInt(properties().getProperty("legacy-executor.core-pool.size"), 1);
log.info("Initial pool size for 'legacyTaskExecutor' is {}", corePoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(10);
executor.setThreadNamePrefix("LegacyTaskExecutor-");
executor.initialize();
return executor;
}
@Bean(name = "reconTaskExecutor")
public Executor reconPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int corePoolSize = NumberUtils.toInt(properties().getProperty("recon-executor.core-pool.size"), 2);
log.info("Initial pool size for 'reconTaskExecutor' is {}", corePoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(10);
executor.setThreadNamePrefix("ReconTaskExecutor-");
executor.initialize();
return executor;
}
}
CodePudding user response:
System properties can change at any time so your attempt to properties.putAll(System.getProperties())
is throwing ConcurrentModificationException. That is because the putAll method is using an iterator. Try to clone()
system properties and use the cloned instance instead.
properties.putAll(System.getProperties().clone());