Thanks Chris,
Sound like it's time for some MarshalledInstance Refactoring?
Perhaps a Maven (generic if possible) URL schema (with message digest
support), we need an annotation (or name convention) that indicates
whether proxy's can share ClassLoader & ProtectionDomain space, dictated
by static variables and common Principals.
A new constructor for MarshalledInstance that accepts an alternate URL too.
... and two new methods in MarshalledInstance:
Object get(ClassLoader cl, CodeSource[] cs, boolean
verifyCodeBaseIntegrity);
URL[] getCodeSourceAnnotation();
Then MarshalledServiceItem could include new methods:
public URL[] getCodeSourceAnnotation();
public Object getService( CodeSource[] cs );
//If cs == null || cs missing a CodeSource use default URL.
Note here that while unmarshalling has been delayed, I haven't
relinquished control of ClassLoaders or ProtectionDomains, eg the client
can use OSGi, without dictating the Service must also, none of the
serialized instances from method returns will need to be deserialized by
OSGi, avoiding altogether the OSGi deserialization issue.
The client application doesn't have to deal with these concerns
directly, we could write multiple ResultStreamFilters that can be
chained, the filter that matches the URL schema will unmarshall the
service, the filter sequence will dictate the preferred unmarshalling.
The filter responsible for successful unmarshalling would construct a
new ServiceItem, that isn't unmarshalled, the next unmarshalling filter
would ignore it, allowing it to pass through. After it is unmarshalled
another filter will check method constraints.
Method Parameters that originate from client ClassLoaders will be
unmarshalled in the Application ClassLoader space on the Service
implementation node, this is where things get hairy if the Service API
method parameters are non final, abstract or interfaces. Any class that
belongs to a Service API jar will be safely loaded into the Jini
Platform ClassLoader space in it's own ProtectionDomain. Client
returned parameter classes however will need their own ClassLoader's
If the Service API is loaded into a Parent ClassLoader (Jini Platform
ClassLoader) at the Service implementation node and API parameters are
extended, the client classes will need their own ClassLoader space at
the Service Implementation end, Since a service may serve many clients,
these ClassLoaders must be shared, based on identical CodeSource and
Principals. The client classes will only be accessible via the Service
API interfaces or classes (they are abstracted).
ANY CLIENT THAT IMPLEMENTS AN API Interface or extends an API parameter,
will need to make it's implementation package jar publicly available.
Like the proxy implementation, it is free to change, however it should
be versioned appropriately, like the proxy and have it's own jar. (
This is where the Java Package Version Spec comes in handy, we can
annotate classes with Package version and local CodeSource). The
CodeSource might contain a file URL, however it will contain the jar
archive name (which is why Dennis want's to name packages with their
versions, which can't hurt!) and given the Package Version Spec, it will
work for OSGi bundles as well as Maven. A client using an OSGi bundle
must remember that all of the implementing classes should be in the same
bundle and the Service node and may not be utilising OSGi, so shouldn't
attempt to use any OSGi services in Service API parameter implementations.
The version spec will identify compatiblity of classes, the closed
compatible local CodeSource may be used, otherwise a new ClassLoader
will be used. Each client will either share all compatible CodeSource
and Principals or have their own ClassLoader space.
Greg, do you think we could use your service-client.jar for client
parameter implementations or would this cause confusion?
Perhaps we should use:
service-param.jar
So to really round if off:
Service Implementers must produce versioned manifest jar archives of:
Smart Proxy:
Implementation jar: service.jar (depends on service-api.jar)
API jar: service-api.jar
Smart proxy jar: service-proxy.jar (depends on service-api.jar)
Selfish Smart proxy jar: service-iproxy.jar (depends on
service-api.jar)
Dumb Proxy:
Implementation jar: service.jar (depends on service-api.jar)
API jar: service-api.jar
Client Implementers must produce version manifest jar archives of:
Client Parameter extensions: service-param.jar
If you didn't guess correctly the Selfish Smart proxy jar is the one
that proxy's cannot share in the same ClassLoader and ProtectionDomain.
ClassLoader Structure (In addition to all your helpful comments on
river-dev, thanks also to Jim, Tim & Mike, planting the seed):
System ClassLoader
|
Extension ClassLoader (incl jsk-policy.jar)
|
Jini Platform ClassLoader (incl jsk-platform.jar, *-api.jar)
|
_______________|__________________________________
| | |
Application ClassLoader Proxy ClassLoader's Parameter Impl
ClassLoader's
(Apps & Service Impl) (Smart Proxy's) (Remote client
parameter classes)
Advise History:
Jim: Use common Interfaces and classes in Parent ClassLoaders
Tim: Thanks for research on Dependency Tree and ClassLoader Tree's
and guidance.
Mike: Research paper on ClassLoader issues.
Thanks & Praise worth mentioning:
Bob Scheifler and others for Jini's strong Security foundation.
Bill Venners for the ServiceUI, it is truly innovative
(hint: come back)
Christopher Dolan wrote:
Isn't List<URL> already present in the MarshalledInstance? Why repeat
this as an Entry? Wouldn't it be easier to just add a public accessor
to deserialize the list of URLs from MarshalledInstance.locBytes?
I apologize if this was already explained, but there's been a LOT of
email to read on this list lately.
Chris
-----Original Message-----
From: Dennis Reedy [mailto:dennis.re...@gmail.com]
Sent: Saturday, May 22, 2010 9:29 AM
To: river-dev@incubator.apache.org
Subject: Re: Maven repository Entry was Re: Codebase service?
[CJD] ... <snip> ...
I would just go with a
List<String> dlJars;
With this you could provide support for retrieving the DL jar(s) for
non-maven systems as well. If the dlJars property contains 1 element and
is of the form groupId:artifactId:version:classifier, then maven
resolution gets used. Otherwise the DL jars can be obtained using the
codebase of the advertising service.
For maven resolution, I think you'll also want to either provide support
for parsing your maven settings.xml or include the repositories to go
find the artifact if it's not present. If the artifact is retrieved from
the repository it will have a message digest along side of it (with
either a .sha1 or .md5 extension). That can be used to compare a locally
computed digest HttpmdUtil.computeDigest() for updates. But that
comparison really only needs to take place for snapshots, since by
definition releases are considered immutable.
IMO supporting transitive deps is a must have, without that we really
dont get that far. A DL artifact may depend on another DL artifact, and
that DL artifact may have deps as well.