You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@karaf.apache.org by Hervé BARRAULT <he...@gmail.com> on 2012/04/24 15:53:32 UTC

OSGi and ClassNotFoundException

Hi,

I have a case where i can't see how to cleanly list the imported packages
without using DynamicImport-Package.

Example :

I have a bundle A where there is the whole dto.

I have a bundle B which defines a "container" library (basically a
container can support any Serializable and provides
serialization/deserialization tools).

I have a bundle C which use a container (from B) and add in this container
some object from the dto (from A)
In the bundle C, I instantiate the classes from the bundle B and A.

When i put "object from A" into "container from B" in "my code from C" it
is working without problem.

When i try to get "object from A" from "container from B" in "my code from
C" i get a ClassNotFoundException for the object in A.

My Bundle B has no specific import (i think this library shall be
"agnostic").

My bundle C import packages from A and B.


For Information, in B library we are using genericity which is perhaps a
problem for imports.


Where am I missing something ?

Regards
Hervé

Re: OSGi and ClassNotFoundException

Posted by Holger Hoffstaette <ho...@googlemail.com>.
On Tue, 24 Apr 2012 15:53:32 +0200, Hervé BARRAULT wrote:

Not really a Karaf problem, but whatever..

> I have a case where i can't see how to cleanly list the imported packages
> without using DynamicImport-Package.

It is always possible. It's software.

> I have a bundle B which defines a "container" library (basically a
> container can support any Serializable and provides
> serialization/deserialization tools).

This is the (typical) problem. The solution is to fix the code. :)
You can:

1) fix your B API to take a classloader as argument, so that C can pass
its own Classloader in; this should work since it is wired to import A.

or

2) register & expose the API in B as ServiceFactory (!) and return a
per-caller customized service with the calling bundle's classloader used
for classloading. Then B will also work for client bundles D..Z :)

Both ways are easy to do, reliable, work well and don't require
DynamicImport.

-h



Reflection problem after bundle update/refresh

Posted by Marek Šabo <ms...@buk.cvut.cz>.
Hi all,

I'd like to ask if any of you ever had problem with reflection 
(UnsafeFieldAccessorImpl). I'm using guice/peabery with wicket and 
running my war bundle with pax-war.
When I start karaf it (DI) works fine but upon update/refresh I'm 
getting "can not set" errors from dependency injection (reflection) in 
wicket proxy ( precisely at 
http://www.docjar.com/html/api/sun/reflect/UnsafeObjectFieldAccessorImpl.java.html:81).

When I shutdown karaf and boot it again it works like charm.

Can anyone point me where to look? Thanks for any information.

Marek

Re: OSGi and ClassNotFoundException

Posted by Christian Schneider <ch...@die-schneider.net>.
As far as I know CXF uses a slighty changed jaxb impl to adapt it to OSGi.

Christian

Am 25.04.2012 09:55, schrieb Jean-Baptiste Onofré:
> Hi Hervé,
>
> Karaf itself doesn't provide a DOSGi implementation. However, you can 
> install Karaf Cellar in your Karaf instance: Cellar provides a DOSGi 
> implementation (powered by Hazelcast).
>
> Another possible DOSGi implementation in Karaf is to use CXF DOSGi.
>
> Regards
> JB
>
> On 04/25/2012 09:53 AM, Hervé BARRAULT wrote:
>> Hi, thanks for the tip.
>>
>> I just think that Karaf provides DOSGi implementation [not in my old
>> version]. I guess this implementation has the right implementation of
>> serialization.
>>
>> Regards
>> Hervé
>>
>>
>> On Tue, Apr 24, 2012 at 10:45 PM, Christian Schneider
>> <chris@die-schneider.net <ma...@die-schneider.net>> wrote:
>>
>>     As you can not change the jdk code I think such a workaround is
>>     acceptable.
>>     Btw. It is a good practice to save the old ThreadContextClassLoader
>>     and restore it after the call.
>>
>>     Christian
>>
>>     Am 24.04.2012 22 <tel:24.04.2012%2022>:08, schrieb Hervé BARRAULT:
>>
>>         Hi, i did a really ugly quick fix using ThreadContextClassLoader
>>         and it is working (using resolveClass for ObjectInputStream).
>>
>>         I say ugly because it is still based on class name [not OSGI
>>         compliant] but it validates the ThreadContextClassLoader
>>         "Workaround".
>>
>>         Thanks
>>         Regards
>>         hervé
>>
>>
>>     --
>>
>>     Christian Schneider
>>     http://www.liquid-reality.de
>>
>>     Open Source Architect
>>     Talend Application Integration Division http://www.talend.com
>>
>>
>


-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
Talend Application Integration Division http://www.talend.com


Re: OSGi and ClassNotFoundException

Posted by Jean-Baptiste Onofré <jb...@nanthrax.net>.
Hi Hervé,

Karaf itself doesn't provide a DOSGi implementation. However, you can 
install Karaf Cellar in your Karaf instance: Cellar provides a DOSGi 
implementation (powered by Hazelcast).

Another possible DOSGi implementation in Karaf is to use CXF DOSGi.

Regards
JB

On 04/25/2012 09:53 AM, Hervé BARRAULT wrote:
> Hi, thanks for the tip.
>
> I just think that Karaf provides DOSGi implementation [not in my old
> version]. I guess this implementation has the right implementation of
> serialization.
>
> Regards
> Hervé
>
>
> On Tue, Apr 24, 2012 at 10:45 PM, Christian Schneider
> <chris@die-schneider.net <ma...@die-schneider.net>> wrote:
>
>     As you can not change the jdk code I think such a workaround is
>     acceptable.
>     Btw. It is a good practice to save the old ThreadContextClassLoader
>     and restore it after the call.
>
>     Christian
>
>     Am 24.04.2012 22 <tel:24.04.2012%2022>:08, schrieb Hervé BARRAULT:
>
>         Hi, i did a really ugly quick fix using ThreadContextClassLoader
>         and it is working (using resolveClass for ObjectInputStream).
>
>         I say ugly because it is still based on class name [not OSGI
>         compliant] but it validates the ThreadContextClassLoader
>         "Workaround".
>
>         Thanks
>         Regards
>         hervé
>
>
>     --
>
>     Christian Schneider
>     http://www.liquid-reality.de
>
>     Open Source Architect
>     Talend Application Integration Division http://www.talend.com
>
>

-- 
Jean-Baptiste Onofré
jbonofre@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com

Re: OSGi and ClassNotFoundException

Posted by Hervé BARRAULT <he...@gmail.com>.
Hi, thanks for the tip.

I just think that Karaf provides DOSGi implementation [not in my old
version]. I guess this implementation has the right implementation of
serialization.

Regards
Hervé


On Tue, Apr 24, 2012 at 10:45 PM, Christian Schneider <
chris@die-schneider.net> wrote:

> As you can not change the jdk code I think such a workaround is acceptable.
> Btw. It is a good practice to save the old ThreadContextClassLoader and
> restore it after the call.
>
> Christian
>
> Am 24.04.2012 22:08, schrieb Hervé BARRAULT:
>
>  Hi, i did a really ugly quick fix using ThreadContextClassLoader and it
>> is working (using resolveClass for ObjectInputStream).
>>
>> I say ugly because it is still based on class name [not OSGI compliant]
>> but it validates the ThreadContextClassLoader "Workaround".
>>
>> Thanks
>> Regards
>> hervé
>>
>
> --
>
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> Talend Application Integration Division http://www.talend.com
>
>

Re: OSGi and ClassNotFoundException

Posted by Christian Schneider <ch...@die-schneider.net>.
As you can not change the jdk code I think such a workaround is acceptable.
Btw. It is a good practice to save the old ThreadContextClassLoader and 
restore it after the call.

Christian

Am 24.04.2012 22:08, schrieb Hervé BARRAULT:
> Hi, i did a really ugly quick fix using ThreadContextClassLoader and 
> it is working (using resolveClass for ObjectInputStream).
>
> I say ugly because it is still based on class name [not OSGI 
> compliant] but it validates the ThreadContextClassLoader "Workaround".
>
> Thanks
> Regards
> hervé

-- 

Christian Schneider
http://www.liquid-reality.de

Open Source Architect
Talend Application Integration Division http://www.talend.com


Re: OSGi and ClassNotFoundException

Posted by Hervé BARRAULT <he...@gmail.com>.
Hi, i did a really ugly quick fix using ThreadContextClassLoader and it is
working (using resolveClass for ObjectInputStream).

I say ugly because it is still based on class name [not OSGI compliant] but
it validates the ThreadContextClassLoader "Workaround".

Thanks
Regards
hervé


On Tue, Apr 24, 2012 at 5:45 PM, Hervé BARRAULT <he...@gmail.com>wrote:

> Hi thanks for the explanation about the Class.forname usage (It is clear
> when you don't forget that you can manipulate at the same classes in
> different versions).
>
> I think, it could be a good idea that the OSGi container provides a
> serialization/deserialization service or tool which covers the constraints
> of OSGi.
>
> Regards
> Hervé
>
>
>
> On Tue, Apr 24, 2012 at 5:22 PM, Christian Schneider <
> chris@die-schneider.net> wrote:
>
>> Hi Hervé,
>>
>> does not look like ObjectInputStream is really doing this cleanly. It
>> just uses Class.forname which is not good in the OSGi case.
>> You can try to set the ContextClassloader like this before calling the
>> deserialization code:
>> Thread.currentThread().**setContextClassLoader(**
>> YourSerializedClass.class.**getClassLoader());
>>
>> The context idea only works when you do the serialization code yourself.
>> It would just be a List<Class> with the classes to work with. So
>> you could instantiate a class by classList.get(num).**newInstance();
>> Btw. this is the best solution in OSGi whenever possible. Just do not use
>> class names in String form and instead directly use Class objects that you
>> initialize in
>> the bundle that already has access to this class.
>>
>> Peter Kriens wrote in one of his blog entries that in OSGi there is not a
>> simple class name as you may have different versions of the same class in
>> the system. So a class name is only unique when you also specify the
>> classloader. Using the Class object in the first place completely avoids
>> this problem.
>>
>>
>> Christian
>>
>> Am 24.04.2012 16:52, schrieb Hervé BARRAULT:
>>
>>  Hi,
>>> thanks for the answer.
>>>
>>> The deserialization code is like this :
>>>
>>> final byte[] byteData = Base64.decodeBase64(dataStr);
>>>
>>> ByteArrayInputStream bout = null;
>>> ObjectInputStream oos = null;
>>> try {
>>>    bout = new ByteArrayInputStream(byteData)**;
>>>    oos = new ObjectInputStream(bout);
>>>    toReturn = oos.readObject();
>>> } catch( ...) {
>>>
>>> } finally {
>>>
>>> }
>>>
>>> With the ObjectInputStream there is no class loader parameters but some
>>> resolver (i will check this way).
>>>
>>> For the second case, do you have an example of "class context injection"
>>> ?
>>>
>>> Regards
>>> Hervé
>>>
>>
>> --
>> Christian Schneider
>> http://www.liquid-reality.de
>>
>> Open Source Architect
>> Talend Application Integration Division http://www.talend.com
>>
>>
>

Re: OSGi and ClassNotFoundException

Posted by Hervé BARRAULT <he...@gmail.com>.
Hi thanks for the explanation about the Class.forname usage (It is clear
when you don't forget that you can manipulate at the same classes in
different versions).

I think, it could be a good idea that the OSGi container provides a
serialization/deserialization service or tool which covers the constraints
of OSGi.

Regards
Hervé



On Tue, Apr 24, 2012 at 5:22 PM, Christian Schneider <
chris@die-schneider.net> wrote:

> Hi Hervé,
>
> does not look like ObjectInputStream is really doing this cleanly. It just
> uses Class.forname which is not good in the OSGi case.
> You can try to set the ContextClassloader like this before calling the
> deserialization code:
> Thread.currentThread().**setContextClassLoader(**
> YourSerializedClass.class.**getClassLoader());
>
> The context idea only works when you do the serialization code yourself.
> It would just be a List<Class> with the classes to work with. So
> you could instantiate a class by classList.get(num).**newInstance();
> Btw. this is the best solution in OSGi whenever possible. Just do not use
> class names in String form and instead directly use Class objects that you
> initialize in
> the bundle that already has access to this class.
>
> Peter Kriens wrote in one of his blog entries that in OSGi there is not a
> simple class name as you may have different versions of the same class in
> the system. So a class name is only unique when you also specify the
> classloader. Using the Class object in the first place completely avoids
> this problem.
>
>
> Christian
>
> Am 24.04.2012 16:52, schrieb Hervé BARRAULT:
>
>  Hi,
>> thanks for the answer.
>>
>> The deserialization code is like this :
>>
>> final byte[] byteData = Base64.decodeBase64(dataStr);
>>
>> ByteArrayInputStream bout = null;
>> ObjectInputStream oos = null;
>> try {
>>    bout = new ByteArrayInputStream(byteData)**;
>>    oos = new ObjectInputStream(bout);
>>    toReturn = oos.readObject();
>> } catch( ...) {
>>
>> } finally {
>>
>> }
>>
>> With the ObjectInputStream there is no class loader parameters but some
>> resolver (i will check this way).
>>
>> For the second case, do you have an example of "class context injection" ?
>>
>> Regards
>> Hervé
>>
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> Talend Application Integration Division http://www.talend.com
>
>

Re: OSGi and ClassNotFoundException

Posted by Christian Schneider <ch...@die-schneider.net>.
Hi Hervé,

does not look like ObjectInputStream is really doing this cleanly. It 
just uses Class.forname which is not good in the OSGi case.
You can try to set the ContextClassloader like this before calling the 
deserialization code:
Thread.currentThread().setContextClassLoader(YourSerializedClass.class.getClassLoader());

The context idea only works when you do the serialization code yourself. 
It would just be a List<Class> with the classes to work with. So
you could instantiate a class by classList.get(num).newInstance();
Btw. this is the best solution in OSGi whenever possible. Just do not 
use class names in String form and instead directly use Class objects 
that you initialize in
the bundle that already has access to this class.

Peter Kriens wrote in one of his blog entries that in OSGi there is not 
a simple class name as you may have different versions of the same class 
in the system. So a class name is only unique when you also specify the 
classloader. Using the Class object in the first place completely avoids 
this problem.


Christian

Am 24.04.2012 16:52, schrieb Hervé BARRAULT:
> Hi,
> thanks for the answer.
>
> The deserialization code is like this :
>
> final byte[] byteData = Base64.decodeBase64(dataStr);
>
> ByteArrayInputStream bout = null;
> ObjectInputStream oos = null;
> try {
>     bout = new ByteArrayInputStream(byteData);
>     oos = new ObjectInputStream(bout);
>     toReturn = oos.readObject();
> } catch( ...) {
>
> } finally {
>
> }
>
> With the ObjectInputStream there is no class loader parameters but 
> some resolver (i will check this way).
>
> For the second case, do you have an example of "class context injection" ?
>
> Regards
> Hervé

-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
Talend Application Integration Division http://www.talend.com


Re: OSGi and ClassNotFoundException

Posted by Hervé BARRAULT <he...@gmail.com>.
Hi,
thanks for the answer.

The deserialization code is like this :

final byte[] byteData = Base64.decodeBase64(dataStr);

ByteArrayInputStream bout = null;
ObjectInputStream oos = null;
try {
    bout = new ByteArrayInputStream(byteData);
    oos = new ObjectInputStream(bout);
    toReturn = oos.readObject();
} catch( ...) {

} finally {

}

With the ObjectInputStream there is no class loader parameters but some
resolver (i will check this way).

For the second case, do you have an example of "class context injection" ?

Regards
Hervé


On Tue, Apr 24, 2012 at 4:36 PM, Christian Schneider <
chris@die-schneider.net> wrote:

> That is the typical case like in jpa where you have a generic service that
> needs to create objects from a packages it can not know at compile time.
>
> The typical solution for this is to give B the classloader of C. So
> currently you might have a deserialize method like:
> Object object = unmarshal(InputStream is);
> So the idea is to change this to
> Object object = unmarshal(InputStream is, Classloader classloader);
>
> So C can give B his classloader and B can use this to create objects only
> C knows but not B. Another way is to give B a kind of context that is
> configured with a list of the
> classes from A. C can initialize this context so B does not have to load
> these classes at all.
>
> Christian
>
> Am 24.04.2012 15:53, schrieb Hervé BARRAULT:
>
>  Hi,
>>
>> I have a case where i can't see how to cleanly list the imported packages
>> without using DynamicImport-Package.
>>
>> Example :
>>
>> I have a bundle A where there is the whole dto.
>>
>> I have a bundle B which defines a "container" library (basically a
>> container can support any Serializable and provides
>> serialization/deserialization tools).
>>
>> I have a bundle C which use a container (from B) and add in this
>> container some object from the dto (from A)
>> In the bundle C, I instantiate the classes from the bundle B and A.
>>
>> When i put "object from A" into "container from B" in "my code from C" it
>> is working without problem.
>>
>> When i try to get "object from A" from "container from B" in "my code
>> from C" i get a ClassNotFoundException for the object in A.
>>
>> My Bundle B has no specific import (i think this library shall be
>> "agnostic").
>>
>> My bundle C import packages from A and B.
>>
>>
>> For Information, in B library we are using genericity which is perhaps a
>> problem for imports.
>>
>>
>> Where am I missing something ?
>>
>> Regards
>> Hervé
>>
>>
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> Talend Application Integration Division http://www.talend.com
>
>

Re: OSGi and ClassNotFoundException

Posted by Christian Schneider <ch...@die-schneider.net>.
That is the typical case like in jpa where you have a generic service 
that needs to create objects from a packages it can not know at compile 
time.

The typical solution for this is to give B the classloader of C. So 
currently you might have a deserialize method like:
Object object = unmarshal(InputStream is);
So the idea is to change this to
Object object = unmarshal(InputStream is, Classloader classloader);

So C can give B his classloader and B can use this to create objects 
only C knows but not B. Another way is to give B a kind of context that 
is configured with a list of the
classes from A. C can initialize this context so B does not have to load 
these classes at all.

Christian

Am 24.04.2012 15:53, schrieb Hervé BARRAULT:
> Hi,
>
> I have a case where i can't see how to cleanly list the imported 
> packages without using DynamicImport-Package.
>
> Example :
>
> I have a bundle A where there is the whole dto.
>
> I have a bundle B which defines a "container" library (basically a 
> container can support any Serializable and provides 
> serialization/deserialization tools).
>
> I have a bundle C which use a container (from B) and add in this 
> container some object from the dto (from A)
> In the bundle C, I instantiate the classes from the bundle B and A.
>
> When i put "object from A" into "container from B" in "my code from C" 
> it is working without problem.
>
> When i try to get "object from A" from "container from B" in "my code 
> from C" i get a ClassNotFoundException for the object in A.
>
> My Bundle B has no specific import (i think this library shall be 
> "agnostic").
>
> My bundle C import packages from A and B.
>
>
> For Information, in B library we are using genericity which is perhaps 
> a problem for imports.
>
>
> Where am I missing something ?
>
> Regards
> Hervé
>


-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
Talend Application Integration Division http://www.talend.com