Grim
Grim

Reputation: 2040

Felix not starting bundle

Can not load a bundle into felix. I downloaded Felix 6.0.1, run using

> java -jar bin/felix.jar
____________________________
Welcome to Apache Felix Gogo

g! 

I create a MavenProject TestA in eclipse:

  1. I add a dependency to felix (6.0.1) as provided.
  2. I create a class in TestA/src/main/java/testa/impl/Activator.java.
  3. I extend the class testa.impl.Activator to org.osgi.framework.BundleActivator.
  4. I overwrite the public void start(BundleContext bc) throws Exception to print out Hello World!.

This is the java source:

package testa.impl;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

    public void start(BundleContext arg0) throws Exception {
        System.out.println("Hello World!");
    }

    public void stop(BundleContext arg0) throws Exception {
        System.out.println("stop");
    }
}

This is my pom.xml:

<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>test</groupId>
    <artifactId>testa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.main</artifactId>
            <version>6.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <defaultGoal>clean install org.apache.felix:maven-bundle-plugin:bundle</defaultGoal>
    </build>
</project>

Then I compile to jar using mvn and load using

g! install file:/C:/xxx/TestA/target/testa-0.0.1-SNAPSHOT.jar                              
Bundle ID: 20

Then I list all bundles using lb

g! lb                                                                                                           15:51:56
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.1)|6.0.1
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
   20|Installed  |    1|testa (0.0.1.SNAPSHOT)|0.0.1.SNAPSHOT
g!                                                                                                              

Anyway I start the bundle using start:

g! start 20
g!

I expected to have "Hello World" printed but nothing shows up!

I am confused now and try to find out if the bundle realy has started.

g! lb                                                                                                           15:51:56
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.1)|6.0.1
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
   20|Active     |    1|testa (0.0.1.SNAPSHOT)|0.0.1.SNAPSHOT
g!                                                                                                              15:51:58

Its started but my code has not been executed.

Question

Why is Hello World not printed on the console?

Upvotes: 1

Views: 1832

Answers (2)

Erik Lievaart
Erik Lievaart

Reputation: 433

Hello World is not printed on the console, because the jar you created is not actually a bundle. Oddly, felix allows you to start a jar that doesn't have any OSGI related information in the manifest. It is unclear to me what starting such a bundle means? Maybe the classes get published, maybe they don't.

Most java frameworks scan the files in a jar and use reflection or byte code analysis to find relevant classes. For normal frameworks, the overhead of scanning jars is incurred only once, on startup. OSGI was designed to be lightweight and is also used on mobile. Moreover, since in OSGI bundles can come and go, they designed a more efficient approach. OSGI bundles store the metadata in the manifest. This is a simple text file that is always in the same location (in the jar): "META-INF/MANIFEST.MF". If you use a zip tool to inspect the file in the jar, you should see something like this:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Peter Rader
Build-Jdk: 1.8.0_111

For future OSGI troubleshooting I would suggest you inspect (and post) the manifest that is created.

A valid OSGI manifest would look something like this:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Peter Rader
Build-Jdk: 1.8.0_111
Bundle-Name: testa
Bundle-SymbolicName: testa.impl
Bundle-Version: 1.0.0
Bundle-Activator: testa.impl.Activator
Import-Package: org.osgi.framework

When felix reads this manifest it uses the "Bundle-Activator" entry to find the activator (if any). Replace the manifest and the bundle should be deployed normally.
Simply create a text file named "META-INF/MANIFEST.MF" containing the text above in a location relative to the jar. Next replace the manifest file in the jar with the following linux command (or your favorite zip tool):

zip testa-0.0.1-SNAPSHOT.jar -u META-INF/*

expected output from the zip command:

updating: META-INF/MANIFEST.MF (deflated 36%)

Be sure to open the jar with a zip file and check that the contents have changed. Now if you install and start the bundle it should print "Hello World!".

Although this fixes the problem, it's not a very clean solution.
The jar specification has some rather odd rules, as to how entries in the manifest should be formatted:
https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Manifest_Specification
Most notably:

No line may be longer than 72 bytes (not characters), in its UTF8-encoded form.
If a value would make the initial line longer than this, 
it should be continued on extra lines (each starting with a single SPACE).

Therefore, you don't want to be editing this file by hand. As others have remarked, you have various options for generating an OSGI manifest automatically. As before, you can check the manifest in the generated jar to verify that it is being generated correctly.

Upvotes: 1

BJ Hargrave
BJ Hargrave

Reputation: 9384

You seem to be manually creating the manifest. You should using tools like bnd-maven-plugin to do it. Since you manually created the manifest, it appears wrong. You do not import the packages you use in your code. Namely org.osgi.framework.

Also, do not extends an activator class from someone else's code since you generally cannot import their implementation packages. Just implement it yourself:

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class TestA implements BundleActivator {

Upvotes: 1

Related Questions