0
votes

I have a bean in my app(based on Spring Boot 1.5.3) which takes time to be initialized due to loading lots of resources. While the initialization of that bean the web app already started to listen on port, the spring boot app still is running even if the initialization of that bean failed then thrown exception.

However the app still is running though the bean was failed to be injected.

Any way to exit the spring web app with error code if the bean was failed to be injected.

Below is the way how injectecting my bean,

@Component
@Slf4j
@RefreshScope
@Profile("!integTest")
public class NoteSpellChecker {

private Directory spellIndexDirectory;
private SpellChecker spellChecker;

public NoteSpellChecker(@Value("${app.spellcheck.indexPath:build/suggest}") String spellIndexPath,
                        @Value("${app.spellcheck.accuracy:0.5f}") float spellAccuracy,
                        @Value("${app.spellcheck.suggestDirectory:${spring.cloud.config.uri}/${spring.application.name}" +
                                "/${spring.profiles.active}/${spring.cloud.config.label:master}/spellcheck/note.txt},")
                                String[] spellSuggestDirectories,
                        OkHttpClient httpClient) throws IOException {
**here run some initialization task that takes some time**
}

There is another bean depending on NoteSpellChecker. See code snippet below,

@Configuration
@Slf4j
public class NoteDBConfig {

@Bean
public List<NoteRecognizer> noteRecognizers(NoteSpellChecker noteSpellChecker,
                                            NoteDBRepository noteDBRepository) {
    return noteDBRepository.findByEnabled(true).sorted((n1, n2) -> n1.getOrder() - n2.getOrder())
            .map(note -> new NoteRecognizerImpl(note, noteSpellChecker))
            .collect(Collectors.toList());
}
}

The spring boot application failed to be started due to the error of initialization of bean, but the JVM still is running without exiting. So the daemon app(which starts the spring boot app) does not aware of the fatal exception of my app.

Below is the out in console,

2017-04-28 17:36:54.483 ERROR [magiceye-server,,,] 32444 --- [
main] o.s.boot.SpringApplication : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.noteSpellChecker' defined in file [/.../service/impl/NoteSpellChecker.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [service.impl.NoteSpellChecker]: Constructor threw exception; nested exception is java.io.IOException at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:279) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:345) at org.springframework.cloud.context.scope.GenericScope$BeanLifecycleWrapper.getBean(GenericScope.java:359) at org.springframework.cloud.context.scope.GenericScope.get(GenericScope.java:176) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081) at org.springframework.cloud.context.scope.refresh.RefreshScope.start(RefreshScope.java:121) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:253) at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:174) at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:137) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:337) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:882) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) at BackendApplication.main(BackendApplication.java:21) Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [service.impl.NoteSpellChecker]: Constructor threw exception; nested exception is java.io.IOException at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271) ... 32 common frames omitted Caused by: java.io.IOException: null at service.impl.NoteSpellChecker.(NoteSpellChecker.java:69) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142) ... 34 common frames omitted

1
what do you mean by "the app still is running though the bean was failed to be injected" do u have (required = false) where you inject this bean?pvpkiran
@pvpkiran Could you give me more hints about required = false? I added code snippet to demonstrate how inject that bean.Kane
couple of questions. 1. When you say the app is still running, can u reach any of the rest endpoints for example(I don't think so)? 2. Are you using(@Autowire) this bean NoSpellChecker in some other class?pvpkiran
@pvpkiran, added more detail in question, pls check. Thanks.Kane
During the time when it is initializing you say your application is running, does it mean you can access any of the rest endpoints ? I am sorry, I cannot reproduce this issue. when i tried, the application wouldn't start until the bean is initialized.pvpkiran

1 Answers

0
votes

I found that it was caused by a daemon thread started by a third party library.