OSGi specifies not only the low-level concepts of the framework but also defines high-level APIs and services available for the use in OSGi environment. There are many of them, I’d mention these:
- Log service: a general purpose message logger, allowing to integrate with 3rd party logger frameworks.
- Configuration Admin service: provides possibility to dynamically manage configuration of bundles.
- Event Admin service: inter-bundle communication mechanism based on publish/subscribe model.
- Blueprint Container: dependency injection framework for construction of OSGi application in the way you construct your Spring application describing beans and dependencies in .xml file.
- Web Applications specification: provides means for creating Web Applications (common JavaEE ones but using OSGi lifecycle and classes/resources loading mechanisms ) and deploying JavaEE WAR files into the OSGi container.
There are two widely known implementations of the OSGi framework: Apache Felix and Eclipse Equinox. Can’t compare them as I have experience with Apache Felix only, but in theory they should be interchangeable as they implement the same specification. Typically you have 2 options of using the OSGi framework:
Embedded mode, when you have a common Java application with, say, Apache Felix embedded into it. This is suitable when you need “dynamism” just in some part of your system.
Standalone mode, when you build your software on the top of OSGi framework. Here we talk about this one.
Fortunately same as in Java EE world we have Application Servers (GlassFish or JBoss, for example), which not only implement specifications from the Java EE Profile, but also give us convenient way of managing our application environment, in OSGi world we have Apache Karaf – OSGi applications container built on top of Apache Felix.
Apache Karaf provides additional features on top of the framework. Below are the ones I’ve used more or less intensively (in fact there are more):
- Management Console: a Unix-like console allowing you to fully manage the container via built-in commands. Supports remote access
- Web console: a Web-based management tool
- “Features” concept: mechanism for describing and managing complex applications/functionalities. Feature is a named description of OSGi application in XML. Karaf provides many features which can be installed, developers can also create their own features
- Maven support: Karaf Maven plug-in can be used to create your features and assemble a customised Karaf container
- Hot deployment: Karaf automatically deploys artefacts dropped into specific folder. These can be jar files, features xml descriptors and something else I’ve never tried
- Dynamic Configuration: Karaf applies changes in configuration files of the bundles on the fly
- JMX Management: management indicators and operations are supported via JMX
- Provisioning: Karaf can install bundles from various sources – file, http, maven etc.
Apache Karaf comes with a minimal set of bundles and features installed. When creating an OSGi application you typically download the needed container version, define your requirements for 3rd party frameworks and libraries, install them into container, then implement and install your own bundles, wiring all this together, for example, with Blueprint dependency injection technology. Karaf provides many “standard enterprise” features which can be installed with one command in Karaf console from the Maven repository (such as JPA, JNI, JMS, JDBC support etc.) so that you don’t need to install bundles one by one. Some frameworks also provide features for Karaf, for example, Apache CXF. For those who don’t you explicitly mention needed bundles in the xml feature descriptor of your application.
Most frameworks ship their jars as OSGi bundles. There can be situations when some .jar was not initially created as an OSGi bundle, so it cannot be managed by OSGi framework. For such cases Karaf also has a solution – it provides the “wrap” protocol, which “OSGifies” the given .jar on the fly.
Of course, sometimes there can be problems with frameworks/libraries in OSGi environment. The reason is usually the same – somewhere in the code developers stepped away from the modular principles and let the code “expect” that it has everything it can ever need in the classpath. In OSGi it doesn’t. From my experience this is usually solved with a little playing with class loaders: either setting the proper context classloader before the framework API call or passing the needed classloader to the framework explicitly.
Thanks for your time and thirst for knowledge:) In the last article of the series I’ll show the real OSGi architecture of IoT Events Engine software (http://ioteengine.com/blog/2017/07/14/iotee-framework-introduction/) as an alternative to a hypothetical Microservices-based one discussed in the first article of the series: http://ioteengine.com/blog/2017/07/28/osgi-intro/