OSGi Community Event 2013 (http://www.osgi.org/CommunityEvent2013/Schedule)
ABSTRACT
OSGi is a dynamic module system for Java, supporting the development of highly modular applications. However, many concepts and design choices in the OSGi specifications are language neutral and can, for example, also be applied to native C++ application development. In fact, a vast amount of applications in many different domains (embedded, desktop, server, distributed, etc.) are still written in native languages like C++, for various reasons. In turn, many of these applications are in need of a light-weight modular architecture, fostering a service oriented design to minimize coupling between components and to maximize their re-usability.
The C++ Micro Services project (http://cppmicroservices.org) is a pure C++ implementation of the OSGi service layer, bringing a dynamic and service oriented framework inspired by OSGi to native application developers. Its scope is similar to the PojoSR project, a Java implementation of the OSGi service layer only. By only implementing the OSGi service layer, the complexity and foot-print of such an implementation is drastically reduced and its usage heavily simplified. Additionally, incrementally modifying an existing project to make use of the OSGi service layer can be viewed as an easy migration path to using a full-blown native OSGi implementation later on.
In this talk, the challenges of mapping the Java OSGi service layer API (based on OSGi R4.3 and Java generics) to an intuitive and easy-to-use C++ API are presented. Further, the properties of the native linkers of the major operating systems (Windows, Linux, MacOS) and how they effectively already implement parts of the OSGi module layer are discussed. These concepts will then be illustrated by looking at how a big C++ toolkit related to medical image processing makes use of the C++ Micro Services project and its OSGi-based service layer implementation. Furthermore, the relationship of the C++ Micro Services project to the recently initiated "Native OSGi" efforts, the related OSGi RFP 156, and other native OSGi implementations like Apache Celix will be discussed.
SPEAKER BIO
Sascha Zelzer studied Theoretical Physics in Austria and has been working with Java and C++ for the last ten years. While working on his Ph.D. at the German Cancer Research Center, he is also deeply involved in developing and maintaining a large C++ software stack primarily focused on medical imaging platforms. His current interests include modularized and distributed systems in C++, especially how to leverage the benefits of OSGi technology in a native environment.
2. About Me
●
●
Post-doctoral researcher at the German Cancer Research
Center (DKFZ)
Interested in
–
Medical Image Processing
and 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
3. 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
4. Motivation
●
●
●
●
●
Common C++ software toolkit for medical imaging (MITK)
Researchers develop their algorithms in shared libraries
(modules)
High potential for
reuse of common
services
Modularity and
interoperability are
key points
OSGi provides
established means
to handle modularity
and flexibility
Sascha Zelzer
29/10/13
5. 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!
Sascha Zelzer
29/10/13
6. 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
Sascha Zelzer
29/10/13
7. 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 controlled
via meta-data and
custom class loaders
OSGi takes care of
the correct wiring
Platform independent:
●
Meta-data
●
Embedded resources
Sascha Zelzer
29/10/13
8. 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
Sascha Zelzer
29/10/13
9. 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, …);
Sascha Zelzer
29/10/13
10. 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 support
useful throughout the whole code-base!
Sascha Zelzer
29/10/13
11. 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
Sascha Zelzer
29/10/13
13. 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 a
sophisticated program
handling
●
Dependency resolution
●
Symbol versioning
●
Library initialization
Sascha Zelzer
29/10/13
14. 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 on
link-time dependencies)
Less powerful dependency
versioning
No flat classpath issues as
in Java OSGi Lite!
Sascha Zelzer
29/10/13
15. Life Cycle – Dynamic Linker
The life-cycle is handled by the dynamic
linker too
●
●
Sequential state diagram
Successfully reaches the ACTIVE
state or fails completely
●
No lazy activation
●
No library updates at runtime
●
Activation via static initialization
●
Deactivation via static de-initialization
●
Life-cycle events available
Sascha Zelzer
29/10/13
16. Service Layer - Templates
●
Type-safe templated API
–
–
Any class can be used as a service interface
–
No custom dynamic_cast calls necessary
–
●
No base class for service interfaces or service
implementations required
Pointer magic hidden from the API user
API is almost identical to the OSGi specifications
Sascha Zelzer
29/10/13
17. 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();
Sascha Zelzer
29/10/13
18. 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>();
Sascha Zelzer
29/10/13
19. Example – Auto Loading
Library A
struct IMyService {};
Library B
Library C
struct MyService :
public IMyService {};
IMyService* service =
ctxt->GetService(...);
Loading of Library A triggers auto-loading of associated
libraries.
Sascha Zelzer
29/10/13
20. 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) {…}
Or any “callable” object (functors, lambdas, etc.)
struct MyFunctorialListener {
void operator() (const ServiceEvent event) {…}
};
context->AddServiceListener(MyFunctorialListener());
Sascha Zelzer
29/10/13
21. 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;
}
Sascha Zelzer
29/10/13
22. 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"));
Sascha Zelzer
29/10/13
23. 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);
Sascha Zelzer
29/10/13
25. More
●
Global library specific GetModuleContext() function for
easy context retrieval
●
Hooks for framework log messages
●
Full static linking support
Sascha Zelzer
29/10/13
26. 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)
Sascha Zelzer
29/10/13
27. Use Case - MITK
●
Injection of an Activator class in all shared libraries
●
Conversion of singletons to services
●
Increased cohesion by embedding resources
●
●
Decreased coupling
via interfaces and
services
Auto-loading of
libraries providing
service
implementations
Sascha Zelzer
29/10/13
28. Use Case - MITK
●
●
●
Whiteboard pattern for interaction event listener
Hardware devices (like range cameras and optical tracker)
modelled as services
File reader writer
services with
prototype scope
Sascha Zelzer
29/10/13
29. Native OSGi
●
Several C/C++ implementations have been created
–
–
CTK Plugin Framework (C++, Qt based)
–
Apache Celix (C)
–
Nostrum (C++, POSIX)
–
SOF (C++, CORBA remoting)
–
●
CppMicroServices (C++)
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
Sascha Zelzer
29/10/13
31. Summary
●
OSGi Lite is well accepted by C++ developers
●
Less complexity due to the missing module layer
●
●
●
●
Less flexibility and
dynamism
C++ OSGi API
can be very close
to the Java version
Used in and
interest from
various domains
API should converge
with Native OSGi
efforts in the future
Sascha Zelzer
29/10/13
32. 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
Sascha Zelzer
29/10/13