Skip to content

Kura Addon Archetype

The Kura Addon Archetype is a Maven Archetype that allows to create a development environment with the following features:

  • Maven-based build
  • Template project for creating DEB packages
  • bnd based integration test template

The Kura Archetype JAR (kura-addon-archetype-<kura-version>.jar) is available in the released artifacts and can be installed in the local maven repository with the following command:

mvn install:install-file \
-Dfile=./kura-addon-archetype-<kura-version>.jar \
-DgroupId=org.eclipse.kura \
-DartifactId=kura-addon-archetype \
-Dversion="<kura-version>" \
-Dpackaging=jar \
-DgeneratePom=true

Valid <kura-version> values are 6.0.0-SNAPSHOT and 6.0.0. This archetype is available since Kura 6.0.0.

After that, it is possible to generate a project skeleton using the archetype with the following command:

mvn archetype:generate \
-DarchetypeArtifactId=kura-addon-archetype \
-DarchetypeGroupId=org.eclipse.kura \
-DarchetypeVersion="<kura-version>"

The command will start the generation of the archetype in interactive mode.

Maven will ask for a few parameters on the command line:

  • groupId : the Maven group id of the generated POM files
  • artifactId: the Maven artifact id of the generated parent pom file, and the name of the generated top level project folder
  • package: the base Java package and the main artifact of the project

The official Kura addons naming rule is:

  • groupId = org.eclipse.kura
  • artifactId = repository name: kura-<feature> (e.g. kura-wires)
  • package = org.eclipse.kura.<feature> (e.g. org.eclipse.kura.wires)

It is not allowed to generate a project with artifactId = package.

The following optional parameters can be changed by answering n after the Confirm properties configuration prompt, which appears after editing the properties above:

  • version: the generated project's version. Defaults to 1.0.0-SNAPSHOT
  • mainBundleVendor: the name of the vendor to use in the metadata. Defaults to Eclipse Kura
  • kuraVersion: the version of the Kura bill-of-materials, used to resolve dependencies. Defaults to 6.0.0[-SNAPSHOT]
  • year: the year to use in the copyright headers, which by default have the following format:
    Copyright (c) ${year} Eurotech and/or its affiliates and others
    
    This program and the accompanying materials are made
    available under the terms of the Eclipse Public License 2.0
    which is available at https://www.eclipse.org/legal/epl-2.0/
    
    SPDX-License-Identifier: EPL-2.0
    
    Contributors:
     Eurotech
    

A .gitignore file is automatically added with a default configuration. The OSGI-INF folder is omitted because it will be generated during tests at compile-time (this is necessary to make the PDE launcher work).

Add the generated sources to git

The project requires source control management via git to correctly build. To add the project to git run the following:

git init
git add .
git commit -m "initial commit"

Once this steps are completed you can safely build the project.

Project structure

At the end of the procedure, the generated project is organized as follows:

kura-myfeature
├── .gitignore
├── pom.xml
├── bom
│   └── pom.xml
├── distrib
│   ├── deb
│   └── pom.xml
├── org.eclipse.kura.myfeature
│   ├── pom.xml
│   └── src
└── tests
    ├── org.eclipse.kura.myfeature.test
    ├── pom.xml
    └── test-env
  • bom: this project's bill-of-materials, containing the list of all the bundles that this project will deploy. It is intended to be consumed by other projects

  • tests: contains unit tests and OSGi integration tests executed via the bnd-testing-maven-plugin.

  • distrib: a packaging project that builds a Debian (.deb) package. The package installs the JAR produced by the bundles into Kura’s plugins directory at /opt/eclipse/kura/plugins. You should review and adjust this project to match your target architecture and packaging requirements; the source is annotated with comments indicating the main configuration points

Project build

Requirements:

  • Java 21
  • Maven 3.9.9 or higher

The first build will require running the resolve-integration-tests profile to resolve the dependencies of the integration tests. This is necessary to populate the bndrun files with the correct versions of the dependencies.

Run the following command to execute the first build:

mvn clean install -P resolve-integration-tests

The resolve-integration-tests profile is only required to run when building the project for the first time and any time the runrequires field of the bndrun file changes. We suggest adding the bndrun files to the source control to avoid losing changes and to have a clear history of the changes made to the test dependencies.

The build will produce the following system packages in distrib/target:

  • DEB installer (<artifactId>_<version>_<debian-architecture>.deb)

Installer properties like the architecture, organization name, package dependencies, and others can be configured in the distrib project.

Install and run the generated packages

Depending on the system, the packages can be installed with:

apt install <artifactId>_<version>_<debian-architecture>.deb

After having installed the package, restart kura with:

systemctl restart kura

During startup Kura will scan the plugins folder to pick up the installed JARs and include them in the framework's runtime.

It is possible to remove the installed plugins with:

apt purge <artifactId> # or apt remove <artifactId>

Debug builds and Release builds

Since version 6.0.0 of the archetype, two type of builds are supported:

  • Debug builds: active by default, generate artifacts whose version is computed from the timestamp and the git commit hash. Versioning scheme: X.X.X~git{timestamp}.{hash}-{revision}
  • Release builds: generate release-ready artifacts. This build requires that no artifact/version is in "snapshot" mode. A "snapshot" version will result in a build failure. Versioning scheme: X.X.X-{revision}.

The build defaults to the debugBuild profile, if the -DreleaseBuild parameter is specified, the build selects the releaseBuild profile.

By default the package.revision is set to 1. It can be overridden via CLI using the -Dpackage.revision=N parameters.

Example:

mvn clean install -Dpackage.revision=6 -DreleaseBuild

Versions uptick

Using the following command it is possible to update the version of the project:

mvn versions:set -DnewVersion=<new-version> -DprocessAllModules=true

The BOM project and the bundles defined in the dependency management section are updated as well.

Don't forget to update the version in the various MANIFEST.MF of the bundles and tests.

Deploy artifacts

As default, the projects are not deployed (they are configured to skip the execution of the maven-deploy-plugin). Only the BOM POM (the root pom.xml) and the single OSGi bundles are meant to be deployed.

Please add the proper maven-deploy-plugin configuration for the bundles that need to be deployed. See the archetype's generated bundle for details.

IDE setup

Since the introduction of the bnd archetype, no specific IDE configuration is required to work with the generated projects. The project can be imported in any IDE that supports Maven projects, such as Visual Studio Code, IntelliJ Idea and Eclipse IDE.

Importing Projects in Visual Studio Code

To import the project in Visual Studio Code, open the root folder of the project. Refer to the VSCode documentation for more details on how to work with Java projects in VSCode.

Suggested extensions:

Importing Projects in IntelliJ Idea

To import the project in IntelliJ Idea, open the root folder of the project and select the pom.xml file. Refer to the IntelliJ documentation for more details on how to work with Maven projects in IntelliJ.

Importing Projects in Eclipse IDE

In Eclipse IDE, create a new workspace (it is not necessary to have the workspace in the root of the project) and import the projects with File | Import | Maven | Existing Maven Projects.

Note that if the workspace resides in the root of the project the parent POM file cannot be selected.

(Optional) IDE errors resolution

In some cases it might be necessary to manually configure the build path. For the bundles and test projects, select Properties and then Project Natures and add the natures as in picture below.

Then, from the Java Build Path configure the correct source folder as in picture below.

Finally, configure the external Classpath dependencies by selecting the plugin dependencies from the Add Library.

Architecture-specific development

The Addon Archetype standard procedure allows to build generic Debian installers not dependant on the architecture on which the bundle will be installed.

However, it is possible to customise the files in the distrib folder to develop architecture-dependant installers: this might be necessary when a bundle contains native code (C/C++ libraries, jars that use JNI, etc.) or architecture-specific files (e.g. a systemd service file).

In the following sections we will see how this can be accomplished for the DEB packages. These steps assume that architecture-specific jars are built in the form of fragments of the architecture-agnostic java code. The architecture-specific jars will then be copied in the distrib folder and included in the package. For example, given the following bundles structure:

org.eclipse.kura.myartifact
org.eclipse.kura.myartifact.aarch64
org.eclipse.kura.myartifact.x86_64
....

The org.eclipse.kura.myartifact.bundle contains the agnostic code, while the org.eclipse.kura.myartifact.aarch64 and org.eclipse.kura.myartifact.x86_64 fragments contain the architecture-specific code.

The objective is to produce two debian packages, one for each of the supported architectures. It is possible to modify the pom.xml in distrib to produce the correct metadata for the installers (see section below). Each debian package will install the main bundle and the relative fragment that matches the target environment. For example, the aarch64 deb package will install:

/opt/eclipse/kura/plugins/<start-level>s/org.eclipse.kura.myartifact-<version>.jar
/opt/eclipse/kura/plugins/<start-level>/org.eclipse.kura.myartifact.aarch64-<version>.jar

Note that the fragment org.eclipse.kura.myartifact.aarch64-<version>.jar is put in a plugins folder that is not ending with s since fragments can never be started as they don't have their own lifecycle.

Create architecture dependant installers

The /distrib/deb/control/control file contains the DEB package metadata. The standard file is configured as follows:

Package: [[package.name]]
Version: [[project.version]]
Section: admin
Priority: optional
Depends: kura
Architecture: [[deb.architecture]]
Maintainer: [[deb.maintainer]]
Description: [[summary]]
  [[long.description]]
Homepage: [[deb.docs]]

The Architecture field is the one responsible to specify the architecture of the package. The value is set in the /distrib/pom.xml file, by the property <deb.architecture>all</deb.architecture>. The value all means that the package can be installed on any architecture. This is the recommended value for packages that do not contain architecture-specific files.

To build a package that contains architecture-specific files, it is necessary to separate the control files of the different architectures (namely, aarch64 and amd64). To do so, create two directories in the distrib/deb/ folder with this structure:

distrib
├── deb
│   ├── amd64
│   ├── arm64
Each control file must be created in the distrib/deb/<arch>/ folder. These folders can also contain the postinst and postrm files, used to execute commands after the installation and before the removal of the package. The content of these files is not relevant for this example, but they can be used to execute commands that are necessary for the correct installation of the package.

An example of control file for the arm64 architecture is:

Package: [[package.name]]
Version: [[project.version]]
Section: admin
Priority: optional
Depends: kura
Architecture: [[deb.arm64.architecture]]
Maintainer: [[deb.maintainer]]
Description: [[summary]]
  [[long.description]]
Homepage: [[deb.docs]]

The same file for the amd64 architecture will just change the Architecture field to [[deb.amd64.architecture]].

Finally, the plugin responsible of generating the DEB package is the jdeb plugin. To build the architecture-dependant installers, the execution must change to:

<execution>
    <id>generate-arm64-deb</id>
    <phase>package</phase>
    <goals>
        <goal>jdeb</goal>
    </goals>
    <configuration>
        <verbose>true</verbose>
        <deb>${basedir}/target/deb/${output.installer.name}_${project.version}_${deb.arm64.architecture}.deb</deb>
        <controlDir>${project.basedir}/deb/arm64</controlDir>
        <skipPOMs>false</skipPOMs>
        <dataSet>
            <data>
                <src>${basedir}/target/plugins/${jar.name}-${project.version}.jar</src>
                <dst>${jar.name}-${project.version}.jar</dst>
                <type>file</type>
                <mapper>
                    <type>perm</type>
                    <prefix>${addon.installation.dir}</prefix>
                    <user>kurad</user>
                    <group>kurad</group>
                    <filemode>600</filemode>
                </mapper>
            </data>
            <data>
                <src>${basedir}/target/plugins/${jar.aarch64.core}-${project.version}.jar</src>
                <dst>${jar.aarch64.core}-${project.version}.jar</dst>
                <type>file</type>
                <mapper>
                    <type>perm</type>
                    <prefix>${native.core.installation.dir}</prefix>
                    <user>kurad</user>
                    <group>kurad</group>
                    <filemode>600</filemode>
                </mapper>
            </data>
        </dataSet>
    </configuration>
</execution>

A similar execution can be used for the amd64 architecture, just changing the deb and controlDir fields to point to the correct architecture (and change the execution id if they're present at the same time). Also in the <dataSet> section, the src and dst fields must be changed to point to the correct architecture-specific jars.

The final result will consist of two installers, one for each architecture. They will be found in the distrib/target/deb/ folder with the following names:

<artifactId>_<version>_<deb.amd64.architecture>.deb
<artifactId>_<version>_<deb.arm64.architecture>.deb