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

Scope of some dependencies has changed from compile to runtime #21507

Closed
michael-simons opened this issue May 19, 2020 · 6 comments
Closed

Scope of some dependencies has changed from compile to runtime #21507

michael-simons opened this issue May 19, 2020 · 6 comments
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@michael-simons
Copy link
Contributor

The scope of org.springframework.boot:spring-boot-test has been changed from compile to runtime from 2.2.x to 2.3. spring-boot-test comes as dependency of spring-boot-test-autoconfigure.

[INFO] +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.2.6.RELEASE:compile
[INFO] |  \- org.springframework.boot:spring-boot-test:jar:2.2.6.RELEASE:compile

vs

[INFO] +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.3.0.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot:jar:2.3.0.RELEASE:compile
[INFO] |  \- org.springframework.boot:spring-boot-test:jar:2.3.0.RELEASE:runtime

This is a breaking change for library developers providing custom test autoconfiguration. For example, using SpringBootTestContextBootstrapper to provide additional properties.

SpringBootTestContextBootstrapper is considered public API:

{@link TestContextBootstrapper} for Spring Boot. Provides support for
{@link SpringBootTest @SpringBootTest} and may also be used directly or subclassed.

As a workaround I can change the scope back to compile again in our Maven build or include the dependency manually, but the change came as a surprise to us.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 19, 2020
@wilkinsona
Copy link
Member

Thanks, @michael-simons.

This is a side-effect of the build switching to Gradle. spring-boot-test-autoconfigure declares spring-boot-test as an implementation dependency. That means that none of the types in spring-boot-test are part of the API of spring-boot-test-autoconfigure. This minimises the size of the compile classpath for Gradle projects that depend on spring-boot-test-autoconfigure. Maven doesn't support the same separation of API and implementation dependencies so Gradle maps them to compile and runtime scope respectively which is how the problem has arisen.

If we consider spring-boot-test to be part of the API of spring-boot-test-autoconfigure we should change to an api dependency. If we want to avoid this wrinkle when upgrading, we should change to an api dependency. Otherwise, we should stick with an implementation dependency so that the compile classpath remains as small as possible.

@wilkinsona wilkinsona added the for: team-attention An issue we'd like other members of the team to review label May 19, 2020
@wilkinsona wilkinsona changed the title Scope of spring-boot-test changed from compile to runtime. Scope of spring-boot-test dependency in spring-boot-autoconfigure has changed from compile to runtime May 19, 2020
@wilkinsona wilkinsona changed the title Scope of spring-boot-test dependency in spring-boot-autoconfigure has changed from compile to runtime Scope of spring-boot-test dependency in spring-boot-test-autoconfigure has changed from compile to runtime May 19, 2020
@filiphr
Copy link
Contributor

filiphr commented May 26, 2020

I don't want to hijack this issue, However, I noticed other places where something like this happens. Please let me know if I should open a new issue.

I noticed that spring-boot-actuator-autoconfigure has spring-boot-autoconfigure as a runtime scope instead of compile. In 2.2.x it was a compile dependency. This isn't the only place which is like this.

@filiphr
Copy link
Contributor

filiphr commented May 26, 2020

Not sure if it is linked to this, but since we updated to 2.3 some of our teammates have the following when running the our maven project from IntelliJ.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'delegatingApplicationListener' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' available
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.context.event.AbstractApplicationEventMulticaster.retrieveApplicationListeners(AbstractApplicationEventMulticaster.java:245) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:197) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:134) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:403) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.boot.availability.AvailabilityChangeEvent.publish(AvailabilityChangeEvent.java:81) ~[spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.availability.AvailabilityChangeEvent.publish(AvailabilityChangeEvent.java:67) ~[spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.doClose(ServletWebServerApplicationContext.java:167) ~[spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:978) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:814) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:325) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at com.flowable.external.banking.app.ExternalBankingApplication.main(ExternalBankingApplication.java:19) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' available
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:409) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(BeanFactoryAdvisorRetrievalHelper.java:91) ~[spring-aop-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(AbstractAdvisorAutoProxyCreator.java:109) ~[spring-aop-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:94) ~[spring-aop-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:76) ~[spring-aop-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:347) ~[spring-aop-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299) ~[spring-aop-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:431) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    ... 19 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:814) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1282) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:297) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor.postProcessBeforeInitialization(ConfigurationClassPostProcessor.java:456) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    ... 42 common frames omitted

Is it possible that the runtime scoped of the different dependencies, to be causing this?

@wilkinsona
Copy link
Member

However, I noticed other places where something like this happens. Please let me know if I should open a new issue.

@filiphr We can expand the scope of this issue as needed. Where you've noticed the dependencies that are affected, it'd be great if you could comment here with the details please.

Is it possible that the runtime scoped of the different dependencies, to be causing this?

No, I don't think so. A change from compile scope to runtime scope will only affect the compile classpath. It should have no effect on runtime behaviour. If you can share a project that reproduces the missing importRegistry, please open a new issue and we'll take a look.

@filiphr
Copy link
Contributor

filiphr commented May 26, 2020

@filiphr We can expand the scope of this issue as needed. Where you've noticed the dependencies that are affected, it'd be great if you could comment here with the details please.

Thanks. Currently it is only the one I mentioned before. If we see something else we will let you know.

No, I don't think so. A change from compile scope to runtime scope will only affect the compile classpath. It should have no effect on runtime behaviour. If you can share a project that reproduces the missing importRegistry, please open a new issue and we'll take a look.

This is not really easy to reproduce. It sometimes disappears after restarting IntelliJ, reimporting Maven projects several times, etc. It could very much be an IntelliJ bug and how they handle the maven runtime scope. If I get more information I will create a new issue and let you know.

@wilkinsona
Copy link
Member

wilkinsona commented May 27, 2020

I've managed to reproduce the problem with the missing importRegistry bean. The failure's happening when the context is being closed. It's the attempt to retrieve the application listeners for the AvailabilityChangeEvent that is failing. This event is new in 2.3 which I think may explain why we've started to see the problem now. I believe it will affect any app where the context fails to refresh or perhaps only those where the refresh attempt fails at a certain point. I've opened #21588.

@philwebb philwebb added type: regression A regression from a previous release and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels May 29, 2020
@philwebb philwebb modified the milestones: 2.4.x, 2.3.x May 29, 2020
@wilkinsona wilkinsona changed the title Scope of spring-boot-test dependency in spring-boot-test-autoconfigure has changed from compile to runtime Scope of some dependencies has changed from compile to runtime Jun 3, 2020
@wilkinsona wilkinsona self-assigned this Jun 3, 2020
@wilkinsona wilkinsona modified the milestones: 2.3.x, 2.3.1 Jun 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants