Closed ops4j-issues closed 7 years ago
Alexey Markevich commented
Initial Karaf issue: https://issues.apache.org/jira/browse/KARAF-5101
NiclasH commented
Observations from the peanut gallery...
If you want to use a Log4J version 2 backend, then you should not use the pax-logging-service, which is the Log4J version 1 backend.
For people looking at solving this; My guess is that Log4J2 is getting triggered "too early", for instance by the Log4J class in Activator.
Achim Nierbeck commented
For a log4j2 backend we do have the pax logging log4j2 bundle
NiclasH commented
Yes, he understood that, but both -servce and -log4j2 bundles are referenced in the pom.xml of the testcase.
Alexey Markevich commented
pax-logging-service can be safely removed; I took pax-logging-it as input and just add pax-logging-log4j2 dep
Grzegorz Grzybek commented
Alexey Markevich I'm looking at your example and I see you're using convenience method:
org.apache.logging.log4j.core.LoggerContext#getContext(boolean)
It Avoids the type cast for:
(org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(currentContext);
The problem is that org.apache.logging.log4j.LogManager#getContext(boolean)
method is declared to return org.apache.logging.log4j.spi.LoggerContext
interface and indeed, org.apache.logging.log4j.core.LoggerContext
implements this SPI interfaces.
But in pax-logging-log4j2, org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext
is used as org.apache.logging.log4j.spi.LoggerContext
implementation and the hierarchy is:
org.apache.logging.log4j.spi.LoggerContext
+-- org.apache.logging.log4j.core.LoggerContext
| +-- org.apache.logging.log4j.core.async.AsyncLoggerContext
+-- org.apache.logging.log4j.simple.SimpleLoggerContext
+-- org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext
so, org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext
is not an instance of org.apache.logging.log4j.core.LoggerContext
and you're getting ClassCastException...
Grzegorz Grzybek commented
There's no obvious way to access org.apache.logging.log4j.core.config.Configuration
as you want to do with the call to:
final org.apache.logging.log4j.core.config.Configuration config = LoggerContext.getContext(false).getConfiguration();
org.apache.logging.log4j.core.config.Configuration
object is stored inside org.ops4j.pax.logging.log4j2.internal.PaxLoggingServiceImpl#m_log4jContext
field, which is private and doesn't have getter.
Grzegorz Grzybek commented
Another portion of OSGi magic.
In PAX-EXAM, when org.ops4j.pax.exam.ExamSystem
is created, you have several options configured using org.ops4j.pax.exam.ConfigurationManager
. By default you can have exam.properties
file in root of your CLASSPATH or you can point to such file using pax.exam.configuration
System property.
In this file you can configure pax.exam.system
property with values:
org.ops4j.pax.exam.Constants#EXAM_SYSTEM_DEFAULT
("default")org.ops4j.pax.exam.Constants#EXAM_SYSTEM_JAVAEE
("javaee")In case of 3), you'll get system configured using org.ops4j.pax.exam.spi.PaxExamRuntime#defaultTestSystemOptions()
with several predefined options (among others - pax-logging-api bundle!)
I changed slightly your example:
exam.properties
resource with pax.exam.system = default
propertyorg.ops4j.pax.logging.it.appender.AppenderTest#configure
method to contain:
workingDirectory("target/paxexam"),
cleanCaches(true),
// added implicitly by pax-exam, if pax.exam.system=test // these resources are provided inside org.ops4j.pax.exam:pax-exam-link-mvn jar url("link:classpath:META-INF/links/org.ops4j.base.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.core.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.extender.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.framework.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.lifecycle.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.tracker.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.exam.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.exam.inject.link").startLevel(START_LEVEL_SYSTEM_BUNDLES), url("link:classpath:META-INF/links/org.ops4j.pax.extender.service.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
// configadmin should start before org.ops4j.pax.logging.pax-logging-log4j2 linkBundle("org.apache.felix.configadmin").startLevel(START_LEVEL_SYSTEM_BUNDLES),
// added implicitly by pax-exam, if pax.exam.system=test // - url("link:classpath:META-INF/links/org.ops4j.pax.logging.api.link").startLevel( START_LEVEL_SYSTEM_BUNDLES), // - url("link:classpath:META-INF/links/org.osgi.compendium.link").startLevel( START_LEVEL_SYSTEM_BUNDLES), // but we will use versions aligned to pax-web: url("link:classpath:META-INF/links/org.apache.geronimo.specs.atinject.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
CoreOptions.junitBundles(), mavenBundle().artifactId("pax-logging-api").groupId("org.ops4j.pax.logging").version("1.10.1-SNAPSHOT"), mavenBundle().artifactId("pax-logging-log4j2").groupId("org.ops4j.pax.logging").version("1.10.1-SNAPSHOT")
* these `url("link:classpath:META-INF/links/...` will be resolved using resources embedded inside `pax-exam-link-mvn` bundle
* this `linkBundle("org.apache.felix.configadmin")` comes from explicit resource inside `src/test/resources/org.apache.felix.configadmin.link`, which contains (configadmin is needed for pax-logging-log4j2):
mvn:org.apache.felix/org.apache.felix.configadmin/1.8.14
* in order to be able to use property placeholders, you can't have just `log4j2.property.pattern` and use {{log4j2.appender.console.layout.pattern = $ {log4j2.pattern}
}}, because prefix `log4j2.` is stripped and `org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder#build` detects generic properties to be prefixed by `property.`, so you have to have:
log4j2.property.pattern = %d{ISO8601} | %-5p | %-16t | %-32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n … log4j2.appender.console.layout.pattern = ${pattern}
This way you'll have working example
Grzegorz Grzybek commented
Ah - and shorter explanation - if you use default pax-exam configuration, which explicitly adds pax-logging-api bundle, with mavenBundle().artifactId("pax-logging-api").groupId("org.ops4j.pax.logging").version("1.10.0"),
you'll have two pax-logging-api bundles and your test class will configure the latter one, while loggers will come/be configured using the first one - that's why you saw failed test.
Alexey Markevich created PAXLOGGING-237
Trying to check appender from code cause [1] in console and [2] in logs
ERROR No log4j2 configuration file found. Using default configuration: logging only errors to the console. Set system property 'org.apache.logging.log4j.simplelog.StatusLogger.level' to TRACE to show Log4j2 internal initialization logging.
config.getAppenders() =
{DefaultConsole-4=DefaultConsole-4}
Affects: 1.10.0 Attachments:
Votes: 0, Watches: 4