Going Native with theOSGi Service Layer
Sascha Zelzer
About Me● Post-doctoral researcher at the German Cancer Research
Center (DKFZ)
● Interested in
– Medical Image Processingand Analysis
– Modularity and interoperability
– Large scale C++ systems
– OSGi technology
● Several years of Java and C++ programming experience
● OSGi Invited Researcher
● Participant in the Native OSGi specification effort
Outline● Motivation for native OSGi – like frameworks
● Challenges
– Conceptual
– Language● History and Requirements
● The C++ Micro Services Project
– Architecture
– Features● Use Cases
● Excursion: Native OSGi
● Roadmap & Summary
29/10/13Sascha Zelzer
Motivation● Common C++ software toolkit for medical imaging (MITK)
● Researchers develop their algorithms in shared libraries (modules)
● High potential forreuse of commonservices
● Modularity andinteroperability arekey points
● OSGi providesestablished meansto handle modularityand flexibility
29/10/13Sascha Zelzer
Motivation
However
● Medical image processing is traditionally done in C++ (Java and Python are gaining popularity)
● Large existing code bases written in C++
● Full blown OSGi framework (even if available for C++) considered too intrusive and heavy-weight
● C/C++ developers are very conservative
● Lack of a migration path towards full OSGi support
Still, there is a need for strong modularity!
29/10/13Sascha Zelzer
Challenges
OSGi layers are coupled to Java specifics
● Module Layer
– Class loading architecture (visibility of classes)
– Dependency resolution (package wiring)
● Life-cycle Layer
– Lazy activation
– Updates
● Service Layer
– Nothing crucial
● Security Layer
– Based on the Java 2 security architecture
29/10/13Sascha Zelzer
Conceptual Challenge – Module Layer● Bundles are represented by JAR files with meta-data
● Code is organized in packages
● Bundles export and import Java packages
● Visibility is controlledvia meta-data andcustom class loaders
● OSGi takes care ofthe correct wiring
Platform independent:
● Meta-data
● Embedded resources
29/10/13Sascha Zelzer
Conceptual Challenge – Life Cycle● Elaborate bundle life-cycle and dependency resolution
● Lazy activation triggered by class loading
● Bundle updates at runtime
Platform independent:
● Activation
● Life-cycle listeners
29/10/13Sascha Zelzer
Language Challenges● Garbage collector VS Destructors
● Generics VS Templates
● Thread-safety (without third-party libraries)
● Common base class (Object in Java)
ServiceRegistration<?> BundleContext.registerService(java.lang.String clazz, java.lang.Object service, …);
ServiceRegistration<?> BundleContext::registerService(const std::string& clazz, Object* service, …);
29/10/13Sascha Zelzer
Internal History● The CTK Plugin Framework (started 2007/2008)
– Full C++ OSGi implementation (except Security Layer)
– Qt dependency
● C++ developers like shared libraries, but frameworks not so much
● Full dynamism was rarely needed
● Service registry and bundle activator solved a couple of issues (e.g. dependencies between singletons)
Service registry and basic module layer supportuseful throughout the whole code-base!
29/10/13Sascha Zelzer
Requirements● No third-party dependencies (only the STL)
● Cross-platform support (Linux, Windows, MacOS)
● C++98 compliance (use C++11 features if available)
● Type-safe API (no void* or client dynamic_cast calls)
● Full Service Layer support
● Module Layer support without its dynamics
29/10/13Sascha Zelzer
C++ Micro Services
● Developed and © German Cancer Research Center
● Is a “OSGi Lite” implementation in C++
● Apache License 2.0
● GitHub hosted
29/10/13Sascha Zelzer
C++ Micro Services - Architecture
The CppMicroServices library uses standard shared libraries
● Shared objects (.so) in ELF format on Linux
● Dynamic Link Libraries (.dll) in PE format on Windows
● Dynamic Libraries (.dylib) in MachO format on MacOS
The dynamic linker is asophisticated programhandling
● Dependency resolution
● Symbol versioning
● Library initialization
29/10/13Sascha Zelzer
Module Layer – Dynamic Linker
The dynamic linker of the OS handles
● Symbol visibility
– GCC / Clang use __attribute__((visibility (“default”))
– MSVC uses__declspec(dllexport)
● Dependency resolution
● Symbol lookup (based onlink-time dependencies)
● Less powerful dependencyversioning
● No flat classpath issues asin Java OSGi Lite!
29/10/13Sascha Zelzer
Life Cycle – Dynamic Linker
The life-cycle is handled by the dynamiclinker too
● Sequential state diagram
● Successfully reaches the ACTIVEstate or fails completely
● No lazy activation
● No library updates at runtime
● Activation via static initialization
● Deactivation via static de-initialization
● Life-cycle events available
29/10/13Sascha Zelzer
Service Layer - Templates● Type-safe templated API
– No base class for service interfaces or service implementations required
– Any class can be used as a service interface
– No custom dynamic_cast calls necessary
– Pointer magic hidden from the API user
● API is almost identical to the OSGi specifications
29/10/13Sascha Zelzer
Example – Type Safety
ServiceRegistration and ServiceReference classes are templates:
struct IMyService { virtual ~IMyService(); };US_DECLARE_SERVICE_INTERFACE(IMyService,"org.me.IMyService")
struct MyService : public IMyService {};MyService myService;ServiceRegistration<IMyService> reg =
context->RegisterService<IMyService>(&myService);
ServiceReference<IMyService> ref = context->GetServiceReference<IMyService>();
IMyService* service = context->GetService(ref);context->UngetService(ref);
reg.Unregister();
29/10/13Sascha Zelzer
Example – Object Lifetime● Implicitly shared objects
● Almost no raw pointers for library objects in the API
ServiceRegistration<IMyService> reg = context->RegisterService<IMyService>(&myService);
ServiceReference<IMyService> ref =context->GetServiceReference<IMyService>();
29/10/13Sascha Zelzer
Example – Auto Loading
Loading of Library A triggers auto-loading of associated libraries.
Library A
struct IMyService {};
Library C
IMyService* service =ctxt->GetService(...);
Library B
struct MyService : public IMyService {};
29/10/13Sascha Zelzer
Example – Listeners● Listeners for library (bundle) events
● Listeners for service events
Use a member function pointer
context->AddServiceListener(this, &MyClass::ServiceChanged);
void ServiceChanged(const ServiceEvent event) {…}
struct MyFunctorialListener { void operator() (const ServiceEvent event) {…}};context->AddServiceListener(MyFunctorialListener());
Or any “callable” object (functors, lambdas, etc.)
29/10/13Sascha Zelzer
Example - Resources● The generic resources system allows
● Embedding arbitrary data
● Compression if a specific threshold is reached
● Modelling an embedded resources file system
● Access via STL compatible streams
ModuleResource resource = module->GetResource("conf.props");ModuleResourceStream resourceStream(resource);
std::string line;while (std::getline(resourceStream, line)){ std::cout << line << std::endl;}
29/10/13Sascha Zelzer
Example – JSON Meta-data● Library meta-data can be added via a JSON file
● Embedded as a resource and parsed at load-time
● Arbitrary key-value pairs, accessible via the module API
{"module.version" : "1.0.2","module.description" : "This module provides a service","authors" : [ "John Doe", "Douglas Reynolds", "Daniel Kim" ],"rating" : 5}
Module* module = context->GetModule();int r = ref_any_cast<int>(module->GetProperty("rating"));
29/10/13Sascha Zelzer
Example – RFC 195 Service Scopes● In OSGi, services are singletons (sharing state) or bundle
specific (ServiceFactory)
● RFC 195 formalizes service scopes
– Singleton and Bundle Scope: As usual
– Prototype Scope (new): Create service instances based on a prototype on demand
class MyFactory : public PrototypeServiceFactory {…};context->RegisterService<IMyService>(myFactory);
ServiceReference<IMyService> ref =context->GetServiceReference<IMyService>();
ServiceObjects<IMyService> objects =context->GetServiceObjects(ref);
IMyService* myService = objects.GetService();objects.UngetService(myService);
29/10/13Sascha Zelzer
Example – LDAP Filter DSL
Creating LDAP filter strings in Java is error-prone.
Filter example: “(&(name=Ben)(!(count=1)))”
context.createFilter("(&(name=Ben)(!(count=1))");
LDAPFilter filter( LDAPProp("name") == "Ben" && LDAPProp("count") != 1);
29/10/13Sascha Zelzer
More
● Global library specific GetModuleContext() function for easy context retrieval
● Hooks for framework log messages
● Full static linking support
29/10/13Sascha Zelzer
Use Cases
DS4Cpp
● A declarative services framework in C++ based on CppMicroServices
● Contributed by Global Vision Systems
● Introduces similar dependency-injection patterns across their Java and C++ code-base
Interest from various technical companies
● Embedded systems
● Avionics and sensoring
● Military sub-contractors working on mission-critical software
● Medical Imaging (e.g. Mint Medical)
29/10/13Sascha Zelzer
Use Case - MITK● Injection of an Activator class in all shared libraries
● Conversion of singletons to services
● Increased cohesion by embedding resources
● Decreased couplingvia interfaces andservices
● Auto-loading oflibraries providingserviceimplementations
29/10/13Sascha Zelzer
Use Case - MITK● Whiteboard pattern for interaction event listener
● Hardware devices (like range cameras and optical tracker) modelled as services
● File reader writerservices withprototype scope
29/10/13Sascha Zelzer
Native OSGi● Several C/C++ implementations have been created
– CppMicroServices (C++)
– CTK Plugin Framework (C++, Qt based)
– Apache Celix (C)
– Nostrum (C++, POSIX)
– SOF (C++, CORBA remoting)
– Poco OSP (commercial)
● Developers joined forces and created RFP 156 Native OSGi for standardization of a native C/C++ API
– RFP 156 will be voted on in November
– RFC workis about to be started
– CppMicroServices is field-testing a native service-layer API
29/10/13Sascha Zelzer
Roadmap
Release 2.0
● Service hooks
Ecosystem
● Configuration Admin
● Device Access
● Event Admin
● Remote Services
Native OSGi
● Specify the Service Layer API
● Work on a native Module Layer
29/10/13Sascha Zelzer
Summary● OSGi Lite is well accepted by C++ developers
● Less complexity due to the missing module layer
● Less flexibility anddynamism
● C++ OSGi APIcan be very closeto the Java version
● Used in andinterest fromvarious domains
● API should convergewith Native OSGiefforts in the future
29/10/13Sascha Zelzer
URLs
C++ Micro Service
● Homepage http://cppmicroservices.org
● GitHub https://github.com/saschazelzer/CppMicroServices
● Blog http://blog.cppmicroservices.org
RFP 156 – Native OSGi
● Bug https://www.osgi.org/bugzilla/show_bug.cgi?id=165
● Document https://github.com/osgi/design/tree/master/rfps
29/10/13Sascha Zelzer
Thank You!
Questions?