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.
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.
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.
A limited number of options is available to configure the weaving process.
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
)
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.
The plugin introduces the spiFly
task which can also be invoked directly. But
this task requires that the bundle jar has already been created.
This code is open source software licensed under the Apache 2.0 License.
-
Added the
classifier
key that allows customizing or disabling the classifier, under which the processed artifact gets published.