Enterprise Java

OSGi Service Test Helper: ServiceCollector

OSGi services come in handy for the development of systems based on loosely coupled components. But loose coupling can make it difficult to recognize problems related to dangling service references. Thus we usually run integrations tests to ensure the availability of service components at runtime.

With the intention to reduce boilerplate needed for these kind of tests, I have written a simple utility class to obtain particular service implementations. As this might also be useful for other people, I decided to provide a short usage description in this post.
 
 

OSGi Service Relations

OSGi services may depend or use other components to fulfill their purpose. And the web of relations in a running system might get quite complex. This can make it sometimes hard to find out why a certain functionality of an application does not work as expected.

Consider a component that notifies other components using the whiteboard-pattern for example. In case one of the observers fails to register itself, the notification will not happen and dependent capabilities could be broken.

While the reason for this problem might be trivial – e.g. a missing component declaration in the MANIFEST.MF – it could take some time before it is spotted. Hence it seems to be a good idea to prevent these problems by means of integration tests.

Such tests run after the system’s build process, start the bundle-under-test within an appropriate OSGi environment and verify the its proper component contribution at runtime.

For general OSGi testing purposes there is an OSGi Testing Utils project at GitHub. However I was not able to code a simple one-liner using this library to retrieve a particular service implementation from the registry. That is why I have written the utility class described in this post. But as always there is a good chance that I simply was too stupid to find the proper solution…

ServiceCollector

Let us assume we have a component type Service

// Service API declaration
interface Service {
  [...]
}

…and a bundle providing an appropriate implementation class…

// Service implementation provided by another bundle
public class ServiceImpl
  implements Service
{
  [...]
}

… which is registered via declarative services:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component
  xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
  immediate="true" 
  name="Implementation of Service API">
  <implementation class="com.codeaffine.example.core.ServiceImpl"/>
  <service<
    <provide interface="com.codeaffine.example.api.Service"/>
  </service>
</scr:component>

To ensure that the bundle actually succeeds in registering the ServiceImpl instance, a test could retrieve the components of type Service from the registry at runtime and somehow filter our particular component contribution. Which is in principle what the ServiceCollector does.

However I use a down-to-earth approach searching for a particular implementation only. While this might not be conclusive under rare conditions (multiple services of the same implementation type provided by different bundles or the like), it is straight forward for the use cases we encounter in our daily work.

@Test
public void serviceAvailable() {
  List services = collectServices( Service.class, ServiceImpl.class );

  assertThat( services ).hasSize( 1 );
}

As you can see ServiceCollector#collectServices takes the service declaration and its implementation type as parameter to lookup available service instances contributed by a bundle at runtime. It returns a list of components since multiple service instances matching the implementation type might be registered.

Conclusion

So far the ServiceCollector proves itself quite useful in our current project. Before writing any funtionality related tests when creating a new service, the first thing we usually do is to verify the service availability – which is a piece of cake with the little helper.

But note again that the intended usage is a service-contributions-per-bundle integration test scenario. So be careful with e.g. multiple instances of a a particular implementation provided by different bundles. Such situations induce unwanted coupling of the bundle related tests.

The ServiceCollector is part of the com.codeaffine.osgi.test.util feature of the Xiliary P2 repository: http://fappel.github.io/xiliary

In case you want to have a look at the code or file an issue you might also have a look at the Xiliary GitHub project: https://github.com/fappel/xiliary

For everything else feel free to use the commenting section below. So stay tuned – next time I introduce another helper of this package, a JUnit rule useful for test service registrations…

Reference: OSGi Service Test Helper: ServiceCollector from our JCG partner Frank Appel at the Code Affine blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button