In Jini/River, there are two ways that any class is resolved.  First, it is 
resolved because a class under construction has a reference to it.  Second is 
that it is resolved by a client class that needs it to specify an 
interface/class to use for service discovery/usage.

In the first case, we don’t care where it is resolved, if the second case 
doesn’t occur.   For the first case, every service JAR file should carry the 
definition of every single class that it depends on, marking those that will 
never be encountered for the Second case as preferred.

This is just a simple fact of how mobile code works.  If the “jar” that the 
service uses to resolve classes for the first case can be the same jar as the 
client uses to resolve the classes in the second case (OSGI, Maven and other 
non-mobile code, jar distribution mechanisms), then you can have one class 
loader having view of the class.

The Preferred class loader will do the right thing, automatically as long as 
you create the correct preferred list.  If you don’t do that correctly, then 
you can encounter problems.  Without a preferred list, the PreferredClassLoader 
is going to always look in the parent class loader, and that is usually the 
right thing to do.  Most people encounter problems when the list something as 
preferred which is then passed around to another “proxy” that has another 
instance of the same class that is not resolved to the first class loader and 
then you see class cast exception.

The preferred list should only really ever contain the names of classes that 
are not publicly visible in the API or any reference those public API classes 
have.

The basic reason to not use Maven or OSGi or other static class resolution 
mechanisms is that it provides one the flexibility to have a much more 
dynamically evolving runtime environment including test scenarios where it 
doesn’t make sense to “publish” a jar file that others may then have access to.

Gregg Wonderly

On Mar 4, 2014, at 12:02 AM, Michał Kłeczek <michal.klec...@xpro.biz> wrote:

> The real problem is that Util interface is in two codebases. It should be
> in a single codebase shared between UtilProxy and WrapperProxy.
> But to make it possible we would need to have peer class loading like in
> ClassWorlds or OSGI.
> It is not solvable in a standard hierarchical class loading scheme.
> 
> Anyway... It is not really River-436 problem so my patch proposal is going
> to have the same issue since it is just a replacement for String
> annotations and not change in class loading scheme.
> 
> Thanks,
> Michal
> 4 mar 2014 06:38 "Michał Kłeczek" <michal.klec...@xpro.biz> napisał(a):
> 
>> 1. The problem is there is no such thing as "the service interface". It is
>> context dependent. What is "the service interface" for service browser?
>> 
>> 2. In this particular case Util interface is an implementation detail of
>> WrapperProxy. It is Wrapper interface the client is interested in. So I
>> would say it should be preferred in WrapperProxy codebase.
>> 
>> 3. Even if Util is not preferred in WrapperProxy codebase we still have
>> ClassCastException if the client does not have Util in its classpath. Why
>> should it? it is interested in Wrapper not in Util. So either
>> a. We always get ClassCastException if Util is preferred in WrapperProxy
>> codebase, or
>> b. We get ClassCastException anyway if a client does not have Util in its
>> classpath.
>> Let's say I want to register RemoteEventListener that wraps a Javaspace
>> proxy to write events in a space. Does that mean the service "event source"
>> has to be aware of Javaspace interface??? That would be absurd...
>> 
>> It all does not have anything to do with codebase services.
>> 
>> Thanks,
>> Michal
>> 4 mar 2014 00:09 "Peter" <j...@zeus.net.au> napisał(a):
>> 
>>> The Util interface should not be preferred.  Implementations of Util can
>>> be preferred but not Util itself.
>>> 
>>> Services need a common api that all implementations and clients can use
>>> to interract, even if this is a kind of codebase service.
>>> 
>>> Modifying an interface is generally considered bad practise but now Java
>>> 8 makes it possible to add default methods for added functionality, that
>>> line blurs somewhat.  What can you do if an earlier interface is loaded by
>>> a parent ClassLoader and you need a later version, make it preferred?
>>> 
>>> My thoughts are that interfaces should never be preferred and all classes
>>> defined in their methods shouldn't be preferred either.
>>> 
>>> It would be relatively easy to write a new implementation that ensures
>>> that interfaces are loaded into their own ProtectionDomain in a parent
>>> ClassLoader.  But that would be confusing as dynamic policy grants are made
>>> to ClassLoader's not ProtectionDomains.
>>> 
>>> But using ProtectionDomains in this manner, preserves security, ensures
>>> maximum visibility and avoids codebase annotation loss, if we ask the
>>> ProtectionDomain for the annotation, instead of the ClassLoader.  But this
>>> is not how we do things presently.
>>> 
>>> Cheers,
>>> 
>>> Peter.
>>> 
>>> ----- Original message -----
>>>> But it will also be loaded by WrapperProxy ClassLoader, since it is
>>>> preferred there. So it will end up with ClassCastException, right?
>>>> 
>>>> Regards,
>>>> Michal
>>>> 
>>>> If Util is installed locally, it will only be loaded by the application
>>>> ClassLoader, since it isn't preferred.
>>>> 
>>>> Peter.
>>>> 
>>>> ----- Original message -----
>>>>> Folks,
>>>>> while woking on the River-436 patch proposal I've came across the
>>>>> scenario that I am not sure how to handle:
>>>>> 
>>>>> Utility service:
>>>>> //inteface is NOT preferred
>>>>> interface Util {...}
>>>>> //class IS preferred
>>>>> class UtilProxy implements Util {}
>>>>> 
>>>>> Wrapper service:
>>>>> //NOT preferred
>>>>> interface Wrapper {}
>>>>> //preferred
>>>>> class WrapperProxy implements Serializable{
>>>>> //initialized with Util impl from a lookup service
>>>>> private Util util;
>>>>> }
>>>>> 
>>>>> Wrapper service codebase includes Util interface but it is
>>> _preferred_.
>>>>> 
>>>>> Would deserialization of WrapperProxy end with ClassCastException?
>>>>> From what I understand UtilProxy is annotated with its codebase. When
>>>>> deserializing UtilProxy a ClassLoader is going to be created with
>>>>> parent set to TCCL. It means Util interface is going to be loaded
>>>>> twice by two ClassLoaders - one for WrapperProxy codebase and another
>>>>> for UtilProxy codebase.
>>>>> 
>>>>> Am I correct?
>>>>> And if so: is it desired behavior?
>>>>> 
>>>>> Regards,
>>>>> 
>>>>> --
>>>>> Michał Kłeczek
>>>>> XPro Quality Matters
>>>>> http://www.xpro.biz
>>>>> 
>>> 
>>> 

Reply via email to