log4j2 not working in spring boot application

Viewed 11126

I am trying to use log4j2 instead of logback in my spring application but it keep throwing error. The pom file looks like

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.7.RELEASE</version>
    <relativePath /> 
</parent>

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

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
</dependencies>

The log4j2 xml files looks like

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="60">
    <Properties>
        <Property name="path">logs</Property>
    </Properties>
    <Appenders>
        <Console name="Console-Appender" target="SYSTEM_OUT">
            <PatternLayout>
                <pattern>
                    [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
                </pattern>>
            </PatternLayout>
        </Console>
        <File name="App-Appender" fileName="${path}/app_log.log" >
            <PatternLayout>
                <pattern>
                    [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
                </pattern>
            </PatternLayout>
        </File>
        <File name="SpringBoot-Appender" fileName="${path}/springboot_log.log" >
            <PatternLayout>
                <pattern>
                    [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
                </pattern>
            </PatternLayout>
        </File>
    </Appenders>
    <Loggers>
        <Logger name="master.dt" level="info" additivity="false">
            <AppenderRef ref="SpringBoot-Appender"/>
            <AppenderRef ref="Console-Appender"/>
        </Logger>
        <Logger name="master.dt" level="info" additivity="false">
            <AppenderRef ref="App-Appender"/>
            <AppenderRef ref="Console-Appender"/>
         </Logger>
        <Root>
            <AppenderRef ref="Console-Appender"/>
        </Root>
    </Loggers>
</Configuration>

however when i run the spring boot app it throws an error

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/asd.asd/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.6.2/log4j-slf4j-impl-2.6.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/asd.asd/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
[WARNING] 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:483)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.apache.logging.slf4j.Log4jLoggerFactory loaded from file:/Users/karan.shah/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.6.2/log4j-slf4j-impl-2.6.2.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml Object of class [org.apache.logging.slf4j.Log4jLoggerFactory] must be an instance of class ch.qos.logback.classic.LoggerContext
    at org.springframework.util.Assert.isInstanceOf(Assert.java:346)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:221)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLogger(LogbackLoggingSystem.java:213)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:98)
    at org.springframework.boot.logging.LoggingApplicationListener.onApplicationStartedEvent(LoggingApplicationListener.java:222)

I followed multiple blog but none of them are working. What is the correct way to get log4j2 work?

5 Answers

Exclude the default spring boot starter logging dependency from spring boot starter web dependency also.

<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 faced this issue in Microservice based project which is based on many services. Because of lot of conflicts between log4j, slf4j , apache common logging etc. Hence log files is not creating even sufficient privileged are there. First run command to resolved the jar conflict from dependency tree.

**mvn dependency:tree**
Exclude those jars from spring-boot starter dependencies and other component dependencies.

Following Code is perfectly working for me after lot of struggle.

<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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

****Log4j.xml files:****

        <?xml version="1.0" encoding="UTF-8"?>
        <Configuration>
            <Appenders>
                <Console name="Console" target="SYSTEM_OUT">
                    <PatternLayout
                        pattern="%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{1.}}{bright,yellow}: %msg%n%throwable" />
                </Console>

                <RollingFile name="RollingFile"
                    fileName="./logs/gateway-log4j2.log"
                    filePattern="./logs/$${date:yyyy-MM}/spring-boot-logger-log4j2-%d{-dd-MMMM-yyyy}-%i.log.gz">
                    <PatternLayout>
                        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
                    </PatternLayout>
                    <Policies>
                        <!-- rollover on startup, daily and when the file reaches 
                            10 MegaBytes -->
                        <OnStartupTriggeringPolicy />
                        <SizeBasedTriggeringPolicy
                            size="10 MB" />
                        <TimeBasedTriggeringPolicy />
                    </Policies>
                </RollingFile>
            </Appenders>

            <Loggers>
                <!-- LOG everything at INFO level -->
                <Root level="info">
                    <AppenderRef ref="Console" />
                    <AppenderRef ref="RollingFile" />
                </Root>

                <!-- LOG "com.mytest.project*" at TRACE level -->
                <Logger name="com.mytest.project" level="trace"></Logger>
            </Loggers>

        </Configuration>

        Try it. It perfectly working for me.

You have a jar conflict with slf4j. Look at your dependency tree to figure out which jar to exclude.

This problem like me mad for an hour. There are very less probability that you might be having any issue with log4j2.xml or log4j2-spring.xml. Most likely problem is in your pom.

I would suggest to run mvn:dependeny:tree and exclude spring-boot-starter-logging from all the dependencies in your class path.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

I hope this would help. No need to explicitly give logging config file location in application.properties unless it is outside your project classpath.

You put a double ending bracket in the Console layout definition in your log4j.xml file : it should be corrected first.

Related