Bundle Plugin

Build bundles using maven and the bundle-plugin - used to build and package components for the Vespa Container. Prerequisite: Do the quick-start. Start from vespa-engine/sample-apps/basic-search-java/pom.xml - below is the minimal:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.yahoo.example</groupId>
  <artifactId>basic-application</artifactId>
  <packaging>container-plugin</packaging> <!-- Use Vespa packaging -->
  <version>1.0.1</version>

  <build>
    <plugins>
      <plugin> <!-- Build the bundles -->
        <groupId>com.yahoo.vespa</groupId>
        <artifactId>bundle-plugin</artifactId>
        <version>6-SNAPSHOT</version>
        <extensions>true</extensions>
      </plugin>
      <plugin> <!-- Zip the application package -->
        <groupId>com.yahoo.vespa</groupId>
        <artifactId>vespa-application-maven-plugin</artifactId>
        <version>6-SNAPSHOT</version>
        <executions>
          <execution>
            <goals>
              <goal>packageApplication</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency> <!-- Vespa dependencies -->
      <groupId>com.yahoo.vespa</groupId>
      <artifactId>container</artifactId>
      <version>6-SNAPSHOT</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>
Create a deployable application package:
$ mvn install package

The bundle plugin automates generation of configuration classes by invoking the maven step generate-resources - read more in configuring-components.html

Including third-party libraries

Include external dependencies into the bundle by specifying them as dependencies:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20090211</version>
</dependency>
All packages in the library will then be available for use. If the external dependency is an OSGi bundle, one can deploy it instead of including it into the bundle by setting the scope to provided:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20090211</version>
  <scope>provided</scope>
</dependency>

Then deploy the external dependency along with the bundle. Only packages exported by the author of the library will then be available for use (see the section below).

Exporting, Importing and Including Packages from Bundles

OSGi features information hiding — by default all the classes used inside a bundle are invisible from the outside. Also, the bundle will by default only see (all) the packages in the Java and Container + Vespa APIs. If any other package is needed by the bundle, then it must happen in one of three ways:

  • Some additional packages are exported by the container and may be imported explicitly by a bundle
  • In addition, any deployed bundle may export packages on its own, which may then be imported by another bundle
  • Finally, the bundle may include its own JAR libraries
One can export packages from a bundle by annotating the package. E.g. to export com.mydomain.mypackage, create package-info.java in the package directory with:
@ExportPackage(version = @Version(major=1, minor=0, micro=0))
package com.mydomain.mypackage;

import com.yahoo.osgi.annotation.ExportPackage;
import com.yahoo.osgi.annotation.Version;
The Maven plugin will place such information in the manifest of the plugin JAR built to be picked up by the Container.

Note that this may also be used with bundles that do not contain any searchers but libraries used by other searchers - a bundle may just exist to export some libraries and never have any searchers instantiated.

Bundles may import packages (exported by some other bundle or by the container). The maven plugin will automatically import any package used from bundles it compiles against(i.e. maven dependencies with scope provided).

As mentioned above, each exported package has a version associated with it. Similary, an import of a package has a version range associated with it. The version range determines which exported packages can be used. The range used by the maven plugin is the current version(i.e. the version of the package available at compile time) up to the next major version (not including).

To learn more about OSGi manifests and bundle packaging (e.g how to include Java libraries and native code), please refer to the OSGi spec at the OSGi home page.

More details in troubleshooting.

Configuring the Bundle-Plugin

The bundle plugin can be configured to tailor the resulting bundle to specific needs.

<build>
  <plugins>
    <plugin>
      <groupId>com.yahoo.vesp</groupId>
        <artifactId>bundle-plugin</artifactId>
        <version>vespa-version</version>
        <extensions>true</extensions>
        <configuration>
          <discApplicationClass>…</discApplicationClass>
          <discPreInstallBundle>…</discPreInstallBundle>
          <bundleVersion>…</bundleVersion>
          <bundleSymbolicName>…</bundleSymbolicName>
          <bundleActivator>…</bundleActivator>
          <configGenVersion>…</configGenVersion>
          <configModels>…</configModels>
        </configuration>
    </plugin>
  • discApplicationClass: The fully qualified class name of the Application to be started by JDisc.
  • discPreInstallBundle: The name of the bundles that jDISC must pre-install.
  • bundleVersion: The version of this bundle. Defaults to the Maven project version.
  • bundleSymbolicName: The symbolic name of this bundle. Defaults to the Maven artifact ID.
  • bundleActivator: The fully qualified class name of the bundle activator.
  • configGenVersion: The version of com.yahoo.vespa.configlib.config-class-plugin that will be used to generate config classes.
  • configModels: List of config models.

Troubleshooting

A package p is imported if all of the following holds:

  1. Using a class in p directly (i.e. not with reflection) in the bundle
  2. There's no classes in the bundle that is in p
  3. There's a bundle that exports p, and compiling against this bundle
To debug, run
$ mvn -X package
and look at Defined packages (=packages in the bundle), Exported packages of dependencies, Referenced packages(= packages used). A package is imported if it is in Exported packages and Referenced packages but not in Defined packages.