'log4j 1.2 to log4j 2 migration not working

I am trying to migrate log4j from 1 to 2 and logs are not generated. I removed actual path of writing and application able to write the logs the mentioned path since logs are not printing after upgrade only Legacy code contains Parent Pom

<!-- 
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
-->

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-1.2-api</artifactId>
    <version>2.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.16.0</version>
</dependency>

Child POM: - Updated version only

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-ext</artifactId>
    <!--  <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jcl</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>

<!-- 
<dependency> 
    <groupId>org.slf4j</groupId> 
    <artifactId>slf4j-log4j12</artifactId> 
    <version>1.7.5</version> 
    </dependency> 
-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>

log4j -> xml

<log4j:configuration>
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="DEBUG" />
            <param name="LevelMax" value="INFO" />
            <param name="AcceptOnMatch" value="true" />
        </filter>
    </appender>

    <appender name="errout" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.Err" />
        <param name="Threshold" value="WARN" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
        </layout>
    </appender>

    <appender name="userLog" class="com.test.RollingFileAppender">
        <param name="File" value="userlogs.log" />
        <param name="Threshold" value="INFO" />
        <param name="MaxFileSize" value="50MB" />
        <param name="MaxBackupIndex" value="5" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%m | [%d{ISO8601}] | [%t]%n" />
        </layout>
    </appender>

    <appender name="errorLog" class="com.test.RollingFileAppender">
        <param name="File" value="error.log" />
        <param name="Threshold" value="ERROR" />
        <param name="MaxFileSize" value="50MB" />
        <param name="MaxBackupIndex" value="10" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{ISO8601}] [%t] %-5p %c{1}: - %m%n" />
        </layout>
    </appender>

    <category name="REQUEST_LOG" additivity="false">
        <priority value="INFO" />
        <appender-ref ref="userLog" />
    </category>

    <root>
        <priority value="INFO" />
        <appender-ref ref="errorLog" />
    </root>

</log4j:configuration>

We initialized log4j programatically

import java.io.File;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.xml.DOMConfigurator;

import ApplicationContext;
import ResourceUtility;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.LogManager;

public class Initializer implements Startable {

    private static Log logger = null;
    private static boolean logsPathSet = false;

    private static String logsPath = "";

    static {
        BasicConfigurator.configure();
        logger = LogFactory.getLog(Initializer.class);
    }

    public static void initialize() {
        logsPath = System.getProperty("log4j.configuration","");
        logsPathSet = (logsPath != null && !logsPath.equals(""));
        initializeLogging();
        ApplicationContext.getInstance();
    }

    public static void initializeLogging() {
        String configFile = "";
        URL aURL  = null;
        
        if ( logsPathSet ) {
            configFile  = logsPath;
            aURL = ResourceUtility.geUrlResource(configFile);
        }
        
        if ( (!logsPathSet) || ( logsPathSet && aURL == null) ) {
            configFile = ApplicationContext.getInstance().getStringProperty("logging", "log4j", "configFile");
            aURL = ResourceUtility.geUrlResource(configFile);
        }
        DOMConfigurator.configure(aURL);
        logger = LogFactory.getLog(Initializer.class);
        logger.info("Configured Logging from: " + aURL);
    }
}


import java.io.File;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;

import ApplicationContext;
import Initializer;
import ResourceUtility;

    public class Startup extends HttpServlet {
    
        private static Log logger = LogFactory.getFactory().getInstance(Startup.class);
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
        
        public void init() throws ServletException {
            super.init();
            ApplicationContext.getInstance();
            Initializer.initialize();
            String loggingProperty = "/" + ApplicationContext.getInstance().getProperty("logging", "log4j", "configFile");
            loggingFile = ResourceUtility.getFileResource(loggingProperty);
            PropertyConfigurator.configure(loggingFile.toString());
        }
    
    }

I tried with couple of approach. Approach 1 -> Migrating log4j 1 to 2 directly and updated log4j connfig

System.out -> SYSTEM_OUT -> tried with bith target

Updated log4j xml file

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="console" target="System.out">
            <PatternLayout pattern="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
            <LevelRangeFilter minLevel="DEBUG" maxLevel="INFO" onMatch="ACCEPT" onMismatch="NEUTRAL" />
        </Console>
        <Console name="consoleError" target="System.Err" follow="true">
            <PatternLayout pattern="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
            <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="NEUTRAL" />
        </Console>

        <RollingFile name="userLog" fileName="/userlogs.log"  filePattern="/userlogs.log.%d{yyyyMMdd}">
            <PatternLayout pattern="%m | [%d{ISO8601}] | [%t]%n" />
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY" />
        </RollingFile>
            
        <RollingFile name="errorLog" fileName="/error.log"  filePattern="/error.log.%d{yyyyMMdd}">
            <PatternLayout pattern="[%d{ISO8601}] [%t] %-5p %c{1}: - %m%n" />
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
        </RollingFile>
    </Appenders>

    <Loggers>
        <Logger name="REQUEST_LOG" additivity="false">
            <AppenderRef  ref="userRequestLog" level="INFO" />
        </Logger>
        <Root  level="INFO">
            <AppenderRef  ref="errorLog"/>
        </Root >
    </Loggers>
</Configuration>

Updated Initalizer class

//BasicConfigurator.configure();
Configurator.initialize(new DefaultConfiguration());

// DOMConfigurator.configure(aURL);
        
LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
loggingFile = ResourceUtility.getFileResource(configFile);
context.setConfigLocation(loggingFile.toURI());
context.reconfigure();

ConfigurationFactory.setConfigurationFactory(new XmlConfigurationFactory());
Configurator.reconfigure(loggingFile.toURI());

Updated startup into

// PropertyConfigurator.configure(loggingFile.toString());
        ConfigurationFactory.setConfigurationFactory(new XmlConfigurationFactory());
        LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
        //Configurator.reconfigure(loggingFile.toURI());
        context.setConfigLocation(loggingFile.toURI());
        context.reconfigure();

Logs are not generated for the above approach

Approach 2 -> Same changes by adding bridge jar -> skipped log4j xml changes

Thanks in advance for any recommendation or changes or approach or can you please share steps you followed while migrate the same or share the approach with minimal code changes.



Solution 1:[1]

I'd advise to follow the second approach, but you have to use log4j 2.17.2+ version. The bridge jar has big issues in previous versions, but the devs made an effort at the start of this year to fix it. I would have made this a comment rather than an answer, but have low reputation.

In my case it was possible to make a simple jar file and overwrite the existing log4j version 1 jars with it on 200 running apps without changing any config files in the apps or on app server. How is that for an "approach with minimal code changes" :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1