Bug 43282 - Add OSGi packaging info to log4j and companions
Summary: Add OSGi packaging info to log4j and companions
Alias: None
Product: Log4j - Now in Jira
Classification: Unclassified
Component: Other (show other bugs)
Version: 1.2
Hardware: Other other
: P2 normal
Target Milestone: ---
Assignee: log4j-dev
: 52018 (view as bug list)
Depends on:
Reported: 2007-08-31 13:56 UTC by Curt Arnold
Modified: 2011-10-14 04:39 UTC (History)
5 users (show)

Loader.java (6.28 KB, text/x-java)
2010-08-05 16:01 UTC, Craig Ziesman
Log4jActivator.java (1015 bytes, text/x-java)
2010-08-05 16:02 UTC, Craig Ziesman
manifest.bnd (462 bytes, application/octet-stream)
2010-08-05 16:10 UTC, Craig Ziesman

Note You need to log in before you can comment on or make changes to this bug.
Description Curt Arnold 2007-08-31 13:56:18 UTC
Jacob Kjome in http://marc.info/?l=log4j-dev&m=118793327920353&w=2

What does everyone think about releasing OSGi ready Log4j jars?  OSGi 
is quickly becoming popular.  In order for OSGi apps to depend on 
Log4j in an OSGi environment, certain MANIFEST.mf entries need to 
exist.  There's a Maven plugin that performs the OSGi packaging 
called the "maven-bundle-plugin".

... (more follows)

Also the following discussion on users@maven on 27-Aug-2007 regarding
commons-logging's pom may be helpful:
Comment 1 Thorbjørn Ravn Andersen 2008-08-02 13:31:21 UTC
If it is only a question of a slight change of the maven configuration file, could you please provide a patch :)

What do the Apache Felix folks think of this?  Is the logging outside the OSGi container?
Comment 2 Curt Arnold 2008-08-13 12:29:01 UTC
Committed for log4j in rev 685646.   Did not address companions.  May want to ask user@felix.apache.org for feedback.
Comment 3 John Gibson 2010-04-26 20:46:37 UTC
Unfortunately the new OSGi headers are broken, trying to install the Log4J bundle in Equinox yields the following error:
org.osgi.framework.BundleException: Invalid manifest header Import-Package: "com.sun.jdmk.comm;resolution:="optional"" : Cannot import a package more than once "com.sun.jdmk.comm"

Examining the manifest confirms this and another problem in the Import-Package header:
'com.sun.jdmk.comm;resolution:=optional' is specified twice
javax.jmdns is a required package, even though it isn't a standard JDK package.

I'm not sure if you wanted these exposed or not, but the Export-Package header is missing these packages:
Comment 4 Craig Muchinsky 2010-05-11 12:42:17 UTC
I noticed one other issue, the org.apache.log4j packages exported via the Export-Packages header are missing an explicit version number.
Comment 5 Curt Arnold 2010-06-04 23:59:24 UTC
Thanks for the bug report, sorry about the delay in response.  I have not yet investigated the reported issue with log4j 1.2.16, but made an initial attempt to add OSGi metadata to log4j-extras and would appreciate your review.

There are two classes org.apache.log4j.xml.XSLTLayout and org.apache.log4j.varia.SoundAppender that are in packages also exported by log4j.  I looked into split packages, but it looked highly likely that I would get it wrong, so I've left those classes unaccessible.

Here is the generated manifest for extras, do you see anything troubling?

Manifest-Version: 1.0

Export-Package: org.apache.log4j.extras;uses:="javax.xml.parsers,org.w





Built-By: curta

Tool: Bnd-0.0.357

Bundle-Name: Apache Extras Companion for log4j 1.2.

Created-By: Apache Maven Bundle Plugin

Bundle-Vendor: Apache Software Foundation

Build-Jdk: 1.6.0_18

Bundle-Version: 1.1.0.SNAPSHOT

Bnd-LastModified: 1275709540450

Bundle-ManifestVersion: 2

Bundle-Description: This companion provides additional appenders, filt

 ers and  other capabilities for log4j 1.2.  Several of these were bac

 kported from  the abandoned log4j 1.3 development effort.

Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt

Bundle-DocURL: http://logging.apache.org/log4j/companions/extras/index


Bundle-SymbolicName: log4j.apache-log4j-extras

Import-Package: javax.xml.parsers,javax.xml.transform,javax.xml.transf





Name: org.apache.log4j

Implementation-Vendor: Apache Software Foundation

Implementation-Title: Apache Extras Companion for log4j 1.2.

Implementation-Version: 1.1-SNAPSHOT
Comment 6 Curt Arnold 2010-06-12 01:33:17 UTC
I've committed rev 953935 which results in a log4j.jar which can be installed and started in the Equinox OSGi framework supplied with Eclipse.

For future ref:

cd /usr/lib/eclipse/plugins
java -jar org.eclipse.osgi_---.jar -console
install file:///home/.../log4j-1.2.17-SNAPSHOT.jar

Based on a suggest from the 2008 exchange on user@felix, I added a DynamicImport-Package directive via the maven-jar-plugin.  Hopefully, that would allow resolving any user-supplied appender that was specified via a configuration file.

javax.swing, com.ibm.uvm.tools and com.sun.jdmk.comm are explicitly blocked from being listed in the import list.  Swing is used by the obsolete log viewing tools still in the java, but not exported.  com.ibm.uvm.tools is dynamically loaded for some ancient VisualAge specific behavior.  com.sun.jdmk.comm provides an http service for JMX.  If needed, these classes can still be obtained via the DynamicImport-Package.

I've listed three javax packages not included in Java SE 1.5 as optional.  The javax.jmdns is not zeroconf implementation and despite the package name is not from Sun or part of the Java Community Process.

All the other imported classes are either part of Java SE 1.5 or are exported by log4j.jar.

The maven-bundle-plugin has enough info that it could provide the version qualifier on the exported classes, but it doesn't.  I can bounce this off of users@felix, but is there a reason that you think that we should specify it?
Comment 7 Craig Muchinsky 2010-06-12 09:13:41 UTC
Specifying version numbers on export is a good practice in OSGi since it allows consumers to target specific versions of the package, which is often required when multiple versions of the same package exist within the same OSGi runtime.
Comment 8 John Gibson 2010-07-12 12:16:35 UTC
Sorry for not responding earlier, but I forgot to add myself to the CC list.

Anyway, I agree with Craig, we need a version number on all of the exported packages.  It will keep behavior predictable if a user accidentally (or, on purpose for some strange reason) loads multiple version of Log4J into an OSGi environment at once.

Another enhancement that you might consider is packaging the NT appender DLLs inside the bundle.  With headers like this:

Bundle-NativeCode: NTEventLogAppender.dll;osname=Win32;processor=x86,

OSGi is smart enough to unpack the necessary DLL from the bundle and load it on demand.

If 55K is too much bloat for the Log4J jar, then they could be packaged separately and added as a fragment bundle.

WRT Log4J extras, again adding the version number for the exported packages is important.  In addition, you can handle the split packages problem gracefully if you make it a fragment bundle.  A fragment bundle will not function by itself in OSGi, but instead requires the log4j bundle to be loaded first.  Then the contents of the fragment bundle become accessible to the classloader provided by host bundle.  To do this you just add a header like so:

Fragment-Host: log4j;bundle-version="1.2.9"

This would instruct the log4j extras bundle to attach itself to the log4j bundle if the version number of the parent bundle is greater than or equal to 1.2.9.
Comment 9 Craig Ziesman 2010-08-05 16:01:25 UTC
Created attachment 25850 [details]
Comment 10 Craig Ziesman 2010-08-05 16:02:53 UTC
Created attachment 25851 [details]
Comment 11 Craig Ziesman 2010-08-05 16:10:00 UTC
Created attachment 25852 [details]
Comment 12 Craig Ziesman 2010-08-05 16:11:42 UTC
My team has created an OSGi friendly version of Log4j. Unfortunately, it's not as simple as adding the right headers to the manifest because there are classloader issues when using custom layouts or appenders.

Fortunately, the fixes were not too hard. The Loader.loadClass() method in org.apache.log4j.helpers had to be updated to use a bundle context class loader, if available, and a bundle activator class had to be created to provide access to the bundle context class loader.

We used the BND tool to generate the bundle with the appropriate manifest entries.

I have attached the modified/new files for your review.
Comment 13 Curt Arnold 2010-08-05 23:03:14 UTC
Any thoughts on how to write tests around this?  What specific things fail with the current class loader that would pass with the modified class loader?  Are there potential other approaches?
Comment 14 Craig Ziesman 2010-08-07 21:53:24 UTC
The specific situation that we had to address was logging via a customized JMSAppender that uses MDC parameters to set header properties in the JMS messages in order to simplify subscriber filtering. We also use a custom Layout class for simulations.

When custom appenders or layout classes from a bundle are specified in the Log4j properties/xml file, there is no way to resolve them via Class.forName() in Loader.loadClass() because they aren't on the static class path, and the instantiation fails with a ClassNotFoundException. By modifying Loader.loadClass() to use the bundle context class loader, the OSGi runtime is given the chance to locate the classes in the bundle where they were loaded, and the creation of the logger succeeds.

Testing should be fairly straightforward. You would need one or more custom layout and appender classes deployed in a bundle separate from the Log4j bundle. The unit tests would just create and use loggers using those classes. The tests would have to be deployed in a bundle. Knopflerfish and Felix provide JUnit integration to facilitate testing. I don't know about Equinox.

We haven't managed to identify any other approaches. Personally, I don't think there is any other way to make this work.
Comment 15 Curt Arnold 2011-10-14 04:39:46 UTC
*** Bug 52018 has been marked as a duplicate of this bug. ***