...
IGB runs within an OSGi framework, also called the OSGI "container" or "runtime." This means you can easily extend IGB without modifying the core IGB code base. By implementing a few well-described interfaces and using the Apache maven project management tool, you can add new menu items, create new kinds of tracks, or connect IGB to all-new data sources - all without re-installing or even re-starting IGB.
...
How this works
Apps can interact with and add new functionality to IGB by implementing services controlled by the OSGi container that runs IGB. In other words, Apps add new functionality to IGB by implementing services that IGB can consume as services controlled and instantiated by the OSGi run-time.
The Hello World App adds a new menu item to the Tools menu by implementing the MenuBarEntryProvider interface, defined in org.lorainelab.igb.menu.api, which is part of the Menu API module in the IGB code base.
Code Block | ||||
---|---|---|---|---|
| ||||
public interface MenuBarEntryProvider {
public Optional<List<MenuItem>> getMenuItems();
public MenuBarParentMenu getMenuExtensionParent();
} |
The Hello World App uses maven to build and deploy the App for consumption as an OSGi bundle in IGB.
Maven build system assumes that every Java project conforms to an expected directory structure. Here, the maven project includes:
- pom.xml - located at the top level of the project. An IGB App's pom.xml file specifies services the App needs to import from the IGB code base as well as any 3rd party libraries used by your App.
- src - contains source code, organized as shown. Every maven project contains src/main/java, which contains java packages organized as directories in the usual way. The example shows a single Java source code file/
To see the directory structure for your project in NetBeans, select the Files tab (next to the Projects tab).
HelloWorld pom.xml
The pom.xml contains information about the project and configuration details used by Maven to build the project. Here is the pom.xml file for the Hello World App:
Code Block |
---|
<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>
<parent>
<groupId>org.lorainelab.igb</groupId>
<artifactId>igb-project</artifactId>
<version>9.0.0</version>
</parent>
<groupId>org.lorainelab.igb</groupId>
<artifactId>org.lorainelab.igb.menu.api.example</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<name>IGB Menubar Extension</name>
<dependencies>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bndlib</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.lorainelab.igb</groupId>
<artifactId>org.lorainelab.igb.menu.api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>build plugin repository</id>
<goals>
<goal>
index
</goal>
</goals>
<phase>package</phase>
<configuration>
<obrRepository>${project.build.directory}</obrRepository>
<mavenRepository>${project.build.directory}</mavenRepository>
</configuration>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Import-Package>*</Import-Package>
<Export-Package/>
<Service-Component>*</Service-Component>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
|
The parent tag specifies which IGB version an App is compatible with. It is important to specify the It also enables your project to inherit configurations from the parent pom.xml file, which will save you time and effort.
...
...
Code Block | ||
---|---|---|
| ||
<parent>
<groupId>com.affyorg.lorainelab.igb</groupId>
<artifactId>igb-project</artifactId>
<version>9.0.0</version>
</parent> |
...
packaging tag
This tag specifies packaging type - e.g., war or jar. In IGB, we use an OSGi-specific packaging structure called a "bundle," which is a jar file with additional metadata. This additional metadata transforms an ordinary jar file into a plug-able module in the OSGi runtime. The IGB project uses the Apache Felix Maven Bundle plugin (BND) to generate this metadata. The BND bundle defines the packaging type "bundle."
Code Block | ||
---|---|---|
| ||
<packaging>bundle</packaging> |
name tag
...
...
...
...
Code Block | ||||
---|---|---|---|---|
| ||||
<name>IGB Menubar Extension</name> |
dependency tags (parent tag "dependencies")
The term "dependency" just means: third-party resources your project requires to compile and run, such as library files.
Your pom.xml file should contain a single "dependencies" tag with several "dependency" child tags:
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<dependencies>
<dependency>...</dependency>
<dependency>...</dependency>
</dependencies> |
biz.aQute.bnd:bndlib
This dependency enables the Declarative Services annotations used within the IGB code base that allow easy service consumption and registration with the IGB OSGi component runtime.
Note how that scope tag is "provided" - this is because the parent pom.xml file defines this dependency in its dependencyManagement tag. When mvn compiles your App, mvn will retrieve necessary metadata about the dependency, such as its version and other information, from the parent pom.
Code Block | ||
---|---|---|
| ||
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bndlib</artifactId>
<scope>provided</scope>
</dependency> |
org.lorainelab.igb
This dependency is the igb menu api module containing the MenuBarEntryProvider interface used in our code.
Code Block | ||
---|---|---|
| ||
<dependency>
<groupId>org.lorainelab.igb</groupId>
<artifactId>org.lorainelab.igb.menu.api</artifactId>
<scope>provided</scope>
</dependency> |
build, plugins, and plugin tag
maven-bundle-plugin
This is the most important plugin to be aware of as an IGB module developer. This plugin is known as the "Swiss army knife of OSGi" and is a wrapper around the BND project described in the previous section.
Code Block | ||
---|---|---|
| ||
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>build plugin repository</id>
<goals>
<goal>
index
</goal>
</goals>
<phase>package</phase>
<configuration>
<obrRepository>${project.build.directory}</obrRepository>
<mavenRepository>${project.build.directory}</mavenRepository>
</configuration>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Import-Package>*</Import-Package>
<Export-Package/>
<Service-Component>*</Service-Component>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
|
There are several important things to understand about the above configuration.
...
- The metadata can optionally include service component definition files as described in the OSGi Declarative Services Specification (See http://wiki.osgi.org/wiki/Declarative_Services for more information)
- We use annotations in our java code which are processed at compile time by the felix maven bundle plugin to generate the service component definition files for a bundle.
...
Creating a new Java class (MenuBarExtensionExample)
The Hello World IGB App from the completed project example uses a Java class called MenuBarExtensionExample. If you wish to create this class yourself, you can do so in Netbeans by following the instructions below.
- Within NetBeans, check that your IGB Menubar Extension project is the currently selected project. If it isn't, select File > Open Project to open it.
- Next, create a new Java class named MenuBarExtensionExample:
- Select File > New File
- Select Java Class as your file type.
- Select Next
- Enter class Name MenuBarExtensionExample
- Select package org.lorainelab.igb.menu.api.example
- Select Finish
Your newly created class should match the code seen below:
language | java |
---|---|
title | MenuBarExtensionExample |