The log4j-core bundle registers a bundle listener when the Activator is started and starts searching for log plugins and if something is found it performs a sequence of operations similar to the usual Logger initialization (not really idiomatic OSGi stuff and i'm not sure it works, but it seems to set at least Log4jContextSelector
and LoggerContextFactory
), just to be sure of it, did you install and start the log4j-core bundle and verified that nothing changed?
Update:
I did some testing and found what is an acceptable solution/workaround for log4j2 OSGi issues. But as someone else recommended, alternatively i would use slf4j, pax-logging or simply the OSGi Log Service (the simpler of the bunch).
@Grant, you have 2 separate things that need to be fixed:
1. As you described, the "Log4j2 could not find a logging implementation" error is caused by the fact that the log4j2-api
bundle is unable to find the log4j-provider.properties file and, after that is fixed, log4j2-api
cannot find the log4j2-core
classes (it's a different bundle and log4j2-api
doesn't have a specific Import-Package: for those classes).
The workaround for this is to create a small fragment bundle for log4j2-api
(i called mine log4j-api-config.jar) with that .properties file in META-INF
and a manifest that forces a dynamic import:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Log4j API configurator
Bundle-SymbolicName: org.apache.logging.log4j.apiconf
Bundle-Version: 1.0.0
Bundle-Vendor: None
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2
Fragment-Host: org.apache.logging.log4j.api
DynamicImport-Package: *
I'm importing * here, you can improve it adding the required subset of log4j2-core
packages that log4j2-api
needs.
With this, that error will disappear, but log4j will notice that you didn't provide a log4j2 configuration file, next thing to fix (only if you care in this case).
2. At this point Felix will display this:
log4j2.xml not found by org.apache.logging.log4j.core
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
and i suppose you could want to add your own log4j2.xml without messing with the original log4j2-core.jar
. You can do this creating another fragment bundle, this time hosted by log4j2-core
, with just a log4j2.xml configuration file in the root and a simple manifest:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Log4j Core configurator
Bundle-SymbolicName: org.apache.logging.log4j.coreconf
Bundle-Version: 1.0.0
Bundle-Vendor: None
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2
Fragment-Host: org.apache.logging.log4j.core
I used this simple log4j2.xml configuration during my tests:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
With this you will not need that sort of "bridge" bundle you described below anymore, and you'll just need a simple Import-Package: org.apache.logging.log4j
to use log4j from your bundle.
Update 2:
Important to note that the two fragments are NOT dependencies of the original bundles (no need to modify log4j jars or or even your bundles to add import/export), so the original bundles and your own custom ones will remain untouched.
Also, they don't depend on the original bundle either, they are just basic jar archive with a manifest and an additional text file, no code, no need for Import-Package or Export-Package.
You just need to install each fragment after their host bundle is installed.
I've created both fragments manually starting from an empty jar and copying inside the archive the properties file and modifying the MANIFEST.MF with a text editor, you can create them both with this pom.xml, remember to copy log4j-provider.properties where pom.xml is located.
For the log4j2-api
fragment:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.group</groupId>
<artifactId>log4j2-api-config</artifactId>
<version>1.0</version>
<name>log4j2-api-config</name>
<packaging>bundle</packaging>
<properties>
<java-version>1.7</java-version>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.0.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.apache.logging.log4j.apiconf</Bundle-SymbolicName>
<Bundle-Name>Log4j API Configurator</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Fragment-Host>org.apache.logging.log4j.api</Fragment-Host>
<DynamicImport-Package>
*;resolution:=optional
</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>.</directory>
<includes>
<include>log4j-provider.properties</include>
</includes>
<targetPath>META-INF</targetPath>
</resource>
</resources>
</build>
</project>
Modify this pom where appropriate(included file, bundle names) to generate the other one with the log4j2-core
configuration.