cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christian Schneider <ch...@die-schneider.net>
Subject Re: avoid using contextClassLoader inside OSGi?
Date Sun, 01 Mar 2015 11:25:07 GMT
I agree that using the TCCL or other means of setting the classloader 
only at the places where it is necessary would be better. This is not 
that easy to achive though.

* We need to first identify the places where the TCCL has an effect.
* Then we need to find a way to determine the correct classloader there. 
This can mean we need to transport it to the position in the code as it 
is not in any of the current interfaces.
* In the end we need to do the change while making sure that none of the 
platforms we currently support is negatively affected

I think you understand that this is a big task. While I agree with you 
that it would be a good step and I also proposed it in the past I was 
never bold enough to actually tackle this.

Christian

Am 01.03.2015 um 09:35 schrieb Mike Wilson:
> I think this path is probably not constructive. I provided the details so
> you can understand the context of the problem but now this turns into a game
> of blaming everybody else. I'm quite sure that if we ask any of the other
> projects they will find reason to blame everyone but themselves too ;-)
>
> So, stepping back to the subject of this discussion thread I think the
> interesting question to ask is:
> Why does CXF execute *all* underlying subsystems with a modified TCCL when
> it is only targeting some of them? Specifically, what is the goal of calling
> the logging subsystem with a custom CXF TCCL?
>
> To my understanding, what CXF does with TCCL is a well-intended hack, but
> still a hack. The JEE role of TCCL is that it represents a whole application
> and this is how JEE containers assign them. You can expect a number of
> libraries in the wild that make the assumption that there is one TCCL per
> application. As CXF's OSGi adaptation breaks this rule and instead sets up
> one TCCL per bundle, and one application may be implemented by multiple
> bundles, effort should be made to let this "breakage of rules" leak into as
> few places as possible. So my assumption is that the CXF codebase would
> become more correct if changed to only override TCCL on the specific points
> where it is needed, such as when calling into JAXB and similar.
>
> Best regards
> Mike
>
> Daniel Kulp wrote:
>> To me, this looks like a bug in tomcat-embedded, not CXF.
>> Couple things:
>>
>> 1) Why is it's LogManager being used in OSGi instead of the
>> normal JDK one?
>>
>> 2) It's LogManager looks like it's designed for use in a J2EE
>> based system (not surprising, Tomcat implements J2EE specs as
>> well) and is making decisions based on the TCCL.   Not sure
>> why it would do that in OSGi.   If it's bad for CXF to set
>> the TCCL, why would it be OK for Tomcat to act upon it in OSGi?
>>
>>
>> Kind of have to wonder if pax-logging should prevent the
>> other LogManager's or provide one that is more OSGi friendly.
>>    What happens if you set the system property:
>>
>> -Djava.util.logging.manager=java.util.logging.LogManager
>>
>> on the command line when you start your OSGi container (or
>> via etc/system.properties or whatever)?
>>
>> Dan
>>
>>
>>
>>
>>
>>> On Feb 27, 2015, at 11:10 AM, Mike Wilson
>> <mikewse@hotmail.com> wrote:
>>> Right, this sounds fair. If you (or the things you call) need to do
>>> classname->class lookups then some kind of classloader
>> context is needed and
>>> TCCL is the JEE way..
>>> So what remains then is to constrain TCCL setup to only the
>> places where it
>>> is really needed. Below I describe the Pax/Juli bug that
>> appears when
>>> looking up loggers with TCCL set.
>>> TL;DR: TCCL should not be set while executing getLogger(name) in an
>>> OSGi/PaxLogging/Juli context.
>>>
>>> CONFIGURATION
>>> -------------
>>>
>>> System classpath contains:
>>>     juli logging
>>>
>>> Karaf bundles:
>>>     pax logging
>>>     cxf
>>>     mycxfbundle
>>>
>>> Karaf logging config in etc/org.ops4j.pax.logging.cfg:
>>>     log4j.appender.cxf.file=cxf.log
>>>     log4j.logger.org.apache.cxf.services=INFO,cxf
>>>
>>> WHAT HAPPENS AT DIFFERENT LEVELS
>>> --------------------------------
>>>
>>> MYCXFBUNDLE
>>> Calling method on generated API to send WS message:
>>> myCxfApi.sayHello();
>>>
>>> CXF
>>> Interceptor executed as part of message handling:
>>>
>> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.cxf
>> /cxf-bundle/2.
>>> 7.14/org/apache/cxf/transport/ChainInitiationObserver.java
>>> org.apache.cxf.transport.ChainInitiationObserver
>>>     ChainInitiationObserver(...)
>>>         // In OSGi the loader is set to an instance of
>>> org.apache.cxf.bus.blueprint.BundleDelegatingClassLoader
>>>         loader = bus.getExtension(ClassLoader.class);
>>>     onMessage(Message)
>>>         if (loader != null) {
>>>             // Now TCCL is assigned to the
>> BundleDelegatingClassLoader
>>>             origLoader =
>>> ClassLoaderUtils.setThreadContextClassloader(loader);
>>>         }
>>>
>>> Logging interceptor executed a bit further down the stack:
>>>
>> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.cxf
>> /cxf-bundle/2.
>>> 7.14/org/apache/cxf/interceptor/LoggingInInterceptor.java
>>> org.apache.cxf.interceptor.LoggingInInterceptor
>>>     // The class's own logger will route through Pax's
>> handler as it is
>>> looked
>>>     // up while TCCL is null
>>>     LOG = LogUtils.getLogger(LoggingInInterceptor.class)
>>>     handleMessage(...)
>>>         // This logger will route through Juli's handler as
>> it is looked up
>>>         // while TCCL is set
>>>         Logger logger = getMessageLogger(message)
>>>
>>> PAX
>>> This is how Pax Logging hooks into j.u.l logging used by CXF:
>>>
>> http://grepcode.com/file/repo1.maven.org/maven2/org.ops4j.pax.
>> logging/pax-lo
>> gging-service/1.8.1/org/ops4j/pax/logging/service/internal/Act
>> ivator.java
>>> org.ops4j.pax.logging.service.internal.Activator
>>>     start()
>>>         // TCCL is not set so this RootLogger will be
>> located in the system
>>>         // classloader section below where most bundles will
>> also look
>>>         Logger rootLogger = manager.getLogger( "" );
>>>         ...
>>>         m_JdkHandler = new JdkHandler( m_PaxLogging );
>>>         rootLogger.addHandler( m_JdkHandler );
>>>
>>> JULI
>>> Further down in the call hierarchy the lookup for a logger
>> arrives in Juli:
>> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tom
>> cat.embed/tomc
>> at-embed-logging-juli/8.0.15/org/apache/juli/ClassLoaderLogMan
>> ager.java
>>> org.apache.juli.ClassLoaderLogManager
>>>     getLogger(String name)
>>>         // Juli partition loggers into different "domains"
>> depending on TCCL
>>>         ClassLoader classLoader =
>>> Thread.currentThread().getContextClassLoader();
>>>         return getClassLoaderInfo(classLoader).loggers.get(name);
>>>
>>>     // The data structure that keeps the loggers will be
>> populated like
>>> this:
>>>     classLoaderLoggers: {
>>>         <system classloader>: { // key used when TCCL==null
>>>             loggers: [
>>>                 // Almost all bundles' loggers will be found here
>>>                 
>> "org.apache.cxf.interceptor.LoggingInInterceptor": Logger(no
>>> handlers)
>>>                 ...
>>>                 // This RootLogger is the one Pax locates
>> and patches to
>>> route
>>>                 // logging to its own handler
>>>                 "": RootLogger(handlers -> Pax)
>>>             ]
>>>         <mycxfbundle classloader>: { // TCCL was set so
>> creates a new entry
>>>             loggers: [
>>>                 "...mycxfbundle": Logger(no handlers)
>>>                 // This RootLogger is not found by Pax so it
>> keeps its
>>> default
>>>                 // Juli settings
>>>                 "": RootLogger(handlers -> Juli)
>>>             ]
>>>         }
>>>     }
>>>
>>> Best regards
>>> Mike
>>>
>>> Daniel Kulp wrote:
>>>>> On Feb 26, 2015, at 4:04 PM, Mike Wilson
>>>> <mikewse@hotmail.com> wrote:
>>>>> Having the luxury of not understanding the implications in
>>>> the CXF codebase
>>>>> I would choose to disagree ;-), and welcome removal of TCCL
>>>> usage as it
>>>>> seems not to be set in normal JEE scenarios and is only set
>>>> when running in
>>>>> OSGi, where it is explicitly unrecommended to do so.
>>>> Well, no.  It's also set when using Spring to setup your
>>>> endpoints and services.   There are other cases where it's
>>>> set as well.
>>>>
>>>> Most importantly, there are a BUNCH of places in CXF and in
>>>> the libraries that CXF uses that require it.   CXF being
>>>> primarily an implementation of J2EE specs in general uses the
>>>> recommendations and guidelines provided by J2EE which
>>>> includes the use of the TCCL.    In particular, things like
>>>> loading the JAX-WS handlers from the @HandlerChain would
>>>> require the use of the TCCL to locate and "newInstance" them.
>>>>   The xmlbeans and jibx data bindings would also require the
>>>> use of the TCCL for loading the various resources they need
>>>> to operate.   The WS-Security stuff we have may use the TCCL
>>>> to load callback objects (although some of them can be passed
>>>> by reference to a bean instead of just a class name).    Some
>>>> use of JAXB requires it (if you do a
>>>> JAXBContext.newInstance("com.foo.package") for example).
>>>>
>>>> Even some of the CXF annotations themselves would require it.
>>>> For example, @Features(features = "org.apache.MyFeature")
>>>> would need it to load the appropriate feature.  (Although all
>>>> the CXF annotations that do this have an alternative form
>>>> that takes the class object itself that could be used
>>>> instead.  @Features(classes = MyFeature.class))
>>>>
>>>> Some of them could be "fixed" by adding a bunch of
>>>> "ClassLoader"  parameters to various methods and passing that
>>>> around, but that's a massive change and also a complete hack
>>>> IMO.   The TCCL was created specifically for providing the
>>>> class loader of the current "context" to avoid having to do
>>>> all of that.
>>>>
>>>> Those are just a couple off the top of my head.    I'm sure
>>>> there are others.
>>>>
>>>> Dan
>>>>
>>>>
>>>>> Anyway, I'll put together a description of the bug and post
>>>> here (as it
>>>>> seems this is where you prefer to do the discussion about it?).
>>>>>
>>>>> Best regards
>>>>> Mike
>>>>>
>>>>> Sergey Beryozkin wrote:
>>>>>> On 26/02/15 12:58, Mike Wilson wrote:
>>>>>>> Ok, let's see if other believe TCCL usage is possible to
>>>>>> remove altogether.
>>>>>>> If not, I'll invest the time to create a ticket with the
>>>>>> details of the bug.
>>>>>>> In short, it happens when CXF logging is routed to Juli.
>>>>>> Do you have more details re why it breaks with Juli involved
>>>>>> ? How does
>>>>>> CXF setting TCCL affects Juli doing its work ?
>>>>>>
>>>>>> IMHO the best way to get it moved forward is to have a
>>>> concrete case
>>>>>> discussion (as Christian suggested) and see what can be done
>>>>>> it make it
>>>>>> resolved as opposed to just considering completely removing
>>>>>> the use of
>>>>>> TCCL - might be risky, though may be Christian and Dan may
>>>>>> have another
>>>>>> view with respect to using an OSGI-specific loader in
>> the chain...
>>>>>> Cheers, Sergey
>>>>>>> If configuring CXF
>>>>>>> to route through Slf4j the problem goes away.
>>>>>>>
>>>>>>> Best regards
>>>>>>> Mike
>>>>>>>
>>>>>>> Christian Schneider wrote:
>>>>>>>> I think it might make sense to remove the TCCL usage in OSGi
>>>>>>>> where ever
>>>>>>>> possible. This is not a small thing though as we have to
be
>>>>>>>> careful not
>>>>>>>> to break existing code.
>>>>>>>>
>>>>>>>> So for short term it will make more sense to work around
>>>>>> the problem.
>>>>>>>> Can you give a concrete example where it breaks for you?
>>>>>>>> Btw. I am using pax logging a lot and itworks fine with CXF.
>>>>>>>> I just use
>>>>>>>> the slf4j API in my own code and pax logging implements it.
>>>>>>>>
>>>>>>>> Christian
>>>>>>>>
>>>>>>>> On 24.02.2015 15:46, Mike Wilson wrote:
>>>>>>>>> Yes, the undesired side-effect for us is that the
>>>>>>>> combination of CXF, Juli
>>>>>>>>> and Pax Logging breaks down. Looking at the code it seems
>>>>>>>> all involved
>>>>>>>>> parties have design decisions done with good intentions
>>>>>> and the only
>>>>>>>>> questionable thing is CXF's use of TCCL, which is sort
of
>>>>>>>> the trigger of the
>>>>>>>>> problem. So I thought this would be the first thing worth
>>>>>>>> considering as it
>>>>>>>>> is advised against in OSGi.
>>>>>>>>>
>>>>>>>>> If not possible to remove TCCL entirely, then it might
>>>>>>>> still be possible to
>>>>>>>>> only set it during the very calls into stuff that need
it,
>>>>>>>> instead of during
>>>>>>>>> the whole message cycle?
>>>>>>>>>
>>>>>>>>> Best regards
>>>>>>>>> Mike
>>>>>>>>>
>>>>>>>> --
>>>>>>>> Christian Schneider
>>>>>>>> http://www.liquid-reality.de
>>>>>>>>
>>>>>>>> Open Source Architect
>>>>>>>> http://www.talend.com
>>>>>>>>
>>>>>>>>
>>>>>>
>>>> -- 
>>>> Daniel Kulp
>>>> dkulp@apache.org - http://dankulp.com/blog
>>>> Talend Community Coder - http://coders.talend.com
>>>>
>>>>
>> -- 
>> Daniel Kulp
>> dkulp@apache.org - http://dankulp.com/blog
>> Talend Community Coder - http://coders.talend.com
>>
>>


Mime
View raw message