Edit: The issue is only relevant from Spring Boot 3.0.0 to 3.0.2. It has been addressed in 3.0.3. See last section for details.
I have a very simple Spring Boot 3.0.2 app with only janino as added dependency. When I use an if-else conditional in the logback configuration, then no logs are printed by logback when the application is run as a native image. However, printing with System.out
works fine.
For compilation all reachability metadata has been provided that was given by the tracing agent when running the jar in the JVM. The application exits with a return code of 0.
Without an if-else condition, everything works as expected.
My questions are:
The logback-spring.xml
with a conditional just to have a conditional:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<if condition='property("WITH_DEBUG").equalsIgnoreCase("true")'>
<then>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
</then>
<else>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
</else>
</if>
</configuration>
The main (and only) class:
@SpringBootApplication
public class LogbackIfElseApplication {
private static final Logger LOG = LoggerFactory.getLogger(LogbackIfElseApplication.class);
public static void main(String[] args) {
SpringApplication.run(LogbackIfElseApplication.class, args);
}
@Bean
ApplicationRunner applicationRunner() {
return args -> {
LOG.info("Hello Logback!");
System.out.println("Hello stdout");
};
}
}
My build script:
plugins {
java
id("org.springframework.boot") version "3.0.2"
id("io.spring.dependency-management") version "1.1.0"
id("org.graalvm.buildtools.native") version "0.9.18"
}
group = "foo"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.codehaus.janino:janino")
}
The full code is available in this github repo.
When run in the JVM without any further parameters, the output is as follows but shortened for conciseness:
$ java -jar build/libs/logback-if-else-0.0.1-SNAPSHOT.jar
INFO --- [main] foo.LogbackIfElseApplication : Starting LogbackIfElseApplication using Java 17.0.5 with PID 5905
INFO --- [main] foo.LogbackIfElseApplication : No active profile set, falling back to 1 default profile: "default"
INFO --- [main] foo.LogbackIfElseApplication : Started LogbackIfElseApplication in 0.946 seconds (process running for 1.352)
INFO --- [main] foo.LogbackIfElseApplication : Hello Logback!
Hello stdout
When run as a native image, the full output is just
$ build/native/nativeCompile/logback-if-else
Hello stdout
Thanks to Andy's fix, the application no longer starts up without logging but fails early and logs
Logging system failed to initialize using configuration from 'null'
java.lang.IllegalStateException: Logback configuration error detected:
ERROR in ch.qos.logback.core.model.processor.conditional.IfModelHandler - Failed to parse condition [property("WITH_DEBUG").equalsIgnoreCase("true")] on line 3 org.codehaus.commons.compiler.InternalCompilerException: SNO: Generated compilation unit does not declare class 'SC'
at org.springframework.boot.logging.logback.LogbackLoggingSystem.reportConfigurationErrorsIfNecessary(LogbackLoggingSystem.java:261)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initializeFromAotGeneratedArtifactsIfPossible(LogbackLoggingSystem.java:212)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:187)
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:332)
at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
at java.base@17.0.5/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:352)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
at foo.LogbackIfElseApplication.main(LogbackIfElseApplication.java:16)
Exception in thread "main" java.lang.IllegalStateException: java.lang.IllegalStateException: Logback configuration error detected:
ERROR in ch.qos.logback.core.model.processor.conditional.IfModelHandler - Failed to parse condition [property("WITH_DEBUG").equalsIgnoreCase("true")] on line 3 org.codehaus.commons.compiler.InternalCompilerException: SNO: Generated compilation unit does not declare class 'SC'
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:347)
at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
at java.base@17.0.5/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:352)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
at foo.LogbackIfElseApplication.main(LogbackIfElseApplication.java:16)
Caused by: java.lang.IllegalStateException: Logback configuration error detected:
ERROR in ch.qos.logback.core.model.processor.conditional.IfModelHandler - Failed to parse condition [property("WITH_DEBUG").equalsIgnoreCase("true")] on line 3 org.codehaus.commons.compiler.InternalCompilerException: SNO: Generated compilation unit does not declare class 'SC'
at org.springframework.boot.logging.logback.LogbackLoggingSystem.reportConfigurationErrorsIfNecessary(LogbackLoggingSystem.java:261)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initializeFromAotGeneratedArtifactsIfPossible(LogbackLoggingSystem.java:212)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:187)
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:332)
... 19 more
At the time of writing, Janino does not work when building a native image of your Spring Boot application. The problem is being tracked in this Spring Boot issue.