5

We are usingApache Felix (version 4.4.1)as an embedded OSGi framework. The main application that is providing the framework is usingLog4j2 (version 2.0.1)as logging framework. There are dependencies on log4j-api and log4j-core. Of course when the main application is started also Log4j2 will be loaded and configured. All log messages triggered in the main part are correctly written to the configured appenders.

Now the point. All bundles that are loaded should be able using the same configuration and for that the same LoggingContext as the main application. What I was trying to do is providing all Log4j2 packages (from log4j2-api and log4j-core) by putting them into the framework configuration asorg.osgi.framework.system.packages.extra. But when the bundles are loaded the log4j2 packages do not appear in the list of wiring packages as other provided packages do and when a bundle class tries to access Log4j2 classes an exception will be thrown.

All bundles are configured the same way and having Log4j2 dependencies on log4j2-api and log4j2-core with scope provided. When I'm looking into the MANIFEST.MF the used Log4j2 packages are within theImport-Packagespart

So my questions are.

Why exporting of Log4j2 packages this way does not work? How do I have to configure my environment so I can use same LoggingContext in my bundles and main application?

Here is my configuration part of the OSGi framework from the java code:

Map<String, String> temp = new HashMap<String, String>();
// setting parameter that the felix cache is new initialized on each
// start of the application
temp.put(org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
// setting the packages that are provided by the main system and can
// be used by the osgi bundles
temp.put(org.osgi.framework.Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
// have to export these explicitly as the automatic export does
// not work for this internal java packages
+ "com.sun.org.apache.xerces.internal.dom,"
+ "com.sun.org.apache.xerces.internal.jaxp,"
+ "com.sun.org.apache.xerces.internal.util,"
// export the looging packages
+ "org.apache.log4j," + "org.apache.logging.log4j," +   "org.apache.logging.log4j.message,"
+ "org.apache.logging.log4j.simple," + "org.apache.logging.log4j.spi,"
+ "org.apache.logging.log4j.status," + "org.apache.logging.log4j.util,"
+ "org.apache.logging.log4j.impl," + "org.apache.logging.log4j.appender,"
+ "org.apache.logging.log4j.appender.db," + "org.apache.logging.log4j.appender.db.jdbc,"
+ "org.apache.logging.log4j.appender.db.jpa," + "org.apache.logging.log4j.appender.db.jpa.converter,"
+ "org.apache.logging.log4j.appender.jms," + "org.apache.logging.log4j.appender.rewrite,"
+ "org.apache.logging.log4j.appender.rolling," + "org.apache.logging.log4j.appender.rolling.action,"
+ "org.apache.logging.log4j.appender.routing," + "org.apache.logging.log4j.async,"
+ "org.apache.logging.log4j.config," + "org.apache.logging.log4j.config.json,"
+ "org.apache.logging.log4j.config.plugins," + "org.apache.logging.log4j.config.plugins.osgi,"
+ "org.apache.logging.log4j.config.plugins.processor,"
+ "org.apache.logging.log4j.config.plugins.util," + "org.apache.logging.log4j.config.plugins.visitors,"
+ "org.apache.logging.log4j.config.status," + "org.apache.logging.log4j.config.xml,"
+ "org.apache.logging.log4j.config.yaml," + "org.apache.logging.log4j.filter,"
+ "org.apache.logging.log4j.impl," + "org.apache.logging.log4j.jackson,"
+ "org.apache.logging.log4j.jmx," + "org.apache.logging.log4j.layout,"
+ "org.apache.logging.log4j.lookup," + "org.apache.logging.log4j," + "org.apache.logging.log4j.net,"
+ "org.apache.logging.log4j.net.jms," + "org.apache.logging.log4j.net.server,"
+ "org.apache.logging.log4j.net.ssl," + "org.apache.logging.log4j.pattern,"
+ "org.apache.logging.log4j.selector," + "org.apache.logging.log4j.tools,"
+ "org.apache.logging.log4j.util," + "sun.misc," + "javax.jms," + "javax.mail,"
+ "javax.mail.internet," + "javax.mail.util," + "javax.persistence," + "javax.servlet,"
+ "com.sun.xml.internal.bind");
temp.put(FelixConstants.LOG_LEVEL_PROP, "4");
OSGI_CONFIG = Collections.unmodifiableMap(temp);

Dependencies on log4j2 libs in bundles are defined as followos:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.0.1</version>
    <scope>provided</scope>
</dependency>
sebastian
  • 2,427
  • 4
  • 32
  • 37
  • How you configure log4j2 in OSGi environment ? Can you provide sample pom file you have used because I'm continuously getting log4j2 api cannot find log4j2 core exception. – Grant May 13 '15 at 11:25
  • As of version 2.0.1, OSGi support for Log4j2 is still a work in progress. We would like to improve this, so I invite you to join the [mailing list](http://logging.apache.org/log4j/2.x/mail-lists.html) or file a Jira ticket for this on the [log4j2 issue tracker](https://issues.apache.org/jira/browse/LOG4J2). Ideas on how to improve this would be welcome! (Bear in mind that OSGi environments are not our main use case and there is resistance against breaking up the core jar into many small jar files. So this may be a bit of a challenge.) – Remko Popma Aug 07 '14 at 07:21

3 Answers3

3

I have log4j2 working in osgi in a relatively easy configuration.

You must create TWO fragments.

  • 1st fragment should have log4j-api as the host. It should contain one file: META-INF/log4j-providers.properties (Yank it out of log4j2-core)
  • 2nd fragment should have log4j-core as the host. It should contain one file: log4j2.xml (or whatever configuration file you want)

This works with just dropping the log4j-api and log4j-core jar files into the plugins directory (p2 if your using equinox). I have the following chain working beautifully:

commons-logging (jcl-over-slf4j) -> slf4j (slf4j-api) -> log4j-slf4-impl -> log4j-api -> log4j-core.

Note: slf4j version 1.7.7 log4j2 version 2.1

2

We have found a solution, that works for us with version 2.0.1. Instead of setting the needed log4j packages in theImport-Packagepart of the MANIFEST.MF we have added them to theDynamicImport-Packagedefinition. After that the classes are dynamically wired when needed and all OSGi bundles can use the same LoggerContext.

sebastian
  • 2,427
  • 4
  • 32
  • 37
1

I have log4j working fine within OSGi (Eclipse).

As mentioned by @Fenris Ulth you can create a fragment for log4j-core containing your log4j2.xml configuration file. With log4j2 version 2.3 I found that I had to activate the log4j-api bundle before my code starts using log4j to log messages, otherwise I got the error described here. I did this by setting it to Auto-Start with a low start level.

Community
  • 1
  • 1
Henno Vermeulen
  • 1,495
  • 2
  • 15
  • 25