'Log4J2 not set as logger in OSGi environment

I am using commons-logging which should bridge to Log4J2 in an OSGi environment and so have added the dependencies, export-package and import-package in the pom.xml as below but the logger does not get set to Log4J2 logger. No errors are shown but when debugged I found it being set to JDK14Logger.

    <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>2.8.2</version>
        </dependency>

        <Export-Package>
            org.apache.logging.log4j.*,
            org.apache.commons.logging.*
        </Export-Package>
        <Import-Package>
            !org.apache.logging.log4j.*,
            !org.apache.commons.logging.*,
            *;resolution:=optional
        </Import-Package>

[UPDATE]

From the log4j user mailing list I could figure out that due to the non-modular nature of ServiceLoader. I checked out a few usages of ServiceLoader in the OSGi environment to find implementations of interfaces but still couldn't get how this could be gotten to work.

I tried it using pax logging as well but the result is the same except for that the logger is now being set to JclLogger



Solution 1:[1]

As Christian said in the other answer, the best fit for logging in OSGI is the pax-logging bundle.

The Pax-logging is built over SLF4J and can be deployed with different possible implementations:

  • pax-logging-log4j2 (Log4J2)
  • pax-logging-logback (Logback)

Before we also used pax-logging-service which was using Log4J version 1 but it is not more recommended as the two other implementations works well.

I personally not tested Logback implementation in OSGI, but Log4j2 is working (with some limitations).

One of the good things with this solution is that you must not import any logging implementation on your bundles, the only things have to you do is:

  • declare slf4j-api as provided dependency (maven scope)
  • declare eventually the slf4j-simple as test scope in your maven

You don't need to tweak any of the maven-bundle-plugin options regarding logging of any of your bundles.

Here are the step how to do it in ServiceMix version 7.0.1; this release uses originally the pax-logging-services but the next step shows what need to be changed.

By installing the bundles in the startup.properties (immediately after boot time) you ensure that all libs are loaded in the beginning.

These two replace the older version of pax-logging-api and pax-logging-service replaced by pax-logging-log4j2:

mvn\:org.ops4j.pax.logging/pax-logging-api/1.11.13 = 8
mvn\:org.ops4j.pax.logging/pax-logging-log4j2/1.11.13 = 8

then in the file: org.ops4j.pax.logging.cfg you mentions just the line:

org.ops4j.pax.logging.log4j2.config.file=${karaf.etc}/log4j2.xml

and add your log4j2.xml file in the ${karaf.etc} folder (installation of servicemix/etc).

You have to copy the libs in the ${karaf.home}/system folder.

This is if you just need a standard log file.

Now come the limitations: if you need to generate your log as json document, I was only able to use the deprecated JSONLayout in the log4j2.xml.

For setting up JSONLayout you can follow my other answer.

In short:

Add the three Jackson dependencies in startup.properties:

mvn\:com.fasterxml.jackson.core/jackson-annotations/2.12.4 = 6
mvn\:com.fasterxml.jackson.core/jackson-core/2.12.4 = 6
mvn\:com.fasterxml.jackson.core/jackson-databind/2.12.4 = 6

and also the pax-logging-log4j2-extra (if you're using log4j2 implementation):

mvn\:org.ops4j.pax.logging/pax-logging-log4j2-extra/1.11.13 = 6

On my version I had to add the three following lines in overrides.properties:

mvn:com.fasterxml.jackson.core/jackson-core/2.12.4;range="[2,3)"
mvn:com.fasterxml.jackson.core/jackson-databind/2.12.4;range="[2,3)"
mvn:com.fasterxml.jackson.core/jackson-annotations/2.12.4;range="[2,3)"

I created a simple docker-compose with a servicemix 7.0.1 on github with the two ways of creating json logs (the new JsonTemplateLayout not working at the moment).

Solution 2:[2]

If the above is in your user bundle then this is not correct. In your user bundle you should simply use the commons logging API and not change the settings of the maven bundle plugin.

It will then create Import-Package statements for the commons logging API but not for log4j which is what you want.

You then should install a suitable logging framework at runtime. I know that pax-logging can handle commons logging in a OSGi compatible way. Maybe plain log4j2 also works but I am not sure.

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 рüффп
Solution 2 Christian Schneider