PaxLogging: org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext

581 views
Skip to first unread message

Jérémie Brébec

unread,
Aug 9, 2017, 11:30:12 AM8/9/17
to OPS4J
Hello,

I am using pax-logging 1.10.1 through Karaf 4.1.2 ;

I am trying to integrate the log generated by my ElasticSearch bundle to the pax-logging implementation. However, this didn't work because a ClassCastException. I haven't see any "duplicate classloader issues", and when I check the code, the ClassCastException doesn't feel to be osgi-related. Is it a known issue or I am missing something ?

Regards,
Jérémie

java.lang.ClassCastException: org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
        at org.apache.logging.log4j.core.LoggerContext.getContext(LoggerContext.java:190) [6:org.ops4j.pax.logging.pax-logging-log4j2:1.10.1]
        at org.apache.logging.log4j.core.config.Configurator.setLevel(Configurator.java:291) [6:org.ops4j.pax.logging.pax-logging-log4j2:1.10.1]
        at org.elasticsearch.common.logging.Loggers.setLevel(Loggers.java:149) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.common.logging.Loggers.setLevel(Loggers.java:144) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.index.SearchSlowLog.setLevel(SearchSlowLog.java:111) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.index.SearchSlowLog.<init>(SearchSlowLog.java:106) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.index.IndexModule.<init>(IndexModule.java:127) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.indices.IndicesService.createIndexService(IndicesService.java:441) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:414) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService.validateAndAddTemplate(MetaDataIndexTemplateService.java:216) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService.access$200(MetaDataIndexTemplateService.java:63) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService$2.execute(MetaDataIndexTemplateService.java:172) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.ClusterStateUpdateTask.execute(ClusterStateUpdateTask.java:45) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.service.ClusterService.executeTasks(ClusterService.java:634) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.service.ClusterService.calculateTaskOutputs(ClusterService.java:612) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.service.ClusterService.runTasks(ClusterService.java:571) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.service.ClusterService$ClusterServiceTaskBatcher.run(ClusterService.java:263) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.service.TaskBatcher.runIfNotProcessed(TaskBatcher.java:150) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.cluster.service.TaskBatcher$BatchedTask.run(TaskBatcher.java:188) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:569) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:247) [88:features.boss.elasticsearch.bundle:5.5.0]
        at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:210) [88:features.boss.elasticsearch.bundle:5.5.0]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]

Achim Nierbeck

unread,
Aug 9, 2017, 12:40:55 PM8/9/17
to op...@googlegroups.com
Hi, 

it still might be a class-cast exception when you embed that class in your own bundle. Maybe that is the case in your scenario. 
I'd check that first. 

regards, Achim 


--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Apache Member
Apache Karaf <http://karaf.apache.org/> Committer & PMC
OPS4J Pax Web <http://wiki.ops4j.org/display/paxweb/Pax+Web/> Committer & Project Lead
blog <http://notizblog.nierbeck.de/>
Co-Author of Apache Karaf Cookbook <http://bit.ly/1ps9rkS>

Software Architect / Project Manager / Scrum Master 

Jérémie Brébec

unread,
Aug 9, 2017, 1:44:19 PM8/9/17
to OPS4J
Yes, that is the first thing I checked.

However LoggerContext.getContext() try to cast the context into a org.apache.logging.log4j.core.LoggerContext and Log4jv2LoggerContext implements only org.apache.logging.log4j.spi.LoggerContext so it's doesn't seen to be related to osgi and classloader.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+un...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Asma Zinneera Jabir

unread,
Sep 20, 2017, 2:18:29 AM9/20/17
to OPS4J
I am facing the same issue when trying to get the context using LoggerContext ctx = (LoggerContext) LogManager.getContext(). 
Is there a way to get the context from spi.LoggerContext in pax-logging??

Grzegorz Grzybek

unread,
Sep 20, 2017, 2:38:12 AM9/20/17
to op...@googlegroups.com
Hello

The exact explanation is:

org.apache.logging.log4j.core.LoggerContext#getContext() method explicitly casts org.apache.logging.log4j.LogManager#getContext() result (which by declaration is interface org.apache.logging.log4j.spi.LoggerContext) to org.apache.logging.log4j.core.LoggerContext class.

While in pax-logging, an implementation of org.apache.logging.log4j.spi.LoggerContext interface is org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext class which does NOT extend org.apache.logging.log4j.core.LoggerContext.

Comment on log4j2 class on org.apache.logging.log4j.LogManager#getContext() method says:

 WARNING - The LoggerContext returned by this method may not be the LoggerContext used to create a Logger for the calling class.

So unfortunately Elastic search uses a "convenient static method" on org.apache.logging.log4j.core.LoggerContext, while it should set the level using other methods than org.apache.logging.log4j.core.config.Configurator...

regards
Grzegorz Grzybek

--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.

Guillaume Nodet

unread,
Sep 20, 2017, 2:50:59 AM9/20/17
to op...@googlegroups.com
org.apache.logging.log4j.core package is not supposed to be available.
So the org.apache.logging.log4j.core.LoggerContext#getContext() is not part of the public api.
You should use org.apache.logging.log4j.LogManager#getContext() instead.


To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
------------------------
Guillaume Nodet

Guillaume Nodet

unread,
Sep 20, 2017, 2:54:27 AM9/20/17
to op...@googlegroups.com
LogManager.getContext() works and returns an instance of org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext which implements org.apache.logging.log4j.spi.LoggerContext

If you're casting it to org.apache.logging.log4j.core.LoggerContext, then yeah, that won't work.

2017-09-20 8:18 GMT+02:00 Asma Zinneera Jabir <azin...@gmail.com>:

--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
------------------------
Guillaume Nodet

Asma Zinneera Jabir

unread,
Sep 20, 2017, 4:52:06 AM9/20/17
to OPS4J
I want to programmatically get the registered appenders and reconfigure. It could be done with log4j2 bundles with the mentioned way but a class cast error happens with pax-logging. What is the recommended way to get the appenders in pax-logging if the pure Log4j2 way will cause a class cast exception?


On Wednesday, August 9, 2017 at 9:00:12 PM UTC+5:30, Jérémie Brébec wrote:

Grzegorz Grzybek

unread,
Sep 20, 2017, 5:46:16 AM9/20/17
to op...@googlegroups.com
Hmm

The org.apache.logging.log4j.core.config.Configurator#setLevel() which is part of the stack trace only puts single logger configuration (if it's not present).

But I think it's possible to use pax-logging to achieve what you want.

Don't use Log4j facilities (like LogManager.getContext()). Retrieve OSGi service of interface org.ops4j.pax.logging.PaxLoggingService, cast to org.ops4j.pax.logging.log4j2.internal.PaxLoggingServiceImpl and get
First - just call org.apache.logging.log4j.LogManager#getContext() and cast it to org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext (or configadmin's org.osgi.service.cm.ManagedService) and call org.ops4j.pax.logging.log4j2.internal.PaxLoggingServiceImpl#updated() with dictionary.

But this configuration is normally performed via configadmin.

regards
Grzegorz Grzybek

--

Asma Zinneera Jabir

unread,
Sep 22, 2017, 8:40:19 AM9/22/17
to OPS4J
I tried the above methods you had suggested but still could not get the configuration.

1st suggestion -  casting to org.ops4j.pax.logging.log4jv2.Log4jv2LoggerContext does not work since the needed methods (methods needed to get and update loggers) aren't available in Log4jv2LoggerContext
2nd suggestion - using ConfigurationAdmin only allows retrieving and updating properties given in to pax-logging.properties file.

What I need is, to get the registered Log4J2 appender/s from the LoggerContext and update. (i.e. change level, pattern of an appender). What is the way of doing this??



On Wednesday, August 9, 2017 at 9:00:12 PM UTC+5:30, Jérémie Brébec wrote:

Grzegorz Grzybek

unread,
Sep 22, 2017, 8:42:15 AM9/22/17
to op...@googlegroups.com
Hello

I'm afraid this looks like an enhancement then... Please create PAXLOGGING issue at https://ops4j1.jira.com/projects/PAXLOGGING project.

regards
Grzegorz Grzybek

--

Guillaume Nodet

unread,
Sep 22, 2017, 9:34:32 AM9/22/17
to op...@googlegroups.com
You can't because that's not how pax-logging is working.
The configuration is done via ConfigAdmin, so if you want to modify your configuration, the best way would be to modify that configuration to suit your needs.

2017-09-22 14:40 GMT+02:00 Asma Zinneera Jabir <azin...@gmail.com>:

--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
------------------------
Guillaume Nodet

Asma Zinneera Jabir

unread,
Oct 2, 2017, 12:43:40 AM10/2/17
to OPS4J

The way I have configured Log4j2 is through the following entry in pax-logging.properties.

org.ops4j.pax.logging.log4j2.config.file=path/to/log4j2.properties

So when I try:

Hashtable<String, Object> log4jProps = new Hashtable<String, Object>();
log4jProps.put( "appender.CONSOLE.layout.pattern", "[%d] %5p {%c} - %m%ex%n" );
configuration.update(log4jProps);

This will add another entry into pax-logging.properties as appender.CONSOLE.layout.pattern = [%d] %5p {%c} - %m%ex%n which makes all the entries in pax-logging.properties invalid. 

To make my requirement clear, I have two things to do.

1. I have a Log4J2 custom memory appender in which writes log events to a circular buffer. During the runtime, I need to display these logs in the UI. For this, I should be able to get the memory appender form the log4j2 context.
2. I need to give an option to the user to reconfigure all the appenders during runtime throught the UI. For this, I should be able to reconfigure the specified properties of appenders programatically.


On Wednesday, August 9, 2017 at 9:00:12 PM UTC+5:30, Jérémie Brébec wrote:

Guillaume Nodet

unread,
Oct 2, 2017, 2:14:33 AM10/2/17
to op...@googlegroups.com
2017-10-02 6:43 GMT+02:00 Asma Zinneera Jabir <azin...@gmail.com>:

The way I have configured Log4j2 is through the following entry in pax-logging.properties.

org.ops4j.pax.logging.log4j2.config.file=path/to/log4j2.properties

You can configure the properties directly in the etc/org.ops4j.pax.logging.cfg too.
 

So when I try:

Hashtable<String, Object> log4jProps = new Hashtable<String, Object>();
log4jProps.put( "appender.CONSOLE.layout.pattern", "[%d] %5p {%c} - %m%ex%n" );
configuration.update(log4jProps);

This will add another entry into pax-logging.properties as appender.CONSOLE.layout.pattern = [%d] %5p {%c} - %m%ex%n which makes all the entries in pax-logging.properties invalid. 

To make my requirement clear, I have two things to do.

1. I have a Log4J2 custom memory appender in which writes log events to a circular buffer. During the runtime, I need to display these logs in the UI. For this, I should be able to get the memory appender form the log4j2 context.

For this, you just need to register an OSGi service implementing org.ops4j.pax.logging.spi.PaxAppender and it will be given all log events.
 
2. I need to give an option to the user to reconfigure all the appenders during runtime throught the UI. For this, I should be able to reconfigure the specified properties of appenders programatically.

Yes, that's doable without any problems.  The thing you need to pay attention to is if the main configuration has an indirection to another file, in which case, you'd have to modify that file instead.  The reason for this indirection is that at first, properties-based configuration was not available, so the main config would contain a pointer to the xml config.
Now, if you control everything, just make sure the configuration is flattened in the org.ops4j.pax.logging configuration and it should be ok.

Cheers,
Guillaume Nodet

 

--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
------------------------
Guillaume Nodet

Grzegorz Grzybek

unread,
Oct 2, 2017, 2:14:58 AM10/2/17
to op...@googlegroups.com
Hello


I would so similar thing - register an appender as plugin AND as OSGi service (or have it referenced in other way) - so you won't have to retrieve it back from log4j2 internals.

As for configuration - I still think it's better to configure it via configadmin. Otherwise you'd just have to reimplement pax-logging-log4j2 in a way that allows configuration using different method.

regards
Grzegorz Grzybek

2017-10-02 6:43 GMT+02:00 Asma Zinneera Jabir <azin...@gmail.com>:

--
Reply all
Reply to author
Forward
0 new messages