Hi Michał,
I didn't take it personal, and don't expect you to take it personal
either when I say, I'm pretty sure everyone here is aware of River /
Jini limitations.
Anyway River has been a lot of fun, all the best for the future
everyone, hope to see you around from time to time.
Cheers,
Peter.
On 16/02/2022 7:53 pm, Michał Kłeczek wrote:
Hi Peter,
On 16 Feb 2022, at 10:01, Peter Firmstone
<peter.firmst...@zeus.net.au> wrote:
Inline below.
On 16/02/2022 5:24 pm, Michał Kłeczek wrote:
On 16 Feb 2022, at 04:25, Peter Firmstone
<peter.firmst...@zeus.net.au> wrote:
From the CodebaseAccessor service.
The CodebaseAccessor proxy (local code) is passed as a parameter
along with a MarshalledInstance of the proxy, by ProxySerializer to
ProxyCodebaseSpi.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/export/CodebaseAccessor.java
<https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/export/CodebaseAccessor.java>
Ok, so you have introduced a level of indirection to retrieve String
codebase annotations. Why not go one step further and instead of:
interface CodebaseAccessor {
String getClassAnnotation() throws IOException;
}
have something along the lines of (conceptually):
interface Codebase extends RemoteMethodControl {
ClassLoader getClassLoader() throws IOException;
}
I personally wouldn't take this step, because CodebaseAccessor is a
Remote interface and ClassLoader is a class of high privilege, so it
presents a security risk.
Not really as implementation is constrained by the same security rules
as any other code: you can constrain it via policy that only grants
create ClassLoader permission to specific implementations.
See above:
you can move this code from the client to the service and let it
provide the implementation of class resolution algorithm.
I would advise against that, the remote service JVM knows little
about the client JVM, both are likely to have completely different
ClassLoader hierarchies.
To be able to communicate they have to understand each other class
loading mechanism anyway.
In particular the class annotation String syntax and semantics has to
be the same for both.
[...]
If using OSGi, OSGi will resolve the required dependencies and
download them if not already present on the client, OSGi will give
preference if a compatible version of the bundle dependencies
already loaded at the client. If using preferred classes the
preferred class list will determine the order of preference,
whether classes are loaded from the proxy codebase or the client
ClassLoader (the parent loader of the proxy ClassLoader) first.
I also tried this route and it is a dead end because
* it is not possible to statically (ie. as part of the software
package like OSGi manifest) provide dependency resolution
constraints to be able to exchange arbitrarily constructed object
graphs *
This is a limitation and compromise I have accepted, JGDMS doesn't
attempt to load arbitrarily constructed object graphs, instead it
ensures that both endpoints of a Service have the same class
resolution view, the same proxy bundle version is used at the Server
and client.
This breaks once there are multiple parties (services) involved
because it means _all_ of them have to have their software versions
synchronised in advance - which in turn makes the excercise moot: if
you have to do that there is no need for mobile code anymore.
What is really IMHO needed is a practical way of independent evolution
of system components.
At the server, the proxy bundle is depended upon by the service
implementation, but nothing at the client depends upon the proxy
bundle loaded there, instead the proxy bundle depends on the api
loaded by the client. That is why JGDMS discourages marshaling of
client subclasses that override service method parameter classes,
because they cannot be exported as remote objects and are subject to
codebase annotation loss and class resolution problems.
There is no subclassing in my example of RemoteEventSpacePublisher.
Sometimes, less is more, I've chosen this compromise in this instance
to avoid complexity. I saw little to be gained from the added
complexity, it can be worked around by improving service api design
and practices.
It cannot. How would you improve RemoteEventListener or JavaSpace API
to avoid these issues?
Instead the client can export method parameter interface types as
remote objects, with independent ClassLoader visibility, that will
resolve to common super interface types.
If there is a versioning problem at the client, where it uses an
incompatible API with the client, ServiceDiscoveryManager will
recognise the service is the incorrect type and discard it.
The whole point of my example is that this is not the issue of
compatibility between client and service interface but it is inherent
to existing class loading mechanism.
I recognise my own limitations, I'm not smart enough to solve the
problems of de-serialization of arbitrary object graphs,
so I have left it as a task for someone either smarter or more
determined than myself and focused on what I believe is an acceptable
and reliable compromise. It is because of my own limitations, that I
reduced complexity, so that I (as well as inexperienced users) didn't
have to worry about codebase annotation loss or class resolution issues.
I'm not saying it can't be solved, or that you won't succeed, simply
that after a lot of thought, I decided it would be easier to reduce
complexity and accept some limitations as this seems like the best
compromise, there are also other things which have a higher priority
for my time.
It wasn’t my intent to make this really interesting technical
discussion personal but rather try to discuss the limitations of
Jini/River and the possible directions.
I personally find the idea of mobile objects really interesting and
very influential to the way how systems are implemented.
Having a single uniform way of exchanging both code and data opens up
a lot of possibilities.
Think of loggers being services implemented by mobile objects that can
be replaced with new versions easily - log4shell would not be such a
huge nightmare to handle.
What’s more - mobile code is something you are doing anyway - but in
an ad-hoc ways that are incompatible with each other.
Michal