Taverna 3 runs in an OSGi framework. The main changes for the Taverna plugin developer are :
- All modules (or Maven artifacts) must be OSGi bundles
- All module dependencies must be OSGi bundles (or the dependency code is added to the module)
- All Taverna dependencies must be API (not implementation) modules.
- Services are exported as OSGi services instead of using SPIs
- Services are used by referencing OSGi services and injecting the service using Spring
What is an OSGi bundle?
An OSGi bundle is a jar file with some extra manifest headers. As a minimum an OSGi bundle must have the Bundle-SymbolicName manifest header.
A typical bundle will usually also have the following headers :
Converting Taverna to run in an OSGi framework
Creating OSGi Bundles
The first step is to create OSGi bundles for the Taverna modules. As Taverna is built with Maven the Bundle Plugin for Maven is used to create the manifest entries for the bundle. This is usually just a case of adding the plugin to the module's pom.xml file.
and changing the packaging type to bundle
The Bundle Plugin will add the required manifest headers to the jar file and calculate the packages that the bundle imports and exports.
All the dependencies of Taverna's modules also have to be OSGi bundles. First check if the dependency is an OSGi bundle - have a look in the manifest to see if the Bundle-SymbolicName header is present. If the dependency is not a bundle it is worth checking if a later version is.
The SpringSource Bundle Repository contains OSGi bundle versions of many common libraries. Modules in the SpringSource Bundle Repository have different artifactId's to distinguish them from the non OSGi versions, so a dependency declared as
If an OSGi bundle version of a dependency is not available then it is possible to embed the dependency in the module by using the Private-Package or Embed-Dependency instructions of the Bundle Maven plugin. For example, the RShell Activity has a dependency on rengine and embeds the required packages by adding the Private-Package instruction.
Embedded dependencies should have a scope of provided so that the non-OSGi dependency is not added to the build.
If the dependency is required by consumers of a module (perhaps because it used by an API that the module exposes) then the Export-Package can be used. This will embed the dependency but also make it available for other modules by adding the package to the bundles exported packages.
See the Bundle Maven plugin documentation for more information
Creating OSGi services
Taverna 2 services are defined by SPI interfaces. Taverna 3 uses OSGi services so all the SPI definitions (specified in the META-INF/services resource directory) have to be converted to OSGi services.
For example, in Taverna 2 the implementation of the Edits interface in the workflowmodel module is specified in the file META-INF/services/net.sf.taverna.t2.workflowmodel.Edits which the file contains the name of the implementation class
In Taverna 3 the Edits interface is exported as an OSGi service. The majority of the Taverna 2 SPIs are the same interfaces that need to be registered as services in the OSGi framework. The OSGi services are created and registered using Spring Dynamic Modules for OSGi. So in the above example, the Edits service would be defined in two Spring context files. META-INF/spring/workflowmodel-impl-context.xml creates the implementation bean.
and META-INF/spring/workflowmodel-impl-context-osgi.xml registers the bean as a service with the OSGi framework
Using OSGi Services
Spring DM is also used for making services available in the OSGi framework available as bean in the spring context. The LocalExecutionService defined in the Taverna Platform requires the Edits service that was registered in the example above. To use the OSGi service two Spring context files are added to the execution-local module. META-INF/spring/execution-local-context-osgi.xml specifies a references to the Edits service.
Specifying Package Providers
It is good practice to specify providers of a package in OSGi so that implementation bundles have the correct version range for the API packages they provide.
For example, the Taverna App Configuration Implementation bundle provides an implementation of the uk.org.taverna.configuration.app package and therefore the import range for the package should only include micro version changes.
This is achieved by marking the package import property provide as true in the maven-bundle-plugin configuration.