Karaf 4.2.0M2 issue with classpath

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Karaf 4.2.0M2 issue with classpath

bobanbp
I'm migrating our application to the newer version of Karaf and I started
testing our application on karaf 4.2.0M2. Before 4.2.0M2 I performed some
tests on Karaf 4.1.4 and it worked fine, but on 4.2.0M2 I hit an issue. I am
getting the flowing error:

javax.xml.stream.XMLInputFactory: Provider
com.ctc.wstx.stax.WstxInputFactory not found.

It seems that AWS SDK bundle that we use uses package javax.xml.stream from
org.apache.felix.framework that imports
com.fasterxml.woodstox.woodstox-core, but for some reason
com.ctc.wstx.stax.WstxInputFactory is not visible. I am using apache CXF
3.2.0 and it provides woodstox-core bundle.



--
Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html
Reply | Threaded
Open this post in threaded view
|

Re: Karaf 4.2.0M2 issue with classpath

cschneider
Hi Boban,

I guess the AWS SDK is not importing these packages so they are not visible. 
Of course it can not really import the packages as it does not know what is behind the API.

There is one thing you can try though. Add the com.ctc.wstx.* packages to 
org.osgi.framework.bootdelegation in config.properties.

Best 
Christian

2018-02-13 16:32 GMT+01:00 bobanbp <[hidden email]>:
I'm migrating our application to the newer version of Karaf and I started
testing our application on karaf 4.2.0M2. Before 4.2.0M2 I performed some
tests on Karaf 4.1.4 and it worked fine, but on 4.2.0M2 I hit an issue. I am
getting the flowing error:

javax.xml.stream.XMLInputFactory: Provider
com.ctc.wstx.stax.WstxInputFactory not found.

It seems that AWS SDK bundle that we use uses package javax.xml.stream from
org.apache.felix.framework that imports
com.fasterxml.woodstox.woodstox-core, but for some reason
com.ctc.wstx.stax.WstxInputFactory is not visible. I am using apache CXF
3.2.0 and it provides woodstox-core bundle.



--
Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html



--
--
Christian Schneider

http://www.liquid-reality.de

Computer Scientist

Reply | Threaded
Open this post in threaded view
|

Re: Karaf 4.2.0M2 issue with classpath

bobanbp
Hi Christian,

Thanks for your reply. I tried your suggestion but without success. The only
solution that works is to explicitly change class loader:

ClassLoader tccl = Thread.currentThread() .getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
my code that uses AWS SDK
Thread.currentThread().setContextClassLoader(tccl);



--
Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html
Reply | Threaded
Open this post in threaded view
|

Re: Karaf 4.2.0M2 issue with classpath

cschneider
If you have control over that code then the TCCL is a good solution. 

Christian

2018-03-21 16:54 GMT+01:00 bobanbp <[hidden email]>:
Hi Christian,

Thanks for your reply. I tried your suggestion but without success. The only
solution that works is to explicitly change class loader:

ClassLoader tccl = Thread.currentThread() .getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
my code that uses AWS SDK
Thread.currentThread().setContextClassLoader(tccl);



--
--
Christian Schneider

http://www.liquid-reality.de

Computer Scientist

Reply | Threaded
Open this post in threaded view
|

RE: Karaf 4.2.0M2 issue with classpath

Siano, Stephan

Hi,

 

I think the root cause of the issue is something a little more fundamental with Karaf 4.2.0:

 

Java 9 removed the endorsed mechanism that could override classes from the JDK. Karaf versions before 4.2.0 used that mechanism to replace some javax APIs (like the Stax API javax.xml.stream) with a servicemix wrapped implementation which was changing the implementation lookup in a way that was working with OSGi.

 

Without that endorsed stuff, you will fall back to the JDK implementation of XMLInputFactory which finds the services definition from Woodstox (which says that com.ctc.wstx.stax.WstxInputFactory is the XMLInputFactory implementation to use) and then tries to load that class with its own class loader (the root class loader) or the ThreadContextClassLoader.

 

Now you have different options (which all have their disadvantages):

  1. As you already found out you can import the Woodstox packages from all bundles using Stax and set the Thread Context Class loader to the class loader of that bundle. The disadvantage of that approach is that the bundle using Stax has to know about the implementation (which is not supposed to be the case).
  2. Put woodstox into the system classloader (into ext or endorsed) and export the packages from the system bundle. The disadvantage of this approach is that this will only work with Java 8 (not with Java 9 and later). Alternatively you could put the servicemix wrapped Stax API into the endorsed folder (as with older Karaf versions), which will also only work with Java 8.
  3. Import the woodstox bundle into the bundle using Stax and instantiate the factory implementations directly (not via the Interface). Here the using bundle needs to control the factory instantiaton, but you don’t need to set the thread context class loader.

 

I have not yet figured out what the real solution about that is supposed to look like. I have asked that question already to the karaf-dev list (because the question is actually how Karaf 4.2 and later is supposed to handle the SPI pattern), but I didn’t get an answer for it.

 

Best regards

Stephan

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of user-return-18355-stephan.siano=[hidden email]
Sent: Mittwoch, 21. März 2018 18:35
To: [hidden email]
Subject: Re: Karaf 4.2.0M2 issue with classpath

 

If you have control over that code then the TCCL is a good solution. 

 

Christian

 

2018-03-21 16:54 GMT+01:00 bobanbp <[hidden email]>:

Hi Christian,

Thanks for your reply. I tried your suggestion but without success. The only
solution that works is to explicitly change class loader:

ClassLoader tccl = Thread.currentThread() .getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
my code that uses AWS SDK
Thread.currentThread().setContextClassLoader(tccl);



 

--

--
Christian Schneider

http://www.liquid-reality.de

 

Computer Scientist