-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Tom Ziemer opened SPR-7398 and commented
Concurrent access to a prototype bean with a nested map property causes random java.lang.ClassCastExceptions.
Example:
<!-- prototype -->
<bean id="statefulBean"
class="foo.bar.mapissue.bo.DefaultStatefulBean"
init-method="init"
scope="prototype">
<property name="mappings">
<map key-type="java.lang.String" value-type="java.lang.String">
<entry key="fromA" value="toB"/>
<entry key="fromB" value="toC"/>
</map>
</property>
</bean>
Running the attached program randomly yields the following exception:
27.07.2010 16:29:18 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@e5355f: defining beans [statefulBean]; root of factory hierarchy
Exception in thread "Thread-1100" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'statefulBean' defined in class path resource [spring/applicationContext.xml]: Error converting typed String value for bean property 'mappings'; nested exception is java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.String
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:382)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:161)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1317)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075)
at foo.bar.mapissue.MapIssueTest$RequestThread.doWork(MapIssueTest.java:57)
at foo.bar.mapissue.MapIssueTest$RequestThread.run(MapIssueTest.java:49)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.String
at org.springframework.beans.factory.config.TypedStringValue.getTargetTypeName(TypedStringValue.java:135)
at org.springframework.beans.factory.config.TypedStringValue.resolveTargetType(TypedStringValue.java:158)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveTargetType(BeanDefinitionValueResolver.java:242)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:184)
... 12 more
Possible workaround: do not use an anonymous inner bean but create a util:map-style bean and reference it from the prototype:
<!-- prototype -->
<bean id="statefulBean"
class="foo.bar.mapissue.bo.DefaultStatefulBean"
init-method="init"
scope="prototype">
<property name="mappings" ref="mappings"/>
</bean>
<util:map id="mappings" key-type="java.lang.String" value-type="java.lang.String">
<entry key="fromA" value="toB"/>
<entry key="fromB" value="toC"/>
</util:map>
Please note:
- The issue does not occur all the time, running the test multiple times might be necessary.
- Tested on Windows XP, SUN JVM 1.6.0_17, 1.6.0_18, 1.6.0_21
Affects: 3.0.3
Attachments:
- mapissue.zip (4.85 kB)
Referenced from: commits c3a639f
1 votes, 2 watchers