Distributing OSGi – Differences From R-OSGi

A couple of people have asked about the differences between the implementation I have for a distributed OSGi framework and the framework described by Jan Rellermeyer (see my previous entry on the subject). In a nutshell, the primary difference is that the way services are advertised and discovered is completely hidden in my implementation. The implications, though, that this small difference has on usability and integration with existing OSGi frameworks is rather profound.

In Jan’s implementation, the primary interface to the system – from the client’s POV – is the RemoteOSGiService interface. To make use of a remote service the client does the following:
    // obtain the reference to the RemoteOSGi Service
    // insert standard method for obtaining services
    RemoteOSGiService remotingService = ….
    // create listener for the desired remote service
    DiscoveryListener listener = …..
    // create the properties for the listener service
    String[] ifaces = new String[] {“ch.ethz.iks.r_osgi.sample.api.ServiceInterface”};
    Dictionary props = new HashTable();
    props.put(DiscoverListener.SERVICE_INTERFACES, ifaces);
    // register the listener as a service
    bundleContext.registerService(DiscoverListener.class.getName(), listener, props);
Now, the DiscoveryListener provides for two methods, notifyDiscovery(ServiceURL) and notifyServiceLost(ServiceURL). The ServiceURL class is an implementation of the SLP service URL from Jan’s SLP implementation (available here in open source, of course). These methods do what you expect. When the service matching the SLP URL becomes available on the network, R-OSGi calls the notifyDiscovery() callback and here’s essentially what the implementation has to do:
    void notifyDiscovery(ServiceURL url) {
        ServiceInterface service = (ServiceInterface) remote.getFetchedService(url);
Likewise when the remote service disappears, the notifyServiceLost(ServiceURL) callback of the DiscoveryListener will be invoked.
From my point of view, this is quite an invasive system. First of all, the RemoteOSGiService interface is tied to a particular implementation of the SLP protocol implementation – i.e. Jan’s SLP implementation. Now, one could say that “Aha! We can solve that by making an OSGi SLP standard and abstract the concrete implementation out of the RemoteOSGi Service.” Which is pretty much the way I imagine how specification writers think. Writing specifications which spawns more specifications in some kind of cosmic meta-universe is what seems to be the primary purpose of specification writing committees, but I digress.
We could, for example, simply specify a java.net.URL which represents the SLP service URL. Or maybe we could specify the SLP service URL as a String. In my warped view of reality, however, it’s far better to simply remove the entire need for the introduction of the SLP service URL in any form what so ever – whether it be concrete class, java.net.URL or String. The point being that we’re tying the entire implementation into a particular definition of a discovery service.
Now, I’m not particularly anal about all of this. After all, SLP is a well defined, internationally recognized service discovery protocol with many implementations and pretty well understood. However, if you look at the actual r-osgi implementation, you can see that the match between the way OSGi registers services internally is almost a one-to-one match to SLP’s way of representing service URLs. So the question is, from my perspective, why do we have to expose SLP at all? What value does it add to manifest the SLP URL that makes it attractive to introduce this to the end user model?
Again, from my point of view, it’s quite clear that all of the information the SLP service URL represents is present in the OSGi representation of a service. Looking at the way Jan translates an OSGi service to the SLP service URL that it will be advertised under, it’s pretty clear that all you’re really doing is providing a convention which maps the properties associated with the registered service (remember, OSGi service registrations have a dictionary of properties) into a service registration in the SLP directory.
And so – to my thinking – if it’s an automatic conversion to and from the SLP service URL and attributes, then this is something that the end programmer need not be concerned with – i.e. SLP advertisement and discovery is an implementation artifact rather than something that the end user needs to be concerned with.
So, in my system, the end programmer only has to deal with existing OSGi concepts and mechanisms. There is still an additional step that must be taken by the client to indicate which remote services the client is interested in, and the same thing exists in Jan’s R-OSGi. But here’s how I do it in my system:
    // obtain the reference to the UnifiedRegistry Service
    // insert standard method for obtaining services
    UnifiedRegistry registry = ….
    // Register the filter for the services we desire
    Filter filter = bundleContext.createFilter(“(objectclass=ch.ethz.iks.r_osgi.sample.api.ServiceInterface)”);
Of course, I have in my actual implementation a convenience method when one doesn’t need the full power of the OSGi filter syntax and all you want to do is specify an interface name so the registration simply becomes:
    // Regster the filter for the services we desire
But again, I digress.
So, now that we have registered the filter indicating what services the client is interested in, how does the client get notified when the remote service actually appears or find out when the service disappears. Glad you asked. With the above scheme, the mechanism clients use is precisely the same mechanism that they use to get any other OSGi service. Following the same example, we could choose to do it using the bare bones OSGi mechanisms:
    ServiceReference ref = bundleContext.getServiceReference(“ch.ethz.iks.r_osgi.sample.api.ServiceInterface”);
    ServiceInterface service = bundleContext.getService(ref);
Of course, one could use the org.osgi.util.tracker.ServiceTracker which provides much the same kind of functionality as Jan’s listener does, except that it’s part of the standard OSGi R4 implementations and isn’t something we need to invent. Or one could use Filters and register a ServiceListener and get much the same functionality as Jan’s DiscoverListener interface:
    ServiceListener myListener = ….
    bundleContext.addServiceListener(myListener, “(objectclass=ch.ethz.iks.r_osgi.sample.api.ServiceInterface)”);
Or one could use OSGi’s Declarative Service model. Or, the mechanism I prefer and suggest, is to use the Spring/OSGi integration which means you simply declare a bean in your configuration XML importing the service:
    <osgi:reference id=”my-service” interface=”ch.ethz.iks.r_osgi.sample.api.ServiceInterface”/>
The point of all this is that by removing SLP from the end programmer’s interface and reusing the existing OSGi infrastructure for dealing with services in the local registry, we can now make use of this remote OSGi implementation with any OSGi framework because this implementation looks and behaves just like local services which these frameworks already deal with. True, we will have to add something which will register the interest the services the client wishes to import. But this is, again, done reusing the standard OSGi Filter syntax and mechanism – we don’t invent anything here other than a simple, two method service which we use to register and de-register our interest in remote services. Something easy to add in add on bundles which do the registration, or as additional configuration XML in the Spring/OSGi case.
Underneath the hood, you can implement the exact same infrastructure that Jan has in his open source R-OSGi implementation. The difference is that this implementation can now be replaced with something else if needed – the system isn’t tied to a particular implementation or strategy. In my case, of course, I have a different implementation using my own advertisement and registration protocol overlaid over JGroups – of course with the House Harkonnen acquisition of Tangosol, I may be changing that infrastructure to use their protocols. We’ll see. But given the way my channel and protocol implementation is architected, this is actually pretty easy – assuming certain semantics of the underlying group communication protocol.
However, the discussion of my protocol implementation – the analog to Jan’s Channel metaphor – is the subject for another series of posts.

5 thoughts on “Distributing OSGi – Differences From R-OSGi

  1. Trying to get one out. House Harkonnen doesn’t have a good mechanism to get informal things out to the public – we’re just taking our first steps into open source…

  2. Well, I guess you’ve never worked for a corporation before. Just kidding ;)
    Seriously, though, there’s a good case to be made for such and believe me I’m continuously making such a case internally.
    We’re taking the path of working through the OSGi enterprise expert group to do this. From our POV, there’s vanishingly little that needs to be added to OSGi to make this completely transparent. Then, everyone can play in an open field and coexist in harmony. Ponies for everyone!
    From a practical perspective, there’s just way too much proprietary code that is involved in my implementation. And quite frankly, it’s all implementation details anyway. There’s no reason why the Iona guys can’t use their uber ESB to do this and coexist in loving harmony with Jan’s and my implementation.
    My belief is that there’s no practical imperative to have everyone working on one thing. Jan’s stuff is interesting, but the Iona guys are going to push their open source ESB to do much the same thing. Theirs won’t work on a J2ME platform, Jan’s will.
    If we simply do this with the smallest api surface area possible, then we can all interoperate and coexist. And this is, imho, far more preferable to the “one ring to rule them all” mentality of last century.
    I’m never going to live in a world where there’s only open source software. Maybe my daughter will, but until then, there’s really no reason why the two models can’t happily coexist.
    Well, except for the religious thing. :)

  3. Or, to put it another way, why is JBoss implementing their own OSGi implementation? Why not just join Felix and make it better? Or, why build your own version of IOC and not just join with I21 and make Spring better?
    There’s lots of valid reasons that even firms committed to open source have for doing work which seems to replicate something that is already open source.

Leave a Reply