Spring boot logging when logback and log4j2 both in classpath

Viewed 271

In my spring boot project , I have configured the logging via log4j2 using following dependency

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
         <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
         </exclusions>
    </dependency>

I have added log4j2 and slf4j jar explicitly. I am also using jxls which uses logback. So its included as a transient dependency.

On startup spring tries to configure logging using LoggingSystem

public static LoggingSystem get(ClassLoader classLoader) {
        String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
        if (StringUtils.hasLength(loggingSystem)) {
            if (NONE.equals(loggingSystem)) {
                return new NoOpLoggingSystem();
            }
            return get(classLoader, loggingSystem);
        }
        return SYSTEMS.entrySet().stream().filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader))
                .map((entry) -> get(classLoader, entry.getValue())).findFirst()
                .orElseThrow(() -> new IllegalStateException("No suitable logging system located"));
    }

Now since I have not explicitly set LoggingSystem it default picks logback from the SYSTEMS map.

static {
        Map<String, String> systems = new LinkedHashMap<>();
        systems.put("ch.qos.logback.core.Appender", "org.springframework.boot.logging.logback.LogbackLoggingSystem");
        systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
                "org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
        systems.put("java.util.logging.LogManager", "org.springframework.boot.logging.java.JavaLoggingSystem");
        SYSTEMS = Collections.unmodifiableMap(systems);
    }

The only way I found to make it choose log4j is to pass VM param like this -Dorg.springframework.boot.logging.LoggingSystem=org.springframework.boot.logging.log4j2.Log4J2LoggingSystem”

Even if I add this in application properties its not picked since logging is configured even before app context is loaded.

So my questions is if I am using logback ( direct or transitively ) i have to pass this VM flag to ensure spring boot choose log4j2.

0 Answers
Related