There is minimal SpringBoot + Gradle application
plugins {
java
id("org.springframework.boot") version "3.1.5"
id("io.spring.dependency-management") version "1.1.3"
id("org.graalvm.buildtools.native") version "0.9.27"
}
group = "com.example"
version = "0.0.7"
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
}
tasks {
bootBuildImage {
builder.set("paketobuildpacks/builder-jammy-tiny:latest")
}
}
application.properties
looks like
logging.config=classpath:logback-aaa.xml
and single java file
package com.example.springlogbacknative;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringLogbackNativeApplication {
public static Logger log = LoggerFactory.getLogger(SpringLogbackNativeApplication.class);
public static void main(String[] args) {
System.out.println("System.getenv(\"LOGGING_CONFIG\") = " + System.getenv("LOGGING_CONFIG"));
System.out.println("System.getenv(\"logging.config\") = " + System.getenv("logging.config"));
SpringApplication.run(SpringLogbackNativeApplication.class, args);
}
}
After building this project with command ./gradlew bootBuildImage
and running with following docker compose file
services:
sln:
image: spring-logback-native:0.0.7
environment:
LOGGING_CONFIG: "classpath:logback-replace.xml"
logging.config: "classpath:logback-replace.xml"
No replacement happens.
System.getenv("LOGGING_CONFIG") = classpath:logback-replace.xml
System.getenv("logging.config") = classpath:logback-replace.xml
14:21:46,499 |-INFO in ch.qos.logback.classic.LoggerContext[default] - This is logback-classic version 1.4.11
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Here is a list of configurators discovered as a service, by rank:
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - org.springframework.boot.logging.logback.RootLogLevelConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - They will be invoked in order until ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY is returned.
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Constructed configurator of type class org.springframework.boot.logging.logback.RootLogLevelConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - org.springframework.boot.logging.logback.RootLogLevelConfigurator.configure() call lasted 0 milliseconds. ExecutionStatus=INVOKE_NEXT_IF_ANY
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Trying to configure with ch.qos.logback.classic.joran.SerializedModelConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Instantiation failure: java.lang.ClassNotFoundException: ch.qos.logback.classic.joran.SerializedModelConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Trying to configure with ch.qos.logback.classic.util.DefaultJoranConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Instantiation failure: java.lang.ClassNotFoundException: ch.qos.logback.classic.util.DefaultJoranConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Trying to configure with ch.qos.logback.classic.BasicConfigurator
14:21:46,500 |-INFO in ch.qos.logback.classic.util.ContextInitializer@132da9ab - Instantiation failure: java.lang.ClassNotFoundException: ch.qos.logback.classic.BasicConfigurator
14:21:46,531 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - Processing appender named [console_aaa]
14:21:46,531 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
14:21:46,532 |-INFO in ch.qos.logback.core.model.processor.ImplicitModelHandler - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
14:21:46,532 |-INFO in ch.qos.logback.classic.model.processor.RootLoggerModelHandler - Setting level of ROOT logger to INFO
14:21:46,532 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@ba501d9 - Propagating INFO level on Logger[ROOT] onto the JUL framework
14:21:46,532 |-INFO in ch.qos.logback.core.model.processor.AppenderRefModelHandler - Attaching appender named [console_aaa] to Logger[ROOT]
14:21:46,532 |-INFO in ch.qos.logback.core.model.processor.DefaultProcessor@5e495062 - End of configuration.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.5)
14:21:46.534 AAA INFO c.e.s.SpringLogbackNativeApplication - Starting AOT-processed SpringLogbackNativeApplication using Java 17.0.8.1 with PID 1 (/workspace/com.example.springlogbacknative.SpringLogbackNativeApplication started by cnb in /workspace)
14:21:46.534 AAA INFO c.e.s.SpringLogbackNativeApplication - No active profile set, falling back to 1 default profile: "default"
14:21:46.542 AAA INFO c.e.s.SpringLogbackNativeApplication - Started SpringLogbackNativeApplication in 0.033 seconds (process running for 0.046)
I would expect logging.config=classpath:logback-aaa.xml
from application.properties replaced with ENV LOGGING_CONFIG: "classpath:logback-replace.xml"
provided in docker compose file.
My investigation end inside org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem
where String logConfig = environment.getProperty(CONFIG_PROPERTY);
IMHO should return replaced path. And it works in NON native environment.
This is the expected behavior when using XML to configure Logback.
The Spring Boot reference documentation contains a section on known limitations. Within this section is a link to a page in Spring Boot's wiki that provides up-to-date information on these limitations, including a section on logging where it says the following:
Logback is supported, including XML configuration. XML configuration is loaded at build time during AOT processing and translated into a fixed, native-friendly format. As a result, loading different XML configuration at runtime is not supported.