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

ReactiveWebServerApplicationContext.getHttpHandler() causes early bean initialization #14666

Closed
artembilan opened this issue Oct 2, 2018 · 10 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@artembilan
Copy link
Member

artembilan commented Oct 2, 2018

The config is like this:

@EnableIntegration
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public DirectChannel channel1() {
        return new DirectChannel();
    }

    @Bean
    public DirectChannel channel2() {
        return new DirectChannel();
    }

    @Bean // remove this bean to fix Transformer creation
    public JavaTimeModule timeModule() {
        return new JavaTimeModule();
    }

    /**
     * This method depends on object mapper, which is not yet configured (with module above) when
     * Spring DI is trying to instantiate transformer.
     *
     * Useful debug points:
     * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeansOfType(Class, boolean, boolean)}
     * {@link org.springframework.integration.config.annotation.TransformerAnnotationPostProcessor#createHandler(Object, Method, List)}
     *
     */
    @Bean
    @Transformer(inputChannel = "channel1", outputChannel = "channel2")
    public AbstractPayloadTransformer transformer(ObjectMapper dependency) {
        return new AbstractPayloadTransformer<Object, Object>() {
            @Override
            protected Object transformPayload(Object payload) {
                return payload;
            }
        };
    }
}

But Spring Integration is not relevant here at all.

The main point that we have some Jackson Module bean definition and other one depends on the ObjectMapper auto-configured in the mentioned JacksonAutoConfiguration.

The JacksonAutoConfiguration has the code like this:

@Bean
@ConditionalOnMissingBean
public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(
      List<Jackson2ObjectMapperBuilderCustomizer> customizers) {
   Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
   builder.applicationContext(this.applicationContext);
   customize(builder, customizers);
   return builder;
}

That customize() calls a

Collection<Module> moduleBeans = getBeans(this.applicationContext,
      Module.class);

eventually.

This is really inappropriate to call getBeansOfType() from the other bean definition: it's too early to instantiate all the beans in the application context.

I wonder why ObjectProvider<Module> is not used as a dependency for that jacksonObjectMapperBuilder bean definition...

For more info see spring-projects/spring-integration#2565

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 2, 2018
@philwebb
Copy link
Member

philwebb commented Oct 3, 2018

This is really inappropriate to call getBeansOfType() from the other bean definition: it's too early to instantiate all the beans in the application context.

I'm not sure that that's the problem here. In most cases it's perfectly reasonable to call getBeansOfType() from a @Bean method. It's not really any different than Spring doing it and injecting the values.

I think the real problem is that the jacksonObjectMapperBuilder bean is being created way too early. If I convert the sample to Spring MVC I get the following stack trace:

Web MVC stacktrace
Thread [main] (Suspended (breakpoint at line 185 in JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration))	
	owns: ConcurrentHashMap  (id=81)	
	owns: Object  (id=82)	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$a5467a4d(JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration).jacksonObjectMapperBuilder(List) line: 185	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$a5467a4d.CGLIB$jacksonObjectMapperBuilder$0(List) line: not available	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$a5467a4d$$FastClassBySpringCGLIB$$c13a17e4.invoke(int, Object, Object[]) line: not available	
	MethodProxy.invokeSuper(Object, Object[]) line: 228	
	ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 361	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$a5467a4d.jacksonObjectMapperBuilder(List) line: not available	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 498	
	CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object...) line: 154	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 582	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	2033268925.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DependencyDescriptor.resolveCandidate(String, Class, BeanFactory) line: 251	
	DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1138	
	DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1065	
	ConstructorResolver.resolveAutowiredArgument(MethodParameter, String, Set, TypeConverter) line: 818	
	ConstructorResolver.createArgumentArray(String, RootBeanDefinition, ConstructorArgumentValues, BeanWrapper, Class[], String[], Executable, boolean) line: 724	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 474	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	2033268925.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DependencyDescriptor.resolveCandidate(String, Class, BeanFactory) line: 251	
	DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1138	
	DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1065	
	ConstructorResolver.resolveAutowiredArgument(MethodParameter, String, Set, TypeConverter) line: 818	
	ConstructorResolver.createArgumentArray(String, RootBeanDefinition, ConstructorArgumentValues, BeanWrapper, Class[], String[], Executable, boolean) line: 724	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 474	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	2033268925.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	TransformerAnnotationPostProcessor(AbstractMethodAnnotationPostProcessor).resolveTargetBeanFromMethodWithBeanAnnotation(Method) line: 449	
	TransformerAnnotationPostProcessor(AbstractMethodAnnotationPostProcessor).postProcess(Object, String, Method, List) line: 133	
	MessagingAnnotationPostProcessor.processAnnotationTypeOnMethod(Object, String, Method, Class, List) line: 185	
	MessagingAnnotationPostProcessor.lambda$postProcessAfterInitialization$0(Object, String, Class, Method) line: 158	
	1254827280.doWith(Method) line: not available	
	ReflectionUtils.doWithMethods(Class, MethodCallback, MethodFilter) line: 562	
	ReflectionUtils.doWithMethods(Class, MethodCallback, MethodFilter) line: 569	
	MessagingAnnotationPostProcessor.postProcessAfterInitialization(Object, String) line: 139	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyBeanPostProcessorsAfterInitialization(Object, String) line: 439	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).initializeBean(String, Object, RootBeanDefinition) line: 1712	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 581	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	2033268925.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DefaultListableBeanFactory.preInstantiateSingletons() line: 760	
	AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 869	
	AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).refresh() line: 550	
	AnnotationConfigServletWebServerApplicationContext(ServletWebServerApplicationContext).refresh() line: 140	
	SpringApplication.refresh(ApplicationContext) line: 759	
	SpringApplication.refreshContext(ConfigurableApplicationContext) line: 395	
	SpringApplication.run(String...) line: 327	
	SpringApplication.run(Class[], String[]) line: 1255	
	SpringApplication.run(Class, String...) line: 1243	
	ScratchApplication.main(String[]) line: 22	

With WebFlux, I get the following:

WebFlux stacktrace
Thread [main] (Suspended (breakpoint at line 185 in JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration))	
	owns: ConcurrentHashMap  (id=85)	
	owns: Object  (id=86)	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$93662396(JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration).jacksonObjectMapperBuilder(List) line: 185	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$93662396.CGLIB$jacksonObjectMapperBuilder$0(List) line: not available	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$93662396$$FastClassBySpringCGLIB$$1fa55dac.invoke(int, Object, Object[]) line: not available	
	MethodProxy.invokeSuper(Object, Object[]) line: 228	
	ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 361	
	JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$93662396.jacksonObjectMapperBuilder(List) line: not available	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 498	
	CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object...) line: 154	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 582	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DependencyDescriptor.resolveCandidate(String, Class, BeanFactory) line: 251	
	DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1138	
	DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1065	
	ConstructorResolver.resolveAutowiredArgument(MethodParameter, String, Set, TypeConverter) line: 818	
	ConstructorResolver.createArgumentArray(String, RootBeanDefinition, ConstructorArgumentValues, BeanWrapper, Class[], String[], Executable, boolean) line: 724	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 474	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DependencyDescriptor.resolveCandidate(String, Class, BeanFactory) line: 251	
	DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1138	
	DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1065	
	ConstructorResolver.resolveAutowiredArgument(MethodParameter, String, Set, TypeConverter) line: 818	
	ConstructorResolver.createArgumentArray(String, RootBeanDefinition, ConstructorArgumentValues, BeanWrapper, Class[], String[], Executable, boolean) line: 724	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 474	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DefaultListableBeanFactory$MultiElementDescriptor(DependencyDescriptor).resolveCandidate(String, Class, BeanFactory) line: 251	
	DefaultListableBeanFactory.addCandidateEntry(Map, String, DependencyDescriptor, Class) line: 1325	
	DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) line: 1291	
	DefaultListableBeanFactory.resolveMultipleBeans(DependencyDescriptor, String, Set, TypeConverter) line: 1193	
	DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1096	
	DefaultListableBeanFactory$DependencyObjectProvider.getIfAvailable() line: 1686	
	WebFluxAutoConfiguration$WebFluxConfig$$EnhancerBySpringCGLIB$$9b8d1745(WebFluxAutoConfiguration$WebFluxConfig).(ResourceProperties, WebFluxProperties, ListableBeanFactory, ObjectProvider>, ObjectProvider>, ObjectProvider, ObjectProvider>) line: 125	
	WebFluxAutoConfiguration$WebFluxConfig$$EnhancerBySpringCGLIB$$9b8d1745.(ResourceProperties, WebFluxProperties, ListableBeanFactory, ObjectProvider, ObjectProvider, ObjectProvider, ObjectProvider) line: not available	
	NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]	
	NativeConstructorAccessorImpl.newInstance(Object[]) line: 62	
	DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45	
	Constructor.newInstance(Object...) line: 423	
	BeanUtils.instantiateClass(Constructor, Object...) line: 170	
	CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory, Constructor, Object...) line: 117	
	ConstructorResolver.autowireConstructor(String, RootBeanDefinition, Constructor[], Object[]) line: 275	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).autowireConstructor(String, RootBeanDefinition, Constructor[], Object[]) line: 1276	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1133	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	DefaultListableBeanFactory$MultiElementDescriptor(DependencyDescriptor).resolveCandidate(String, Class, BeanFactory) line: 251	
	DefaultListableBeanFactory.addCandidateEntry(Map, String, DependencyDescriptor, Class) line: 1325	
	DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) line: 1291	
	DefaultListableBeanFactory.resolveMultipleBeans(DependencyDescriptor, String, Set, TypeConverter) line: 1193	
	DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1096	
	DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 1065	
	AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(Object, String, PropertyValues) line: 659	
	InjectionMetadata.inject(Object, String, PropertyValues) line: 91	
	AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String) line: 373	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, RootBeanDefinition, BeanWrapper) line: 1350	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 580	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 199	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 372	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class) line: 204	
	AnnotationConfigReactiveWebServerApplicationContext(AbstractApplicationContext).getBean(String, Class) line: 1095	
	WebHttpHandlerBuilder.applicationContext(ApplicationContext) line: 161	
	HttpHandlerAutoConfiguration$AnnotationConfig$$EnhancerBySpringCGLIB$$417a7db2(HttpHandlerAutoConfiguration$AnnotationConfig).httpHandler() line: 59	
	HttpHandlerAutoConfiguration$AnnotationConfig$$EnhancerBySpringCGLIB$$417a7db2.CGLIB$httpHandler$0() line: not available	
	HttpHandlerAutoConfiguration$AnnotationConfig$$EnhancerBySpringCGLIB$$417a7db2$$FastClassBySpringCGLIB$$e2b5e5bc.invoke(int, Object, Object[]) line: not available	
	MethodProxy.invokeSuper(Object, Object[]) line: 228	
	ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 361	
	HttpHandlerAutoConfiguration$AnnotationConfig$$EnhancerBySpringCGLIB$$417a7db2.httpHandler() line: not available	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 498	
	CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object...) line: 154	
	ConstructorResolver.instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 582	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) line: 1256	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBeanInstance(String, RootBeanDefinition, Object[]) line: 1105	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 543	
	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 503	
	DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317	
	1048434276.getObject() line: not available	
	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 315	
	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class) line: 204	
	AnnotationConfigReactiveWebServerApplicationContext(ReactiveWebServerApplicationContext).getHttpHandler() line: 155	
	AnnotationConfigReactiveWebServerApplicationContext(ReactiveWebServerApplicationContext).createWebServer() line: 99	
	AnnotationConfigReactiveWebServerApplicationContext(ReactiveWebServerApplicationContext).onRefresh() line: 73	
	AnnotationConfigReactiveWebServerApplicationContext(AbstractApplicationContext).refresh() line: 544	
	AnnotationConfigReactiveWebServerApplicationContext(ReactiveWebServerApplicationContext).refresh() line: 61	
	SpringApplication.refresh(ApplicationContext) line: 759	
	SpringApplication.refreshContext(ConfigurableApplicationContext) line: 395	
	SpringApplication.run(String...) line: 327	
	SpringApplication.run(Class[], String[]) line: 1255	
	SpringApplication.run(Class, String...) line: 1243	
	ScratchApplication.main(String[]) line: 22	

The second one is way early and being triggered by ReactiveWebServerApplicationContext.getHttpHandler().

@philwebb philwebb changed the title JacksonAutoConfiguration causes BeanCurrentlyInCreationException ReactiveWebServerApplicationContext.getHttpHandler() causes early bean initialization Oct 3, 2018
@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 3, 2018
@philwebb philwebb added this to the 2.0.x milestone Oct 3, 2018
@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Oct 3, 2018
@philwebb philwebb self-assigned this Oct 3, 2018
@snicoll snicoll modified the milestones: 2.0.x, 2.0.6 Oct 3, 2018
@snicoll snicoll removed the for: team-attention An issue we'd like other members of the team to review label Oct 3, 2018
@artembilan
Copy link
Member Author

@philwebb , thanks for the quick turn around, but I don't think that this fixes our original problem with the JacksonAutoConfiguration and its call for the BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory, type) from the jacksonObjectMapperBuilder bean definition.
What is the problem to do that via ObjectProvider<Module> method argument injection instead?

@snicoll
Copy link
Member

snicoll commented Oct 3, 2018

@philwebb I am not sure I get the history of this issue either. This is the single call to the variant that allows eager init so perhaps we should change it to the one that allows to skip eager inits?

This wouldn't force factory beans that do not expose the type though.

@snicoll snicoll added the for: team-attention An issue we'd like other members of the team to review label Oct 3, 2018
@wilkinsona
Copy link
Member

@artembilan Injecting ObjectProvider<Module> would be a point solution for a broader problem. Phil's change should benefit any type of bean that was previously being created eagerly via HttpHandler. I would guess that the post-processing of @Transformer methods is complicating things further. We'll need to try the sample again and see what's going on. I assume you've tried it with a Boot snapshot and the problem still occurs?

@philwebb philwebb reopened this Oct 3, 2018
@philwebb
Copy link
Member

philwebb commented Oct 3, 2018

@artembilan Can you also provide some more details of what we should do with sample? It runs, but I'm not sure what to look at.

@philwebb philwebb removed the for: team-attention An issue we'd like other members of the team to review label Oct 3, 2018
@artembilan
Copy link
Member Author

I confirm that with this fix the mentioned sample works as expected:

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-webflux:2.1.0.BUILD-SNAPSHOT'
    compile 'org.springframework.boot:spring-boot-starter-integration:2.1.0.BUILD-SNAPSHOT'
}

and I did this change in the code:

public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
        Map<String, EventDrivenConsumer> beansOfType = applicationContext.getBeansOfType(EventDrivenConsumer.class);
        System.out.println(beansOfType);
        applicationContext.close();
}

The output is pretty good:

10-03 10:59:59.289  INFO 11608 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started _org.springframework.integration.errorLogger
2018-10-03 10:59:59.289  INFO 11608 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {:application.transformer.transformer} as a subscriber to the 'channel1' channel
2018-10-03 10:59:59.289  INFO 11608 --- [           main] o.s.integration.channel.DirectChannel    : Channel 'application.channel1' has 1 subscriber(s).
2018-10-03 10:59:59.289  INFO 11608 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started application.transformer.transformer
2018-10-03 10:59:59.409  INFO 11608 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2018-10-03 10:59:59.412  INFO 11608 --- [           main] com.github.fred84.Application            : Started Application in 1.635 seconds (JVM running for 2.26)
{_org.springframework.integration.errorLogger=_org.springframework.integration.errorLogger, application.transformer.transformer=application.transformer.transformer}

So, I think we are good so far, however we still need to revise our usage for the BeanFactory.getBeansOfType() whenever it is called from other beans definitions. If we do this, we really cause an eager initialization as @snicoll mentioned above.

Thank you all for the help!

@wilkinsona
Copy link
Member

wilkinsona commented Oct 3, 2018

The use of getBeansOfType() is only a problem if it's done very early during refresh. That was the case previously due to when the HttpHandler bean was being created. Since Phil's fix, it's no longer the case. As Phil said above, calling it from a @Bean method is no different in terms of the initialisation it'll trigger to injecting the dependency or injecting an ObjectProvider and then calling it. In short, I don't think we need to change our usage of getBeansOfType().

We do, however, need to make a change to the use of volatile fields in ReactiveWebServerApplicationContext as there's a race condition where the handler could, in theory, be initialised twice.

@snicoll
Copy link
Member

snicoll commented Oct 3, 2018

if we do this, we really cause an eager initialization as @snicoll mentioned above.

I am afraid I sent you in the wrong direction. And while I was typing, Andy wrote a fully summary so I'll just refer to that :)

@artembilan
Copy link
Member Author

OK. So, looks like we are all good then! 😄

Thank you again!

@philwebb
Copy link
Member

philwebb commented Oct 4, 2018

I'm going to refactor this a little because @wilkinsona pointed out we're no longer thread safe.

philwebb added a commit that referenced this issue Oct 4, 2018
Fix possible NPE in `ReactiveWebServerApplicationContext`.

See gh-14666
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants