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

Regression in SimpleThreadScope introduced in 5.2.7 #25618

Closed
FernandoFranzini opened this issue Aug 20, 2020 · 7 comments
Closed

Regression in SimpleThreadScope introduced in 5.2.7 #25618

FernandoFranzini opened this issue Aug 20, 2020 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Milestone

Comments

@FernandoFranzini
Copy link

FernandoFranzini commented Aug 20, 2020

Hello people

I updated today to spring 5.2.8.RELEASE and started to give error in my mock session for JUNIT

java.lang.IllegalStateException: Failed to load ApplicationContext

	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testeEmissorLoginBean': Unsatisfied dependency expressed through field 'bean'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginEmissorBean': Unsatisfied dependency expressed through field 'credencial'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'credencialBean' defined in class path resource [spring-junit.xml]: Initialization of bean failed; nested exception is java.util.ConcurrentModificationException
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
	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.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:275)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:243)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	... 25 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginEmissorBean': Unsatisfied dependency expressed through field 'credencial'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'credencialBean' defined in class path resource [spring-junit.xml]: Initialization of bean failed; nested exception is java.util.ConcurrentModificationException
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$1(AbstractBeanFactory.java:359)
	at org.springframework.context.support.SimpleThreadScope.lambda$get$0(SimpleThreadScope.java:70)
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1133)
	at org.springframework.context.support.SimpleThreadScope.get(SimpleThreadScope.java:70)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:356)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1304)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1224)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
	... 43 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'credencialBean' defined in class path resource [spring-junit.xml]: Initialization of bean failed; nested exception is java.util.ConcurrentModificationException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603)
	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.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1304)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1224)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
	... 58 more
Caused by: java.util.ConcurrentModificationException
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1134)
	at org.springframework.context.support.SimpleThreadScope.get(SimpleThreadScope.java:70)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:356)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1699)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
	... 67 more

My tdd uses the following configuration:

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="session">
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>

in version 5.2.6.RELEASE backwards works without error.
Could someone help me how to get around this?
Regards

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Aug 20, 2020
@sbrannen
Copy link
Member

sbrannen commented Aug 20, 2020

This may potentially be a regression introduced in 50a4fda#diff-0a063fe61d0e0640b8c05f6ad641c486.

Note that we do have some simple tests in place for this (see SimpleThreadScopeTests and simpleThreadScopeTests.xml).

@FernandoFranzini, can you provide a minimal sample application that reproduces the issue you are experiencing?

@sbrannen sbrannen added in: core Issues in core modules (aop, beans, core, context, expression) status: waiting-for-feedback We need additional information before we can continue labels Aug 20, 2020
@sbrannen sbrannen changed the title 5.2.7.RELEASE generated a bug with SimpleThreadScope 5.2.7.RELEASE introduced a bug in SimpleThreadScope Aug 20, 2020
@sbrannen
Copy link
Member

@FernandoFranzini, can you confirm the Java version you are using?

I ask, because we assume the ConcurrentModificationException only occurs on Java 11+.

@sbrannen sbrannen added type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 20, 2020
@sbrannen sbrannen changed the title 5.2.7.RELEASE introduced a bug in SimpleThreadScope 5.2.7.RELEASE introduced a regression in SimpleThreadScope Aug 20, 2020
@sbrannen sbrannen added this to the 5.2.9 milestone Aug 20, 2020
@FernandoFranzini
Copy link
Author

Hi Sam
I'm using OracleJDK11.
Thanks for the quick response. I'll be using 5.2.6 until .9 comes out.
Regards

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 20, 2020
@sbrannen
Copy link
Member

I'm using OracleJDK11.

Thanks for the prompt feedback. That confirms our suspicions.

@sbrannen sbrannen removed the status: feedback-provided Feedback has been provided label Aug 20, 2020
@sbrannen sbrannen self-assigned this Aug 20, 2020
@sbrannen sbrannen changed the title 5.2.7.RELEASE introduced a regression in SimpleThreadScope Regression in SimpleThreadScope introduced in 5.2.7 Aug 20, 2020
@sbrannen
Copy link
Member

This has been fixed in 5.2.x and will be available in the next snapshots for 5.2.9.

@quaff
Copy link
Contributor

quaff commented Aug 24, 2020

@FernandoFranzini, can you confirm the Java version you are using?

I ask, because we assume the ConcurrentModificationException only occurs on Java 11+.

@sbrannen Is this a bug of Java 11+?

@quaff
Copy link
Contributor

quaff commented Aug 24, 2020

Never mind, I found the answer in commit log.

sbrannen added a commit that referenced this issue Sep 25, 2020
Issues gh-25038 and gh-25618 collectively introduced a regression for
thread-scoped and transaction-scoped beans.

For example, given a thread-scoped bean X that depends on another
thread-scoped bean Y, if the names of the beans (when used as map keys)
end up in the same bucket within a ConcurrentHashMap AND an attempt is
made to retrieve bean X from the ApplicationContext prior to retrieving
bean Y, then the use of Map::computeIfAbsent in SimpleThreadScope
results in recursive access to the same internal bucket in the map.

On Java 8, that scenario simply hangs. On Java 9 and higher,
ConcurrentHashMap throws an IllegalStateException pointing out that a
"Recursive update" was attempted.

In light of these findings, we are reverting the changes made to
SimpleThreadScope and SimpleTransactionScope in commits 50a4fda and
148dc95.

Closes gh-25801
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: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

5 participants
@sbrannen @quaff @FernandoFranzini @spring-projects-issues and others