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

Regards,

Peter.

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

Reply via email to