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: http://marc.info/?l=turbine-maven-user&m=118823947802801&w=2
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?
Committed for log4j in rev 685646. Did not address companions. May want to ask user@felix.apache.org for feedback.
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: org.apache.log4j.lf5.* org.apache.log4j.chainsaw
I noticed one other issue, the org.apache.log4j packages exported via the Export-Packages header are missing an explicit version number.
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 3c.dom,org.xml.sax,org.apache.log4j.config,org.apache.log4j.or",org.a pache.log4j.filter;uses:="org.apache.log4j.extras,org.w3c.dom,org.apa che.log4j.rule",org.apache.log4j.rolling;uses:="org.apache.log4j.extr as,org.w3c.dom",org.apache.log4j.rule 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 .html Bundle-SymbolicName: log4j.apache-log4j-extras Import-Package: javax.xml.parsers,javax.xml.transform,javax.xml.transf orm.dom,javax.xml.transform.sax,javax.xml.transform.stream,org.apache .log4j.config,org.apache.log4j.extras,org.apache.log4j.filter,org.apa che.log4j.or,org.apache.log4j.rolling,org.apache.log4j.rule,org.w3c.d om,org.xml.sax,org.xml.sax.helpers Name: org.apache.log4j Implementation-Vendor: Apache Software Foundation Implementation-Title: Apache Extras Companion for log4j 1.2. Implementation-Version: 1.1-SNAPSHOT
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 start BUNDLE_FROM_PREVIOUS_STEP 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?
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.
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, NTEventLogAppender.amd64.dll;osname=Win32;processor=x86-64, * 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.
Created attachment 25850 [details] Loader.java
Created attachment 25851 [details] Log4jActivator.java
Created attachment 25852 [details] manifest.bnd
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.
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?
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.
*** Bug 52018 has been marked as a duplicate of this bug. ***