Today at EclipseCon Europe, Sascha Zelzer presented a native OSGi services layer called C++ MicroServices. This aims to provide a service layer similar to the PojoSR project which enables applications to be built with inter-connecting services. Neither C++ Micro Services nor PojoSR have full OSGi's ability to swap out live code; instead, they all work in the same memory process/ClassLoader.
Given that one of OSGi's key strengths is its multiple ClassLoader model, which allows bundles (modules) to be dynamically stopped and restarted, is there scope for an OSGi Lite? Well, the creators of both PojoSR and native approaches (including Apache Celix, another OSGi C runtime) think there is benefit in the μservices programming model, as it allows applications to be built in terms of co-operating services. This allows a general dependency injection mechanism, where a global catalogue of services can hold a list of valid services, and components requiring those services can query the service registry to find an appropriate implementation.
Although modules don't exist in the "OSGi Lite" flavours, it is still possible to dynamically stop (or remove) services from the registry. This still allows for some level of dynamism, even if it doesn't provide for hot code replace on the fly. On the other hand, some Java programs and libraries suffer in anything other than a flat classpath, so the "OSGi Lite" pattern allows for a transitional period between a typical spaghetti model whilst refactoring towards services.
The C++ μservices project released its 1.0.0 version earlier this year, available from GitHub or the project download library, along with a detailed tutorial of how to use it. The library is provided under the us::
namespace (which is an abbreviation for μservices), and provides a us::ModuleContext
(akin to OSGi's BundleContext
) and provides us::GetServiceReference
and us::GetService
. There is also a us::ModuleActivator
base class with Load
and UnLoad
methods which can be used to initialise the state of the module when it comes up or goes down, along with us::ServiceTracker
that can be used to track services being installed or being removed.
InfoQ caught up with Zelzer and started by asking what started the C++ Micro Services project:
Zelzer: I work on a large C++ code-base for medical imaging, which is used by many students to develop their algorithms. To manage such a code-base and their developers (who are usually not software engineers by training) modularity and re-usability is highly important. This is where OSGi excels in. However, our previous attempt to introduce a full C++ OSGi - like framework was hindered by several factors: Two important factors were that the existing code-base was complicated to adapt to a pure OSGi architecture and additionally, our C++ developers were conservative with respect to introducing yet another complex framework. Anyway, layer which was of most interest to us was the service layer - we did not actually have a use case for hot-swapping code at runtime or the flexible dependency resolution mechanisms in the module layer. So I started to create the CppMicroServices project.
InfoQ: How do you deal with services coming and going; does the module still stay loaded?
Zelzer: Usually, modules are not unloaded (although a program could achieve that). Modules are loaded by the dynamic linker during start-up to resolve the compile-time link dependencies. Custom programs may choose to dynamically load and unload modules at runtime (unloading is rarely done, however). Disappearing services need to be handled by service listeners. If a module was unloaded and another module keeps using the service object will lead to program failures.
InfoQ: Can modules be loaded and unloaded dynamically, just with the same code version loaded?
Zelzer: Yes, but this is up to the program. It can choose to dynamically load a shared library at runtime using the provided OS function (
dlopen()
,LoadLibrary()
, etc.).
InfoQ: How does loading bundles work - is there a standard format that can be used to represent a bundle, like a JAR?
Zelzer: The nice thing with CppMicroServices is, that it leaves these things completely to the OS. So on Linux, the bundle format is "ELF Shared Objects" (static is possible too) and on Windows for example the format is "PE" (Portable Executable, which are .dll or. exe files). Loading is done by the dynamic linker of the OS.
InfoQ: What platforms does CPP Micro Services support?
Zelzer: It is written in standard C++ 98 and should compile on all platforms with a compliant C++ compiler. It is tested on Linux, Windows, and MacOS using different compiler versions.
InfoQ: How does this relate to the OSGi Native proposal and Apache Celix?
Zelzer: I see the CppMicroServices project as a field test for a native C++ API of the service layer. The gained experience will help the specification process for a Native OSGi API, where I am participating.
InfoQ: Where and how is this being used at the moment?
Zelzer: It is extensively used in the Medical Imaging Interaction Toolkit (MITK) and implicitly in all projects using it. A commercial example is Mint Medical, a company providing C++ solutions in the medical imaging domain. People from avionics, embedded systems and safety critical software projects seem also to be interested.
There's a lot of interest in the native OSGi space, which is why OSGi has an Request For Proposal (RFP)156 to discuss the requirements behind standardising the OSGi APIs in a native library. Would you be interested in using OSGi APIs in native code?