Hi Peter,

Thanks for this.

I have a comment to make about what you write, but out of respect for the 
original poster, I will create a new thread.

See you in a few seconds.


Cheers,
=David



> On Feb 20, 2017, at 5:38 PM, Peter Kriens <peter.kri...@aqute.biz> wrote:
> 
> After working in this area for too many years I’ve come to the conclusion 
> that objects cannot be really transferred to other systems in a reliable way, 
> only self typed data can. JPA, RMI, and many other systems promise heaven to 
> the programmer that they can use their objects local and remote 
> transparently. The consequence of this dream is a huge amount of complexity 
> that far outweighs any gains in programmer friendliness. Few things have 
> caused so much trauma in the software world as ORM. (Persistence is 
> communications to a future process.)
> 
> The reason objects are so complex to use in communications is that it is in 
> direct violation of the goal of OO to hide your data. However, once you 
> expose the internal data on the wire you have effectively made it public but 
> too many people they can still have the advantages of abstract data types. 
> OSGi is a bitch in this case because it tells you that you’re trying to do 
> something wrong by refusing to cooperate. In this case, it balks at you 
> because you create an invisible dependency between the sender and the 
> receiver. Though this is a good thing too often the receivers of this message 
> blame the messenger.
> 
> You can handle this dependency but you’ll find out is that it is a hugely 
> complex task that introduces a lot of frailty in the overall system. Having 
> tried this several times I can assure you that any gains in programmer 
> friendliness are dwarfed by the complexity of creating this facade.
> 
> The best solution I found is to give up on data hiding. The fact your objects 
> is on the wire means that that wire format is public. I therefore use Data 
> Transfer Objects, in my case objects with public fields. On both sides I have 
> my own objects to provide behavior to this data with methods and classes but 
> this data record is at the core of my code. Since this data is public because 
> it goes over the wire it is better to wrap you code around that ‘standardized 
> public’ object than to try you internal object data.
> 
> If you look at the OSGi specifications of the past 5 year then you will 
> notice that all applicable APIs have been designed to be useful with 
> Distributed OSGi. Calls do not pass objects but they pass DTOs back and 
> forth. They do not rely that the receiver and sender have exactly the same 
> type and version. In this model it is easy to replace an endpoint using 
> another language, which is a really good sign.
> 
> For Java developers this is often an unpleasant message, and quite often OSGi 
> get the blame. However, the fact OSGi gives you these problems means that 
> you’re trying to do something that has hidden dependencies.
> 
> Distributed computing has 7 well known fallacies[1] but I strongly believe 
> that there is an eighth: ’One can communicate objects over a network’.
> 
> Now your question. Yes, you could run a resolve and load the proper bundles 
> but you introduce a huge amount of error cases and a large amount of 
> complexity and you won’t solve the fundamental problem. 
> 
> Kind regards,
> 
>       Peter Kriens
> 
> [1]: https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing 
> <https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing>
> 
> 
>> On 20 Feb 2017, at 05:13, Peter <j...@zeus.net.au <mailto:j...@zeus.net.au>> 
>> wrote:
>> 
>> Hello,
>> 
>> I'm currently working on converting an existing application to OSGi.
>> 
>> This application has a network service architecture based on java 
>> interfaces.  I've broken the application into modules, using a Maven build, 
>> which uses bnd and bndtools to create bundle manifests.  Some of these 
>> modules are ServiceLoader provider's, so I've used annotations to ensure 
>> these are loaded into the OSGi service registry using the Service Loader 
>> Mediator.
>> 
>> The main issue that I face is this application is a networked application 
>> and has it's own Remote Invocation protocols (which currently utilise Java 
>> Serialization, but not Java RMI).  As you'll appreciate, class visiblity is 
>> a little different in OSGi.  :)
>> 
>> The services mentioned above are remote services, these remote services have 
>> a proxy which implements the service interface, these services are 
>> discovered and installed at the client.  There are two types of proxy's, 
>> one, called a smart proxy, requires a codebase from which to retrieve a jar 
>> or jar files that are downloaded and installed at the cleint (traditionally 
>> during deserialization),  the other type of proxy is called a dynamic proxy 
>> (it's basically just an instance of java.lang.reflect.Proxy), which is 
>> dynamically generated at the client.
>> 
>> The Service implementation is broken up into three components:
>> 
>>  1. The service api
>>  2. The smart proxy (resolved and provisioned into in client jvm).
>>  3. The server
>> 
>> The server bundle imports packages from the smart proxy bundle, while the 
>> smart proxy imports packages from the service api as well as exporting it's 
>> own packages, as required by the server bundle.
>> 
>> The server that provides the remote service has three bundles loaded; 
>> server-impl, smart-proxy & service-api.
>> 
>> The client only has the service api bundle installed at deployment and the 
>> smart proxy is resolved and provisioned before the service is made available 
>> via the local OSGi service registry, where the client will learn of it's 
>> existence using ServiceTracker.
>> 
>> At first glance only the smart proxy bundle needs to be provisioned at the 
>> client, however for cases where a dynamic proxy is required to implement 
>> interfaces from different packages, where class visibility issues may exist, 
>> it may be beneficial in these cases to utilise and provision a proxy bundle 
>> that imports all these interfaces, one might do that by taking advantage of 
>> java's interface multiple inheritance; create a bundle that contains one 
>> interface (annotated with @ProviderType) which extends all interfaces, which 
>> the bundle doesn't export, so we ensure that the dynamic proxy has a proper 
>> bundle manifest with all package imports and version ranges correctly 
>> defined.
>> 
>> The inbuilt remote invocation protocol has server and client endpoints, the 
>> protocol is extensible and has a number of implementations (for example 
>> https, http, tls, kerberos, tcp).   Each endpoint is assigned a ClassLoader 
>> when it's created.
>> 
>> For classes installed at the client, these are typically installed in a 
>> URLClassLoader, typically with the Application loader as parent loader.  In 
>> an OSGi environment however, the smart proxy bundle will be installed at the 
>> client, it's ClassLoader utilised by the client endpoint, the smart proxy 
>> bundle will also be installed at the server and it's ClassLoader utilised by 
>> the server endpoint.   In this case the visibility of the bundles at each 
>> endpoint will be utilised to resolve serializable classes.    Private smart 
>> proxy serializable classes will be resolvable at each end, but only public 
>> classes from imported packages will be deserializable, since the client 
>> interacts using the Service API, all serializable classes in the Service API 
>> packages will need to be exported and public and imported by the client and 
>> smart proxy.
>> 
>> Once a bundle has been provisioned its ClassLoader will be given to the 
>> client endpoint and the marshalled state of the proxy unmarshalled into it.  
>> At this point the service that the proxy provides would be registered with 
>> the OSGi service registry for the client to discover and consume.  The smart 
>> proxy communicates with it's server via an internal dynamic proxy 
>> (java.lang.reflect.Proxy), it's used to invoke methods on the server.
>> 
>> While the existing protocol uses Java serialization, it doesn't use Java 
>> serialization's method of resolving classes.  Java Serialization walks the 
>> stack and finds the first non system classloader (looking for the 
>> application ClassLoader).    The existing class resolution method isn't 
>> suitable for OSGi, however the mechanism is extensible, so can be replaced 
>> with something suitable.
>> 
>> 
>> 
>> Does anyone have any advise or experience utilising the OSGi Enterprise 
>> Resolver Service Specification (chapter 136) and the OSGi Enterprise 
>> Repository Service Specification (chapter 132) to resolve and provision a 
>> bundle for the smart proxy at the client?
>> 
>> 
>> 
>> The intent here is the bundle manifests at each endpoint will be used to 
>> determine class visiblity, so the resolution and provisioning process will 
>> be of critical importance.
>> 
>> For anyone curios, the application is a fork of Apache River / Jini and I'm 
>> experimenting with support for OSGi.  I'm also a committer and PMC member of 
>> Apache River.  This isn't the old Jini we all know and love however, there 
>> are some additional features that allow provisioning to occur using a 
>> feature called delayed unmarshalling, so we can avoid the need for codebase 
>> annotations and URLClassLoaders.
>> 
>> The work in progress can be found here, for anyone who's curious:
>> 
>> https://github.com/pfirmstone/JGDMS/tree/Maven_build/modularize/JGDMS 
>> <https://github.com/pfirmstone/JGDMS/tree/Maven_build/modularize/JGDMS>
>> 
>> Regards,
>> 
>> Peter.
>> 
>> _______________________________________________
>> OSGi Developer Mail List
>> osgi-dev@mail.osgi.org
>> https://mail.osgi.org/mailman/listinfo/osgi-dev
> 
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev

_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to