I have a spring application and there is a scheduled logic which produces prototype beans at fixed rate.
Everything works fine on my laptop but after deploying it to server my app fails to start due to:
2016-12-13 04:13:01.885 ERROR 4688 --- [TaskScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
...
BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'metaDataSourceAdvisor': Singleton bean creation not allowed
while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
...
This is the first scheduled call. Looks like a timing issue. On my laptop application initializes much faster and nothing wrong happens for the first scheduled call (which produces prototype beans).
Is there a way to get to know the current state of Spring bean creation flow so I can check it in scheduled logic and produce nothing when app creation is not finished?
Thanks!
Looking at the Spring source (4.3.3 and 4.2.2) this only happens in one location DefaultSingletonBeanRegistry.getSingleton(), and only when the initialisation of the spring context has failed, or you have explicitly closed it. Spring uses a single thread (the calling thread) for creating your beans and invoking the start lifecycle methods, so the exception you found should only be possible if you violate this principle.
I have seen a lot of developers that start threads in a bean constructor, this is a very bad idea. If you have a bean with lifecycle (thread, resource pool), you should always use the LifeCycle interface, and create your resource in start(), and clean it up in stop(). This is a good idea because start() is called after every eager singleton has been instantiated and the context completely wired, so no threads gets created unless every bean can be constructed.