Quantcast

OSGi and ClassNotFoundException

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

OSGi and ClassNotFoundException

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é

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

cschneider
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

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

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é


On Tue, Apr 24, 2012 at 4:36 PM, Christian Schneider <[hidden email]> 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 <a href="tel:24.04.2012%2015" value="+12404201215" target="_blank">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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

Holger Hoffstaette
In reply to this post by Hervé BARRAULT
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

cschneider
In reply to this post by Hervé BARRAULT
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

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

Hervé BARRAULT
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 <[hidden email]> 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 <a href="tel:24.04.2012%2016" value="+12404201216" target="_blank">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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

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é


On Tue, Apr 24, 2012 at 5:45 PM, Hervé BARRAULT <[hidden email]> 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 <[hidden email]> 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 <a href="tel:24.04.2012%2016" value="+12404201216" target="_blank">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



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

cschneider
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

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Reflection problem after bundle update/refresh

Marek Šabo
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

Hervé BARRAULT
In reply to this post by cschneider
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 <[hidden email]> 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 <a href="tel:24.04.2012%2022" value="+12404201222" target="_blank">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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

jbonofre
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
> <[hidden email] <mailto:[hidden email]>> 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é
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: OSGi and ClassNotFoundException

cschneider
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
>> <[hidden email] <mailto:[hidden email]>> 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

Loading...