Jekyll2023-03-02T06:16:54+00:00http://www.liquid-reality.de/feed.xmlLiquid RealityThis blog is about architecture and modularityPopular patterns revisited on OSGi2018-11-21T00:00:00+00:002018-11-21T00:00:00+00:00http://www.liquid-reality.de/2018/11/21/talk-eclipsecon<p>We will look at common cloud and design patterns and see how the special properties of the OSGi environment allow us to rethink these patterns. The talk shows some well-known patterns like the service registry and the whiteboard but also some unique patterns like out of band circuit breaker or graceful degregation.</p>
<p>For OSGi beginners, the well established OSGi patterns will help getting started the right way. Experienced OSGi developers will find some new patterns to think about. Cloud or enterprise developers will get a new approach to some patterns they are used to which hopefully inspires them to take another look at the current state of OSGi.</p>
<ul>
<li><a href="https://www.slideshare.net/ChristianSchneider3/popular-patterns-revisited-on-osgi">Slides</a></li>
<li><a href="https://youtu.be/PS2Ll6q1G-U">Video of the talk</a></li>
</ul>We will look at common cloud and design patterns and see how the special properties of the OSGi environment allow us to rethink these patterns. The talk shows some well-known patterns like the service registry and the whiteboard but also some unique patterns like out of band circuit breaker or graceful degregation.How to set up proper logging in OSGi using logback backend2018-08-07T00:00:00+00:002018-08-07T00:00:00+00:00http://www.liquid-reality.de/2018/08/07/logging-osgi<p>Logging in OSGi seemed to be an arcane thing for quite some time. On the logback website there is still <a href="http://ekkes-corner.blogspot.com/2008/10/index-blogseries-logging-in-osgi.html">this explanation by Ekke</a> which was surely good 2008 but in 2018 people do not accept creating their own logging bridges, adding config using fragments and tweaking start levels.</p>
<p>Luckily this all improved quite a lot. Apache Karaf uses pax-logging and there is now also the <a href="http://felix.apache.org/documentation/subprojects/apache-felix-logback.html">felix logback support bundle</a>. In this article I will focus on the later as it is simple to setup and has some nice features.</p>
<h2 id="example-code">Example code</h2>
<p>I added the felix logback support to my <a href="https://github.com/cschneider/osgi-ds-hello-world">OSGi DS hello world example</a> because
logging is a core aspect in any professional development.</p>
<p>See the Readme in the example for instruction how to buil and run it.</p>
<h2 id="logging-frontends">Logging frontends</h2>
<p>Logback + Felix logback supports a wide range of logging frontents (slf4j, jul, log4j, logback, commons logging, OSGi Log service).
For your own code I recommend to use the slf4j API. It is very slim in dependencies and provides a lot of features.</p>
<p>At compile time you only need the slf4j API.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
</code></pre></div></div>
<p>You instantiate slf4j exactly like outside OSGi. So it can also be used for
hybrid code that can run inside and outside of OSGi.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class MyClass {
Logger log = LoggerFactory.getLogger(this.getClass());
}
</code></pre></div></div>
<h3 id="deployment">Deployment</h3>
<p>At runtime you install the bundles below. These also include the Felix log
service which is used by some OSGi reference implementations.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.log</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.logback</artifactId>
<version>1.0.0</version>
</dependency>
</code></pre></div></div>
<p>The simplest way to install these is to use the bndtools bndrun packaging like in the example above.</p>
<h3 id="configuration">Configuration</h3>
<p>The logback configuration can be provided by a framework property. Logback will
automatically watch the file for changes and apply new settings.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-runproperties: logback.configurationFile=file:${.}/logback.xml
</code></pre></div></div>
<p>You can use plain logback configs but felix logback also provides some special settings to configure OSGi specific logs like bundle events. See the <a href="http://felix.apache.org/documentation/subprojects/apache-felix-logback.html">examples in the felix logback docs</a>.</p>
<p>An example config can be found <a href="https://github.com/cschneider/osgi-ds-hello-world/blob/master/starter/logback.xml">here</a>.</p>Logging in OSGi seemed to be an arcane thing for quite some time. On the logback website there is still this explanation by Ekke which was surely good 2008 but in 2018 people do not accept creating their own logging bridges, adding config using fragments and tweaking start levels.OSGi testing with pax exam2018-04-16T00:00:00+00:002018-04-16T00:00:00+00:00http://www.liquid-reality.de/2018/04/16/osgi-testing<p>Use some hints for OSGi testing with pax exam that can make your tests much faster and more powerful.
See <a href="https://github.com/cschneider/osgi-testing-example">osgi-testing-example</a> at github.</p>Use some hints for OSGi testing with pax exam that can make your tests much faster and more powerful. See osgi-testing-example at github.Some hints to boost your productivity with declarative services2016-09-26T00:00:00+00:002016-09-26T00:00:00+00:00http://www.liquid-reality.de/2016/09/26/hints-ds<p>The declarative services (DS) spec has some hidden gems that really help to make the most out of your application.</p>
<h2 id="use-the-ds-spec-annotations-to-define-your-component">Use the DS spec annotations to define your component</h2>
<p>Some older articles about DS define the components using xml. While this is still possible it is much simpler to use annotations for this purpose.
There are 3 sets of annotations available bnd style, felix style and OSGi DS spec style. While the first two set can still be seen in the wild you
should only use the OSGi spec annotations for new code as the other sets are deprecated.</p>
<p>At runtime DS only works with the xml so make sure your build creates xml descriptors from your annotated components. Recent versions of bnd, maven-bundle-plugin
and bnd-maven-plugin all handle the spec DS annoations by default. So no additional settings are required.</p>
<h2 id="activate-component-by-configuration">Activate component by configuration</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Component(
name = "mycomponent",
immediate = true,
configurationPolicy = ConfigurationPolicy.REQUIRE,
) ˚ In some cases it makes sense to always install a bundle but to be able to activate and deactivate a service it provides. By using configurationPolicy = REQUIRE the component is only activated if the configuration pid "myComponent" exists. Do not forget immediate=true as by defaullt the component would be lazy and thus not activate unless someone requires it.
</code></pre></div></div>
<h2 id="override-service-properties-using-config">Override service properties using config</h2>
<p>By default a DS component is published as a service with all properties that are set in the @Component annotation.
Every component is also configurable using a config pid that matches the component name. It is less well known that the
configuration properties also show on the service properties and override the settings in the annotation.</p>
<p>One use case for this is to publish a componeent using Remote Service Admin that was not marked by the developer.
Another use case is to override the topic a EventAdmin EventHandler listens on. See https://github.com/apache/karaf-decanter/blob/master/appender/kafka/src/main/java/org/apache/karaf/decanter/appender/kafka/KafkaAppender.java#L43</p>
<h2 id="overide-injected-services-of-a-component-using-config">Overide injected services of a component using config</h2>
<p>If a component is injected with a service using @Reference then the service is normally statically filtered using the target property of the annotation in the
form of an ldap filter.
This filter can be overridden using a config property target.refname where refname is the name of the property the service is injected into.</p>
<h2 id="create-multiple-instances-of-a-component-using-config">Create multiple instances of a component using config</h2>
<p>Another not so well known fact is that a DS component not only reacts on a single configuation pid but also on factory configs. If the pid of your component config is “myconfig” then in apache karaf you can create configs named myconfig-1.cfg and myconfig-2.cfg and DS will create two instances of your component.</p>
<h2 id="typesafe-configuration-and-metatype-information">Typesafe configuration and Metatype information</h2>
<p>Starting with DS 1.3 you can define type safe configs and also have them available as meta type information for config UIs.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@ObjectClassDefinition(name = "Server Configuration")
@interface ServerConfig {
String host() default "0.0.0.0";
int port() default 8080;
boolean enableSSL() default false;
}
@Component
@Designate(ocd = ServerConfig.class)
public class ServerComponent {
@Activate
public void activate(ServerConfig cfg) {
ServerSocket sock = new ServerSocket();
sock.bind(new InetSocketAddress(cfg.host(), cfg.port()));
// ...
}
}
</code></pre></div></div>
<p>See <a href="http://njbartlett.name/2015/08/17/osgir6-declarative-services.html">Neil Bartletts post</a> for the details.</p>
<h2 id="internal-wiring">Internal wiring</h2>
<p>In DS every component publishes a service. So compared to blueprint DS seems to miss a feature for creating internal components / beans that are only visible inside the bundle.
This can be achieved by putting a component into a private package and setting the service property to the class of the component. The component is still exported as a service
but the service will not be visible to the outside as the package is private. Still the service can be injected into other classes of the bundle using the component class.</p>
<h2 id="field-injection-and-constructor-injection">Field injection and constructor injection</h2>
<p>Since DS 1.3 (part of the OSGi 6 specs) you can also inject services directly into a field like:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Reference
EventAdmin eventAdmin;
</code></pre></div></div>
<p>You can even inject into a private field but remember this will make it very difficult to write a unit test for your component. I personally always use package visibility for
fields I inject stuff into. I then put the unit test into the same package and can set the field inside the test without doing any special magic.</p>
<p>Constructor injection is is part of DS 1.4 (OSGi spec 7).</p>
<h2 id="injecting-multiple-matching-services-into-a-list">Injecting multiple matching services into a List<MyService></MyService></h2>
<p>Since DS 1.3 it is possible to inject all services matching the interface and an optional filter into a List</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Reference
List<MyService> myservices;
</code></pre></div></div>
<p>By default DS assume the static policy. This means that whenever the list of services changes the component is deactivated and activated again. While this is the safest way it might be too slow for your use case.
So injecting services dynamically can make sense.</p>
<h2 id="injecting-services-dynamically">Injecting services dynamically</h2>
<p>By default DS will restart your component on reference changes. If this is too slow in your case you can allow DS to dynamically change the injected service(s).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Reference
volatile MyService myService;
</code></pre></div></div>The declarative services (DS) spec has some hidden gems that really help to make the most out of your application.