Since there can be three different class loaders in play (1), 1) the service's,
2) the UIDescriptor's and 3) the clients classpath, we have to account for this
in the end. Many times the ServiceItem.service object and the UIDescriptor(s)
share the same codebase so there will only be two class loaders, the remote one
and the client's classpath. It is important that unmarshalling always specify
the appropriate parent class loader so that "compatible classes" are achievable
through normal PreferredClassLoading mechanisms (or whatever RMIClassLoaderSPI
or CodebaseClassAccess impl does).
For the UIDescriptor.getUIFactory() invocation, I agree with Calum that this
seems more like a bug opportunity.
Gregg
(1)The RMIClassLoaderSPI can return any annotation it wants, so the
MarshalledObject passed into the construction of the UIDescriptor which is then
placed into the attributeSet (the Entry objects) for the service registration
might have a different codebase annotation and thus a different class loader
than the ServiceItem.service value.
On 2/14/2011 5:19 PM, Mark Brouwer wrote:
Hi Calum,
The ServiceUI support implemented as part of RIVER-292 is indeed very basic. I
just needed a tool to debug GUIs associated with Jini services and the
commercial Inca-X browser I was using at that time didn't allow me to do that in
a satisfying way.
As you found out there is only support for the JFrameFactory, because that was
what I needed at that time, but it won't be that hard to support the other UI
factory interfaces listed in the ServiceUI specification and to honor the
attributes associated with the UIDescriptor as well as the role.
On 14/02/2011 15:34, Calum Shaw-Mackay wrote:
All -
I believe this may be tied to RIVER-292, but I'll just outline the issue
The UIDescriptor is being asked to load the UIFactory via the current
thread's Context Class Loader rather than the
classloader that the service itself is being loaded with.
Thus the code:
try {
JFrameFactory uiFactory = (JFrameFactory)
uiDescriptor.getUIFactory(Thread.currentThread().getContextClassLoader());
JFrame frame = uiFactory.getJFrame(item);
frame.validate();
frame.setVisible(true);
}
should be
try {
JFrameFactory uiFactory = (JFrameFactory)
uiDescriptor.getUIFactory(item.service.getClass().getClassLoader());
JFrame frame = uiFactory.getJFrame(item);
frame.validate();
frame.setVisible(true);
}
In the subject you mention the word 'bug', did you really run into a problem or
did you notice the code above doesn't match the code in the ServiceUI
specification?
The UIDescriptor will only set the thread context class loader to the class
loader passed in while unmarshalling the marshalled UI factory, so it ain't as
bad as you make it sound ;-). Although your code snippet should be used, the
code currently in place should give no problems in case the UI factory itself
originates from the same codebase as the service (ServiceItem). In case the
UIFactory is coming from a different codebase there will be impact though.
Regards,