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