oheger / sbt-spifly   0.4.0

GitHub

SBT plugin that invokes the Apache Aries SPI Fly static weaving tool

Scala versions: 2.12 2.10
sbt plugins: 1.0 0.13

sbt-spifly

Plugin for sbt to invoke the static weaving tool of Apache Aries SPI Fly.

SPI Fly makes the Java service loader mechanism work in an OSGi environment. To achieve this, it supports both a dynamic and a static approach. The former uses byte code manipulation at runtime when a client bundle is installed in an OSGi container; it requires no special manipulations on client OSGi bundles.

The static approach in contrast is applied at compile time as an additional processing step; it requires the execution of a static weaving tool on a client bundle. This plugin simplifies this step by providing a corresponding task that can be executed directly in the sbt build.

As SPI Fly is about OSGi, you will typically use this plugin together with the sbt-osgi plugin. Then sbt-osgi creates a bundle jar with a correct manifest, and sbt-spifly passes this jar to the Aries SPI Fly weaving tool, generating a second artifact with the spifly classifier.

Versions

The initial version of the sbt-spifly plugin, 0.1.0, targeted sbt versions 0.x, starting from 0.13.8. Later plugin versions require sbt 1.x. So if you still use a 0.x sbt version, you are limited to version 0.1.0.

Using sbt-spifly

sbt-spifly is an sbt Autoplugin. In order to use the plugin in a build project, it has to be declared in <PROJECT_ROOT>/project/plugins.sbt first:

// Other stuff

addSbtPlugin("com.github.oheger.sbt" % "sbt-spifly" % "0.3.0")

Then it can be enabled for the current project. Here is an example how this looks like for a <PROJECT_ROOT>/build.sbt file:

import com.github.oheger.sbt.spifly.SbtSpiFly
import com.github.oheger.sbt.spifly.SbtSpiFly.autoImport._
import com.typesafe.sbt.osgi.SbtOsgi.autoImport._
import com.typesafe.sbt.osgi.{OsgiKeys, SbtOsgi}

lazy val myBundleProject = (project in file ("."))  // project reference
  .enablePlugins(SbtSpiFly)           // enables both osgi and spifly plugins
  .settings(osgiSettings: _*)         // import settings for OSGi plugin
  .settings(spiFlySettings: _*)       // import settings for spifly plugin
  .settings(
    // configure bundle manifest, e.g. set a SPI Fly header
    OsgiKeys.additionalHeaders :=
      Map("SPI-Consumer" -> "javax.sound.sampled.AudioSystem#getAudioInputStream"),
    ...
  )

By importing the settings of the osgi and spifly plugins, it is ensured that the default publishing behavior is changed and the bundle and spiFly tasks are executed. This means it is sufficient to invoke

sbt publishLocal

to generate an OSGi bundle processed with the SPI Fly weaving tool. Actually, the build produces two artifacts: * the normal OSGi bundle jar * a second jar with the classifier spifly which has been processed by SPI Fly

The spifly artifact can then be deployed in an OSGi framework.

Further Options

A limited number of options is available to configure the weaving process.

Classifier

It is possible to configure the classifier, under which the processed artifact is published. This can be done via the classifier settings key. If it is not specified, spifly is used as default. The setting is actually an Option. It can be set to None, then no classifier is used at all, and the processed artifact overrides the original one.

Below is an example how to set an alternative classifier, osgi:

lazy val myBundleProject = (project in file ("."))
  .enablePlugins(SbtSpiFly)
  .settings(osgiSettings: _*)
  .settings(spiFlySettings: _*)
  .settings(
    SpiFlyKeys.classifier := Some("osgi")
  )

The following example disables the classifier:

lazy val myBundleProject = (project in file ("."))
  .enablePlugins(SbtSpiFly)
  .settings(osgiSettings: _*)
  .settings(spiFlySettings: _*)
  .settings(
    SpiFlyKeys.classifier := None
  )

skipSpiFly

The skipSpiFly boolean option allows skipping the invocation of the SPI Fly weaving tool. In this mode, only a normal OSGi bundle is produced. Below is an example:

lazy val myBundleProject = (project in file ("."))
  .enablePlugins(SbtSpiFly)
  .settings(osgiSettings: _*)
  .settings(
    SpiFlyKeys.skipSpiFly := true
  )

The flag is useful to temporarily suppress the weaving in a build without removing the plugin declaration. It can also be beneficial in multi-module projects that produce OSGi bundles which only partly have to be processed via SPI Fly. Then all the subprojects producing bundles can be declared to use only the SbtSpiFly plugin; so declarations are homogeneous. When further processing all the generated bundles (e.g. in a custom plugin) it can be easier to just have to process the results from a single task.

spiFly task

The plugin introduces the spiFly task which can also be invoked directly. But this task requires that the bundle jar has already been created.

License

This code is open source software licensed under the Apache 2.0 License.

Release notes

Version 0.4.0

  • Added the skipSpiFly key to suppress the invocation of the SPI Fly weaving tool.

Version 0.3.0

  • Added the classifier key that allows customizing or disabling the classifier, under which the processed artifact gets published.

Version 0.2.0

  • Support for newer versions of sbt.

Version 0.1.0

  • Initial release