I am not sure how OSGI relates to this question. But I can imagine the
situation like this:
class MySmartAssWrappingObject implements Serializable {
Object myMember;
...
private void readObject(ObjectInputStream ois) {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
myMember = ois.readObject();
}
}
That would allow you to do something similar to what you wanted to do
with class resolution by remembering the stack of class loaders.
So my question is:
is it something that people do?
Thanks,
Michal
Peter wrote:
In PreferredClassProvider, no the callers ClassLoader (context) is the parent ClassLoader of the codebase loader.
It depends on the ClassLoader hierarchy and chosen strategy used to resolve
annotations.
But the index key for PreferrefClassProvider is URI[] and parent loader
(callers loader).
This strategy allows codebases to be duplicated for different calling context.
OSGi however, only loads one Bundle per URL, but as Bharath has demonstrated,
the codebase loader doesn't have to be a BundleReference.
There are some caveats if the proxy codebase loader isn't a BundleReference,
one is your dependencies aren't version managed for you, and you can only see
public classes imported by the parent BundleReference.
The strategy of switching context wouldn't work with PreferredClassProvider.
Regards,
Peter.
Sent from my Samsung device.
Include original message
---- Original message ----
From: "Michał Kłeczek (XPro Sp. z o. o.)"<michal.klec...@xpro.biz>
Sent: 07/02/2017 07:20:59 am
To: dev@river.apache.org
Subject: Re: Changing TCCL during deserialization
This still does not answer my question - maybe I am not clear enough.
Do you have a need to set a TCCL DURING a remote call that is in progress?
Ie. you execute a remote call and DURING deserialization of the return value
you change the TCCL (so one class is resolved using one context loader and
another using a different one when reading THE SAME stream)
Thanks,
Michal
Gregg Wonderly wrote:
Anytime that a thread might end up being the one to download code, you need
that threads CCL to be set. The AWTEvent thread(s) in particular are a
sticking point. I have a class which I use for managing threading in
AWT/Swing. It’s called ComponentUpdateThread. It works as follows.
new ComponentUpdateThread<List<Item>>( itemList, actionButton1, actionButton2,
checkbox1 ) {
public void setup() {
// In event thread
setBusyCursorOn( itemList );
}
public List<Item>construct() {
try {
return service.getListOfItems( filterParm1 );
} catch( Exception ex ) {
reportException(ex);
}
return null;
}
public void finished() {
List<Item> let;
if( (lst = get()) != null ) {
itemList.getModel().setContents( lst );
}
}
}.start();
This class will make the passed components disabled to keep them from being
clicked on again, setup for processing use a non AWTEvent thread for getting
data with other components of the UI still working, and finally mark the
disabled components back to enabled, and load the list with the returned items,
if there where any returned.
There is the opportunity for 3 or more threads to be involved here. First,
there is the calling thread. It doesn’t do anything but start the work. Next,
there is an AWTEvent thread which will invoke setup(). Next there is a worker
thread which will invoke construct(). Finally, there is (possible another)
AWTEventThread which will invoke finished().
In total there could be up to four different threads involved, all of which
must have TCCL set to the correct class loader. My convention in the
implementation, is that that will be this.getClass()getClassLoader().
This is all managed inside of the implementation of ComponentUpdateThread so
that I don’t have to worry about it, any more. But it’s important to
understand that if you don’t do that, then the classes that the calling thread
can resolve, and Item in this specific case in particular, and you would thus
potentially see Item come from another class loader than you intended (the
services class loader with “null” as the parent), and this will result in
either a CNFE or CCE.
Gregg
On Feb 6, 2017, at 11:28 AM, Michał Kłeczek (XPro Sp. z o.
o.)<michal.klec...@xpro.biz> wrote:
What I was specifically asking for is whether this is needed during
deserialization or after deserialization.
In other words - if I can lock the TCCL to an instance of MarshalInputStream
existing for the duration of a single remote call.
Thanks,
Michal
Gregg Wonderly wrote:
The predominant place where it is needed is when you download a serviceUI
component from a proxy service which just advertises some kind of “browsing”
interface to find specific services and interact with them, and that serviceUI
is embedded in another application with it’s own codebase
appl->serviceUI-for-browsing->Service-to-use->That-Services-ServiceUI
In this case, TCCL must be set to the serviceui classes classloader so that the
“serviceui-for-browsing” will have a proper parent class pointer.
Anytime that downloaded code might download more code, it should always set
TCCL to its own class loader so that the classes it downloads reflect against
the existing class definitions.
Gregg
On Feb 6, 2017, at 12:03 AM, Michał Kłeczek (XPro Sp. z o.
o.)<michal.klec...@xpro.biz> <mailto:michal.klec...@xpro.biz> wrote:
Hi,
During my work on object based annotations I realized it would be more efficient not to
look for TCCL upon every call to "load class" (when default loader does not
match the annotation).
It might be more effective to look it up upon stream creation and using it
subsequently for class loader selection.
But this might change semantics of deserialization a little bit - it would not
be possible to change the context loader during deserialization.
My question is - are there any scenarios that require that?
I cannot think of any but...
Thanks,
Michal