Spring-boot: "IllegalArgumentException: Bean factory must allow eager class loading" with 1.5.2.RELEASE when using JRebel

Created on 3 Mar 2017  路  39Comments  路  Source: spring-projects/spring-boot

A project of mine does not start with 1.5.2 anymore. With 1.5.1 it runs fine.

I start the application like this:

package tld.mine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(final String... args) {
        SpringApplication.run(App.class, args); // this is line 10
    }
}

The exceptions thrown are here:

[ERROR] [03.03.17 20:08:35]          SpringApplication.java:815  Application startup failed
java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:64) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:102) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:178) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:140) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:320) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:524) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.jrLockAndRefresh(AbstractApplicationContext.java) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at tld.mine.App.main(App.java:10) [classes/:?]
Caused by: java.lang.IllegalArgumentException: Bean factory must allow eager class loading
    at org.springframework.util.Assert.isTrue(Assert.java:92) ~[spring-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.get(BeanTypeRegistry.java:93) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:185) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:171) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:139) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:110) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    ... 19 more
[ WARN] [03.03.17 20:08:35]  AbstractApplicationContext.java:1005 Exception thrown from LifecycleProcessor on context close
java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@58fb7731: startup date [Fri Mar 03 20:08:33 UTC 2017]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:417) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1002) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:961) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:794) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:325) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at tld.mine.App.main(App.java:10) [classes/:?]
[ERROR] [03.03.17 20:08:35]  DefaultSingletonBeanRegistry.java:581  Destroy method on bean with name 'org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory' threw an exception
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@58fb7731: startup date [Fri Mar 03 20:08:33 UTC 2017]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:404) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.destroySingletons(AbstractBeanFactory.java) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1033) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1009) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:961) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:794) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:325) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at tld.mine.App.main(App.java:10) [classes/:?]

invalid

Most helpful comment

The issue should now be resolved in the latest nightly build. You can download the nightly from here.

All 39 comments

Sorry but that's not enough for us to figure out what went wrong. Can you please share a sample that we can run?

@yglodt That's a result of this change: https://github.com/spring-projects/spring-boot/issues/8439. Can you please describe how and why you have customised your application's bean factory?

Specifically are you calling setAllowEagerClassLoading(false) (and if so, why)

@philwebb setAllowEagerClassLoading() does not occur in my code
@snicoll I can unfortunately not share the code. It's part of a larger application which I can not easily dissect

I will try to figure out if there is any special bean factory stuff and comment back.

I don't see anything special in my configuration, just the usual @Bean.

I use the following configuration annotations, spread over several config classes:

@Configuration
@EnableJdbcHttpSession(maxInactiveIntervalInSeconds = 86400, tableName = "spring_session")
@EnableWebSocketMessageBroker
@EnableWebSecurity
@EnableScheduling
@EnableAsync
@ComponentScan(basePackages = "tld.mine")

Something must be setting it to false. Can you please try debugging your app with a breakpoint on the setter in DefaultListableBeanFactory and see what's calling it?

This is what I came up with so far. Is it of any help?

ex01

Is it of any help?

Not much, unfortunately. I can see that you've got the required breakpoint in place, but, judging by the stack of the suspended thread, it wasn't tripped. That's rather baffling as they field's value defaults to true yet the failure you're seeing requires the value to be false.

Can you please try debugging again with a breakpoint on the field itself. Eclipse should then suspend the thread whenever the field is accessed or modified. It's when it's modified that's of particular interest (although it would also be interesting to have confirmation that's its value is true when it's first accessed).

Hi all

I have a similar situation in my project. It won't start anymore with spring boot 1.5.2. Nothing I'm aware of is explicitly setting allowEagerClassLoading to false.

The problem occurs when ConfigurationClassBeanDefinitionReader is attempting to load the bean definition (loadBeanDefinitionsForConfigurationClass) for configuration class ConfigurationPropertiesRebinderAutoConfiguration.

While doing it's work, OnBeanCondition.collectBeanNamesForType calls BeanTypeRegistry.get(beanFactory). It's third line asserts listableBeanFactory.isAllowEagerClassLoading() is true. Funnily it returns false even though I can see the property of listableBeanFactory is set to true in the debugger.

spring_boot_1 5 2_issue_8488

The debugger does not even jump into listableBeanFactory.isAllowEagerClassLoading(). Some proxy issue?

You can check it out here: https://github.com/ursjoss/sipamato/tree/tb_spring_boot_1_5_2. Start the project with profile DB_JOOQ.

HTH. Thanks and cheers, Urs

@ursjoss Thanks very much. I've just tried your app and it started successfully for me using the DB_JOOQ profile. With a breakpoint set at the same point as you it suspends the VM at the exact same point as you, however it returns true in my case having gone into isAllowEagerClassLoading() as expected. I'm currently at a loss to explain the difference in behaviour.

@ursjoss and @yglodt What OS and JVM are you running on? I tried on OS X using Oracle JDK 8 (1.8.0_121-b13).

@wilkinsona Thanks for investing time on this.

OS: Arch Linux (4.9.11-1-ARCH #1 SMP PREEMPT x86_64 GNU/Linux), JDK: openjdk version "1.8.0_121"
OpenJDK Runtime Environment (build 1.8.0_121-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)

By the way: Followin your pm, I did another attempt of debugging. Even before, I had a breakpoint in the setter and getter for allowEagerClassLoading. Both break points never tripped. Now I also set a break point on the field declaration/initialization (DefaultListableBeanFactory line 153). The debugger did stop there and the field was initialized to true.

Later I'll give it a go to run the project on windows, to see the behavior there...

@wilkinsona I can confirm the project starts without flaw on Windows: java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

How can we proceed?

By the way: Sorry for not mentioning the snapshot dependency on wicket-bootstrap

I run Fedora 25 with their packaged OpenJDK 64-Bit Server VM (build 25.121-b14, mixed mode)

so looks like something openjdk/linux specific

@yglodt Are you able to verify whether your project works on a non-Linux machine?

I'm going to try out mine with oracle-jdk on linux to try narrowing the issue down...

@ursjoss Yes I can do that, tomorrow. I have no Windows machine available here.

We are using latest spring boot 2.x snapshot and it is throwing same error for me. It worked with earlier snapshot. Here is system info.

$ uname -a; java -version; Darwin sanbook.local 16.3.0 Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64 x86_64 i386 MacBookPro13,3 Darwin java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

We haven't specified any customization of bean factory and not calling setAllowEagerClassLoading(false) anywhere.

I tried to create a simple project with basic dependency but couldn't reproduce the issue. So I guess some dependency we have may be causing this issue.

I installed oracle-jdk on my archlinux machine.

java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

Switching back and forth between openjdk and oracle-jdk, I noticed the following:

  • Running the project via maven works (mvn clean install && mvn spring-boot:run), regardless of the jdk.
  • Running the project through STS Boot dashboard fails, also regardless of the jdk.

My STS:

Version: 3.8.3.RELEASE
Build Id: 201612191351
Platform: Eclipse Neon.2 (4.6.2)

So it now looks like this isn't specific to Linux (@brsanthu has the problem on mac OS) or Open JDK.

@ursjoss In light of your latest update, I've had another attempt at reproducing the problem on mac OS using the Oracle JDK and STS 3.8.3.RELEASE but without any joy. I've also tried on Fedora 25 running via mvn spring-boot:run and java -jar with no joy either.

@brsanthu and @yglodt How are you launching your apps when they fail?
@ursjoss Does yours fail in STS if you launch as a Java application rather than through the STS dashboard?

@wilkinsona good point:

  • Running the app via STS as _java application_ works flawlessly
  • running it as spring boot app (RunAs -> Spring Boot App) or via Boot Dashboard doesn't.

Tested on linux using openjdk.

@ursjoss Thanks.

Running as a Spring Boot app sets a few system properties:

  • -Dcom.sun.management.jmxremote
  • -Dcom.sun.management.jmxremote.port=64131
  • -Dcom.sun.management.jmxremote.authenticate=false
  • -Dcom.sun.management.jmxremote.ssl=false
  • -Dspring.liveBeansView.mbeanDomain
  • -Dspring.application.admin.enabled=true
  • -Djava.security.egd=file:/dev/./urandom
  • -Dfile.encoding=UTF-8

It also adds a program argument:

  • --spring.output.ansi.enabled=always

I would guess, although I can't explain why, that it's one or more of these that's causing the change in behaviour. Would you mind experimenting with running as a Java application using these system properties to see if you can narrow things down a bit further?

/cc @kdvolder @martinlippert who work on STS

I run it in Eclipse as Java application. Note that I use JRebel. I have not yet tried if it behaves different without JRebel.

@wilkinsona I tried those parameters on the command line. All went fine.

It then started to play with the parameters in the boot dashboard and found that it's actually JRebel.

Removing the jrebel-agent both on linux and on windows resulted in successfully launching the application - and vice versa: adding jrebel-agent on windows and launching the app through the boot dashboard resulted in the same failure as on linux.

I have opened a ticket with JRebel referring to this thread.

Thanks a lot to all involved in nailing down this issue.

Yes, removing the ${jrebel_args} parameter successfully starts the app for me too.

Thanks, everyone.

@ursjoss Is the ticket that you opened against JRebel publicly accessible? I'd like to be able to follow that discussion as it might influence what we decide to do here. If it's going to take a while for the problem to be fixed, a note in the documentation may be in order.

@wilkinsona I have opened the ticket via JRebel Eclipse plugin (which defaults to sending the relevant logs etc.). I (still) have the same question about gettting a ticket number and being able to track the status of the ticket. I have not heard from ZeroTurnAround since. I will ask them via twitter if I don't hear from them by tomorrow.

Hi, i'm Risto from ZeroTurnaround support team. We have opened a ticked for this issue and are working on getting it fixed. Unfortunately there is no public jira available, but i will keep you informed about the progress.

The issue should now be resolved in the latest nightly build. You can download the nightly from here.

That was quick! Thanks very much, @Ristop.

I can confirm the nightly build solves the issue in my case. Thanks @Ristop

Can confirm that with new build it is working for Spring Boot 2.x.x snapshot version too.

The same problem, waiting for jrebel release.

I can confirm that the JRebel Agent 7.0.6-SNAPSHOT (201703081621) nightly release fixes the bug in IntelliJ.

So do I, thanks a lot guys

Thanks a lot everyone!

I was having the same problem. Thanks~

I was having the same problem. Thanks~

Thanks, this fixed it for me.

Was this page helpful?
0 / 5 - 0 ratings