Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Random ClassCastException when creating prototype-bean with nested map property [SPR-7398] #12056

Closed
spring-projects-issues opened this issue Jul 27, 2010 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

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:

Referenced from: commits c3a639f

1 votes, 2 watchers

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Good catch - there was a potential concurrency issue there with lazy resolution of class names to Class references. I've fixed this for 3.0.4 now; will be available in tonight's 3.0.4 snapshot.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Tom Ziemer commented

Thanks for fixing the issue so quickly!

@spring-projects-issues spring-projects-issues added type: bug A general bug in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 3.0.4 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants