How to create blueprints for your OSGi building blocks

How to create blueprints for your OSGi building blocks

With OSGi we are able to implement building blocks for modular applications. Dependency injection frameworks support us in writing flexible, testable and clean code. The “Blueprint Container Specification” defines a dependency injection framework to build applications that run in an OSGi framework. The specification was added in version 4.2 to the OSGi compendium Specification[1]. This specification is derived from the Spring Dynamic Modules project[2] which is an extension to the Spring dependency injection framework where you can take advantage of the services offered by the OSGi environment.

Essentially, a Blueprint documents an architecture or an engineering design. Sounds promising. In addition, with the releases of Apache Aries[3] and Gemini Blueprint[4], the reference implementation for the Blueprint Container (chapter 121 of the OSGi 4.2 Compendium Specification), there are two open source implementations available.

Blueprint components are defined inside Blueprint XML resources. The location of these resource files can be specified with the Bundle-Blueprint manifest header. If the header is absent the default value: OSGI-INF/blueprint/*.xml will be used.

The sample below shows the body of a Blueprint definition:



    


Let’s test drive a Gemini Blueprint.

We’re going to develop two OSGi bundles. One contains an embedded database and exports a datasource as an OSGi service. The second bundle connects to the datasource provided and extends the built-in shell with basic functionality to execute simple SQL commands.

The following Blueprint Definitions describe the blueprint of the first of our bundles, a DataSourceProxy wrapping a simple DataSource:


  
  


  


The dependency graph facilitates visual inspection of the blueprint.

Blueprint of bundle exporting javax.sql.DataSource

We grant access to our lazy proxy to other OSGi bundles as as an OSGi service via the standard javax.sql.DataSource interface:



Hidden in the logs you will find an entry “Publishing service under classes [{javax.sql.DataSource}]” telling you that the definition has been successfully interpreted by the Blueprint Container.

INFO  region-dm-11                 o.e.g.b.e.i.d.startup.DependencyWaiterApplicationContextExecutor  No outstanding OSGi service dependencies, completing initialization for OsgiBundleXmlApplicationContext(bundle=com.eclipsesource.examples.virgo.blueprint, config=bundleentry://156.fwk1968988860/OSGI-INF/blueprint/beans.xml) 
INFO  region-dm-11                 o.s.beans.factory.support.DefaultListableBeanFactory              Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6dbe7935: defining beans [driver,datasource,.org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean#0,blueprintBundle,blueprintBundleContext,blueprintContainer,blueprintConverter]; root of factory hierarchy 
INFO  region-dm-11                 o.e.g.blueprint.service.exporter.support.OsgiServiceFactoryBean   Publishing service under classes [{javax.sql.DataSource}]

Consuming an OSGi service is just as easy. Instead of defining a service with a reference, a reference is defined with an Id:



The following definition shows how to inject the DataSource into the JdbcTemplate and the JdbcTemplate into the SqlCommandProvider,


  


  


which results in this blueprint for our second bundle.

Blueprint of the bundle importing javax.sql.DataSource

Blueprint of the bundle importing javax.sql.DataSource

In addition to consuming an OSGi service, the second bundle contributes to the Apache Felix Gogo[5] Shell. This requires defining additional service properties as shown in the snippet below:


  
    
      sql
    
    
      
        execute
        queryForInt
      
    
  


Putting it all together allows us to access the database via the OSGi console:

osgi> sql:execute CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))
osgi> sql:queryForInt SELECT COUNT(*) FROM TEST
0
osgi> sql:execute INSERT INTO TEST VALUES(1, \'Hello\')                   
osgi> sql:queryForInt SELECT COUNT(*) FROM TEST        
1


Let’s document the architecture of OSGi applications!

The example code has been written using Virgo Jetty Server 3.5.0.RELEASE with Gemini Blueprint 1.0.1.M01 and is available on GitHUB.

[1] OSGi Alliance Specifications – https://www.osgi.org/Specifications/HomePage
[2] Spring Dynamic Modules – https://www.springsource.org/osgi/
[3] Apache Aries – https://aries.apache.org/modules/blueprint.html
[4] Gemini Blueprint – https://www.eclipse.org/gemini/blueprint/
[5] Apache Felix Gogo – https://felix.apache.org/site/apache-felix-gogo.html