|
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é |
|
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 |
|
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. |
|
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 |
|
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 |
|
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é, |
|
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:
|
|
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 |
|
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 |
|
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. |
|
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 |
|
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 |
| Powered by Nabble | Edit this page |
