HashimR
HashimR

Reputation: 3833

Load Log4j2 configuration file programmatically

I want to load Log4j2 XML configuration file programmatically from my application.

Tried this:

ConfigurationSource source = new ConfigurationSource();
source.setLocation(logConfigurationFile);
Configurator.initialize(null, source);

and this:

ConfigurationSource source = new ConfigurationSource();
source.setLocation(logConfigurationFile);
ConfigurationFactory factory = (ConfigurationFactory) XMLConfigurationFactory.getInstance().getConfiguration(source);
ConfigurationFactory.setConfigurationFactory(factory);

But nothing works yet.

Upvotes: 50

Views: 75593

Answers (9)

I tried all the other solutions nothing worked for me.

tried Log4jServletContextListenerImpl extending Log4jServletContextListener @lonxx said able to write logs but not able to read environmental bean from spring context.

As log4j context is initializing before spring context initialization.

So Placed the below code in init(ServletConfig config) of InitServlet extends HttpServlet.

LoggerContext context = (LoggerContext) 
LogManager.getContext(false);
File file = new File("relativepath/log4j2/log4j2.xml");
context.setConfigLocation(file.toURI());

Now it's working.

using spring 5.3.22 & log4j2 2.17.2 and initservlet is configured in web.xml version ="2.5"

Upvotes: 0

zeroboo
zeroboo

Reputation: 8945

If you config with .properties file:

String propertiesFile = "./test/Configuration/log4j2.properties";  
ConfigurationSource source = new ConfigurationSource(new FileInputStream(propertiesFile), new File(propertiesFile));
Configurator.initialize(null, source);

Upvotes: 3

k_rollo
k_rollo

Reputation: 5472

Below worked for me, Log4j2 with SLF4J wrapper:

Solution 1:

public class MyClass {

    static {
        try {
            InputStream inputStream = new FileInputStream("C:/path/to/log4j2.xml");
            ConfigurationSource source = new ConfigurationSource(inputStream);
            Configurator.initialize(null, source);
        } catch (Exception ex) {
            // Handle here
        }
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class); // LogManager if not using SLF4J

    public void doSomething() {
        LOGGER.info(...)
    }

}

Solution 2:

static {
    File log4j2File = new File("C:/path/to/log4j2.xml");
    System.setProperty("log4j2.configurationFile", log4j2File.toURI().toString());
}

Need toURI() to follow File URI Scheme format, else it throws MalformedURLException.

Sources:

Upvotes: 11

Cristian Florescu
Cristian Florescu

Reputation: 1816

Considering - https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/config/Configurator.html

Configurator.initialize(null, "classpath:conf/logger.xml");
or
Configurator.initialize(null, "/full_path/conf/logger.xml");

Be aware and does not use both at the same time.

Upvotes: 3

TJR
TJR

Reputation: 3773

final URL log4j = Resources.getResource("log4j2-test.xml");
LoggerContext.getContext(false)
  .start(new XmlConfiguration(new ConfigurationSource(
    Resources.asByteSource(log4j).openStream(),
    log4j)));

Upvotes: 1

lanoxx
lanoxx

Reputation: 13041

If you are using a Servlet 3.0 Web Application you can use the Log4jServletContextListener and do the following:

Write a custom LogContextListener which extends from Log4jServletContextListener, set it up in your web.xml and disable auto initialization:

<listener>
    <listener-class>com.example.LogContextListener</listener-class>
</listener>
<context-param>
    <param-name>isLog4jAutoInitializationDisabled</param-name>
    <param-value>true</param-value>
</context-param>

In your custom LogContextListener overwrite contextInitialized and set the config location

public void contextInitialized(ServletContextEvent event) { 
    /* Some logic to calculate where the config file is saved. For 
     * example you can read an environment variable.
     */
    String pathToConfigFile = ... + "/log4j2.xml";
    Configurator.initialize(null, pathToConfigFile);
    super.contextInitialized(event);
}

The advantage over configuring the location directly in the web.xml is that you can compute the path based on some additional information and access the log4j2.xml even if its outside of your classpath.

Upvotes: 5

switch_java3
switch_java3

Reputation: 479

For the newest version of log4j, here is what should work for loading an external log4j2.xml:

String log4jConfigFile = System.getProperty("user.dir") + File.separator + "log4j2.xml";
ConfigurationSource source = new ConfigurationSource(new FileInputStream(log4jConfigFile));
Configurator.initialize(null, source);

Upvotes: 45

dcompiled
dcompiled

Reputation: 4832

If you have a single main entry point, this code snippet might save you some trouble. The set property call must fire before any loggers are created. This approach works with files on the classpath.

public class TestProcess {
    static {
        System.setProperty("log4j.configurationFile", "log4j-alternate.xml");
    }

    private static final Logger log = LoggerFactory.getLogger(TestProcess.class);

}

Upvotes: 25

HashimR
HashimR

Reputation: 3833

Found the answer myself. Someone might find it useful.

ConfigurationSource source = new ConfigurationSource();
source.setLocation(logConfigurationFile);
source.setFile(new File(logConfigurationFile));
source.setInputStream(new FileInputStream(logConfigurationFile));
Configurator.initialize(null, source);

Upvotes: 18

Related Questions