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

Reply via email to