Patricia Shanahan wrote:
Peter Firmstone wrote:
Zoltan Juhasz wrote:
Peter,
I am (has been) interested in the Internet use of Jini. There are many
issues as you have noted below. More fundamental is the model of
interaction
between services. Way back I was trying to talk about these issues in a
London Jini Meeting perhaps without much success. There are two main
schools
of thought in service interaction; API vs messaging (aka document)
based
models.
Messaging relies on a relatively simple send/receive interface, the
real
thing is the content. Services are meant to be intelligent enough to
interpret these messages and deal with them accordingly. In the
networking
world (and also in the Jini community) this is referred to as the
world of
protocols. My personal belief is that these only work for simple and
well-defined services like ftp and the like. If you ask agent people
they
will say the opposite I suppose.
The API approach that Jini takes requires up-front design work and
same say
these systems will inherently be brittle. I think versioning is a
problem in
both approaches.
Versioning - Service API is like an Interface, once it is widely in
use, it cannot change, the implementation can, but the API cannot,
since it is installed in the client.
However we can extend service API, just like we can extend an Interface.
Then, new clients utilise the extended Service API, while old clients
continue to use the original, I've suggested the extended service API
jar archive previously, but it's also possible to add any new API
classes to the proxy download codebase. In the old client it will be
loaded with the proxy's ClassLoader, but not utilised (unless the
Service UI uses it), but the new interface won't be loaded by the
proxy ClassLoader at the new client, because the new client has
already loaded the extended Service API, in a parent ClassLoader,
since new clients are compiled against the extended API.
The mailing list [email protected] contains discussion of
"defender methods", which are intended to make it possible to specify a
default implementation for an interface method. A class that implements
the interface without supplying an implementation for the interface
method would use its default implementation instead of being treated as
an error.
With that in place, it would be possible to add a method to an interface
as long as it can be given a default implementation, without resorting
to a new extension.
Does that have any effect on River direction? Do we want to aim for
similar flexibility?
Patricia
It's an interesting feature for Interfaces.
For an Interface, that takes advantage of binary compatibility, client
classes don't object to additional methods, but implementing classes do,
hence the default implementation for new methods. Allowing a default
implementation for a new interface method, sounds like multiple
inheritance, eg extending three abstract classes, without allowing
object global fields. Time will tell if it's desirable.
It may be possible to use this new interface feature in Service API,
since it is a way of providing backward compatibility and provided that
the Service API remains backward compatible it shouldn't be a problem,
however I'm not sure about how Reggie will handle it.
Service API, is a jar archive containing public interfaces and classes
common to the client, service and proxy, installed at the client, which
the service has no control over. If the client and Service belong to
different people or corporations.... If there was a version management
system on the client, like OSGi, then it might be possible to ask the
client to update it's local copy of the Service API. But if the client
accesses another service and compatibility is broken between versions,
then the client must have a copy of both Service API versions and the
client doesn't have a way to treat each as the same class, unless it
uses a common superclass (eg Object).
From memory Reggie does allow for different versions of Service API,
but they are treated as separate types, this is probably important in a
Global sense, in case name conflicts occur.
The beauty of extending Service API is that there is always a common
superclass in the form of the original service API, for compatibility.
Service API may span several Interface and classes, such as parameters
and return objects, clients might export objects (unregistered services)
passed to the service as parameters.
There's much more complexity for Service API than an Interface class,
because it includes deployment, so I used a Simile to help developers
understand, I didn't mean it as Metaphor though.
Instead of changing a Service API incompatibly, create a new Service
API, create another Service that implements the deprecated Service API
but uses the new Service from within a smart proxy, until all clients
are updated.
Due to the complexity of Versioning within Service API, I think it's
easier if changes to Service API are limited to internal class
implementation changes and fixes, without changing serialization
compatibility and without adding new classes (which would cause
deserialization problems on the client). The minimum standard is that
Service API should always be backward compatible for clients that you
want to support.
It's far simpler to extend and distribute the extension classes in a
separate jar, that can be downloaded with the proxy for clients missing
the additional classes.
The Service implementation and proxy are free to change any way they
like, while they honor the Service API contract.
Cheers,
Peter.