Skip to content

Improve circular import exception, in particular for @Import vs import through nesting [SPR-13101] #17692

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

Closed
spring-projects-issues opened this issue Jun 5, 2015 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jun 5, 2015

Christopher Smith opened SPR-13101 and commented

I have the following configuration class, with a nested extension:

@Configuration
@Import(GalleryMockMvcConfig.InMemorySecurity)
@CompileStatic
class MockMvcMyConfig {
    @Bean
    MyHtmlController myHtmlController(WorkImageRepository images) {
        new MyHtmlController(images)
    }

    @Configuration
    @Import(MockMvcMyConfig)
    @CompileStatic
    static class Digitizer {
        @Bean
        DigitizerClientHtmlController digitizerClientHtmlController(PersonRepository people, UploadPermissionRepository permissions, UserOperations userOps) {
            new DigitizerClientHtmlController(people, permissions, userOps)
        }
    }
}

GalleryMockMvcConfig.InMemorySecurity does not include Digitizer.

When trying to use this class in @ContextConfiguration, I get the following exception:

java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
	at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
	at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:170)
	at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:110)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
	at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:49)
	at org.spockframework.spring.SpringInterceptor.interceptSetupMethod(SpringInterceptor.java:42)
	at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:28)
	at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
	at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88)
	at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1.evaluate(AbstractRuleInterceptor.java:37)
	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
	at org.spockframework.runtime.extension.builtin.TestRuleInterceptor.intercept(TestRuleInterceptor.java:38)
	at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: A circular @Import has been detected: Illegal attempt by @Configuration class 'MockMvcMyConfig.Digitizer' to import class 'MockMvcMyConfig.Digitizer' as 'MockMvcMyConfig.Digitizer' is already present in the current import stack [ImportStack: [MockMvcMyConfig.Digitizer]]
Offending resource: com.artsquare.gallery.web.html.mockmvc.config.MockMvcMyConfig$Digitizer
	at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70)
	at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:450)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:275)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:229)
	at org.springframework.context.annotation.ConfigurationClassParser.processMemberClasses(ConfigurationClassParser.java:317)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:246)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:229)
	at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:485)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:275)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:229)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:196)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:165)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:306)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:239)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
	at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:133)
	at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:60)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
	at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
	at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
	... 19 more

Affects: 4.1.6

Issue Links:

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

That might be a side effect from our handling of nested configuration classes: nesting a config class within an outer config class is a kind-of import from the outer class to the inner class (the way we're processing it). From that perspective, you could probably simply drop the @Import(MockMvcMyConfig) part on the nested class.

In any case, we should not be throwing a circular import exception in such a scenario since there is no user-defined import circle...

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This is indeed caused by the 'implicit' import through the nesting of configuration classes. I'll make sure to improve the circular import exception that way, explicitly pointing out that nesting might be involved.

Fundamentally, we do want to process such a scenario as an import circle, enforcing the removal of the explicit @Import on the nested class in such a case. Otherwise, reading the source code suggests a different processing order.

Jeurgen

@spring-projects-issues
Copy link
Collaborator Author

Ashvin Kanani commented

I don't use nested classes but still I am getting the same error when upgrading spring-boot version to 1.3.5.RELEASE.

@spring-projects-issues
Copy link
Collaborator Author

Ashvin Kanani commented

I have logged the issue I am facing at http://stackoverflow.com/questions/37963213/a-circular-import-has-been-detected

@spring-projects-issues
Copy link
Collaborator Author

Jean-Pierre Bergamin commented

We're also facing a "Configuration problem: A circular @Import has been detected" error when upgrading from Spring Boot 1.3.1 to 1.3.5.

Our case is like:

A shared repository maven module contains:

@Configuration
@ComponentScan
MyRepositoryContextConfiguration {
}
@Configuration
@Import(MyRepositoryContextConfiguration.class)
MyRepositoryTestConfiguration {
}

A webapp using this shared repository (including is as a test-jar as well) has:

@Configuration
@Import(MyRepositoryTestConfiguration)
MyWebappTestConfiguration {
}

The component scan in the MyRepositoryContextConfiguration class picks up the MyRepositoryTestConfiguration again when running tests and leads to the following error:

Configuration problem: A circular @Import has been detected: Illegal attempt by @Configuration class 'MyRepositoryTestConfiguration' to import class 'MyRepositoryTestConfiguration' as 'MyRepositoryTestConfiguration' is already present in the current import stack [MyRepositoryTestConfiguration->MyWebappTestConfiguration]

I don't think that an @ComponentScan should trigger this error since it's not an explicit @Import definition.

What do you think?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Jean-Pierre Bergamin, sounds valid, since a @ComponentScan indeed does not qualify as an explicit @Import in terms of circular import detection

Could you please create a new JIRA ticket for this one? We might still address it for 4.3.2 later today then.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jul 27, 2016

Jean-Pierre Bergamin commented

Please see #19086

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: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants