Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
161 views
in Technique[技术] by (71.8m points)

java - Apache Maven Assembly Plugin not working with OSGi bundles

I have a Maven OSGi multi-module project. The project runs perfectly well when the OSGi picks the module jars from the individual project modules. (view 1.1.B below).

However, using a second approach, bundle.getRegisteredServices() (view 1.1.A below) returns null whenever I try using bundles deposited into a central folder (D:/parent/provider/target/modules) using the maven-assembly-plugin version : 2.6:

framework.getBundleContext().installBundle("file:D:/parent/provider/target/modules/OSGiDmHelloWorldProvider-1.0.jar");
framework.getBundleContext().installBundle("file:D:/parent/provider/target/modules/OSGiDmHelloWorldConsumer-1.0.jar");

View 1.1.C below for console output using the second approach.

1.1.A

if (bundle.getRegisteredServices() != null) {
    for (ServiceReference<?> serviceReference : bundle.getRegisteredServices())
        System.out.println("Registered service: " + serviceReference);
}

Why can't I access the bundles with the second approach?

GitHub

I have a SSCCE on GitHub HERE. Running the main class will show my predicament.

Thank you all in advance.

1.1.B

package main;

import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;

public class App {

    public static void main(String[] args) throws BundleException, URISyntaxException {
        App app = new App();
        app.initialize();
    }

    private void initialize() throws BundleException, URISyntaxException {
        Map<String, String> map = new HashMap<String, String>();

        // make sure the cache is cleaned
        map.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);

        map.put("ds.showtrace", "true");
        map.put("ds.showerrors", "true");

        FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
        Framework framework = frameworkFactory.newFramework(map);

        System.out.println("Starting OSGi Framework");
        framework.init();

        loadScrBundle(framework);

        framework.getBundleContext().installBundle("file:D:/parent/provider/target/OSGiDmHelloWorldProvider-1.0.jar");
        framework.getBundleContext().installBundle("file:D:/parent/consumer/target/OSGiDmHelloWorldConsumer-1.0.jar");

        for (Bundle bundle : framework.getBundleContext().getBundles()) {
            bundle.start();
            System.out.println("Bundle: " + bundle.getSymbolicName());
            if (bundle.getRegisteredServices() != null) {
                for (ServiceReference<?> serviceReference : bundle.getRegisteredServices())
                    System.out.println("Registered service: " + serviceReference);
            }
        }
    }

    private void loadScrBundle(Framework framework) throws URISyntaxException, BundleException {
        URL url = getClass().getClassLoader().getResource("org/apache/felix/scr/ScrService.class");
        if (url == null)
            throw new RuntimeException("Could not find the class org.apache.felix.scr.ScrService");
        String jarPath = url.toURI().getSchemeSpecificPart().replaceAll("!.*", "");
        System.out.println("Found declarative services implementation: " + jarPath);
        framework.getBundleContext().installBundle(jarPath).start();
    }
}

1.1.C

Starting OSGi Framework
Found declarative services implementation: file:/C:/Users/Revilo/.m2/repository/org/apache/felix/org.apache.felix.scr/1.6.2/org.apache.felix.scr-1.6.2.jar
INFO : org.apache.felix.scr (1):  Version = 1.6.2
DEBUG: Starting ComponentActorThread
Bundle: org.apache.felix.framework
    Registered service: [org.osgi.service.resolver.Resolver]
    Registered service: [org.osgi.service.packageadmin.PackageAdmin]
    Registered service: [org.osgi.service.startlevel.StartLevel]
Bundle: org.apache.felix.scr
    Registered service: [org.apache.felix.scr.ScrService]
    Registered service: [org.osgi.service.cm.ManagedService]
    Registered service: [org.apache.felix.scr.impl.ScrGogoCommand]
Bundle: null
Bundle: null
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I had to do a lot to get your sample to duplicate the question.

First off your reactor order is wrong in the parent. That is why you have to do mvn install all the time.

<modules>
    <module>OSGiDmHelloWorldProvider</module>
    <module>OSGiDmHelloWorldConsumer</module>
    <module>main</module>
    <module>dist</module>
</modules>

Next, if you define a dependency (e.g. JUnit) in the parent you don't need to redfine it in the children.

Next, it is conventional to put the parent tag at the top of the pom.

I don't see a reason to have your child modules have a different version to the parent so I removed the tag so they all have 1.0-SNAPSHOT from the parent.

Next, you have the wrong group id in the OSGiDmHelloWorldProvider dependency (it should be rev).

    <dependency>
        <groupId>rev</groupId>
        <artifactId>OSGiDmHelloWorldProvider</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

In the main module you have a dependency that isn't in the reactor. I am guessing this is just an oversight of the sample.

    <dependency>
        <groupId>rev</groupId>
        <artifactId>core</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

After all that, mvn clean package -DskipTests=true works.

You have a hard-coded string in your Main class that obviously doesn't work for me. (You also might want to look at the free IDEA Community instead of Eclipse!)

String baseDir = "D:/standAloneDev/java/workingDir/Sample Projects/Eclipse/Gen/OSGiDmHelloWorld/dist/target/dist-1.0-SNAPSHOT-bin/plugins/";

You should make this relative. e.g.

File baseDir = new File("dist/target/dist-1.0-SNAPSHOT-bin/plugins/");
String baseDirPath = baseDir.getAbsolutePath();

loadScrBundle(framework);

File provider = new File(baseDirPath, "OSGiDmHelloWorldProvider-1.0-SNAPSHOT.jar");
File consumer = new File(baseDirPath, "OSGiDmHelloWorldConsumer-1.0-SNAPSHOT.jar");

framework.getBundleContext().installBundle(provider.toURI().toString());
framework.getBundleContext().installBundle(consumer.toURI().toString());

Anyway, after getting it going I noticed the following javadoc on bundle.getSymbolicName().

Returns the symbolic name of this bundle as specified by its Bundle-SymbolicName manifest header. The bundle symbolic name should be based on the reverse domain name naming convention like that used for java packages.

So in the MANIFEST.MF of org.apache.felix.scr-1.6.2.jar you have

Bundle-Name: Apache Felix Declarative Services
Bundle-SymbolicName: org.apache.felix.scr

You don't have this in yours as you are not creating a manifest and adding it to a jar.

You need to add an execution phase and tell the jar plugin to use the manifest:

        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <executions>
                <execution>
                    <id>bundle-manifest</id>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>manifest</goal>
                    </goals>
                </execution>
            </executions>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>OSGiDmHelloWorldProvider</Bundle-SymbolicName>
                    <Export-Package>com.bw.osgi.provider.able</Export-Package>
                    <Bundle-Activator>com.bw.osgi.provider.ProviderActivator</Bundle-Activator>
                    <Bundle-Vendor>Baptiste Wicht</Bundle-Vendor>
                </instructions>
            </configuration>
        </plugin>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...