Question

I have a Bundle P(rovider= which implements an Interface Defined in Bundle I(interface) Bundle U(ser) should use this Service. After I started the application everything works fine, all my service can be used. But when I update the Bundle P, non of its service can be resolved.

The update method looks like this:

this._bundle.stop();
this._bundle.update(new FileInputStream(updateFile));
this._bundle.start();

This is my BundleActivator for all of my Packages which also should handle ServiceRegistrations and ServiceReferences:

public abstract class BundleActivator implements org.osgi.framework.BundleActivator, BundleListener, ServiceListener
{
/**
 * Bundle Context.
 */
protected BundleContext context;

/**
 * Services which are registered by this bundle.
 */
protected HashSet<ServiceRegistration> serviceRegistrations = new HashSet<ServiceRegistration>();

/**
 * Service references used by this bundle.
 */
protected HashMap<String, ServiceReference> serviceReferences = new HashMap<String, ServiceReference>();

/**
 * Perform this method after Bundle has started.
 *
 * @param bc BundleContext.
 */
protected abstract void afterStart(BundleContext bc);

/**
 * Perform this method before Bundle is going to be stoped.
 *
 * @param bc BundleContext.
 */
protected abstract void beforeStop(BundleContext bc);

/**
 * Perform this method after Bundle has changed.
 *
 * @param be BundleEvent
 */
protected abstract void afterBundleChanged(BundleEvent be);

/**
 * Returns the bundle context for this bundle.
 *
 * @return bundle context
 */
public BundleContext getContext() {
    return this.context;
}

/**
 * Registeres a service.
 *
 * @param clazz      interface
 * @param service    service
 * @param properties properties
 *
 * @return service registration
 */
public ServiceRegistration registerService(Class clazz, Object service, Dictionary<String, ?> properties) {
    return this.registerService(clazz.getCanonicalName(), service, properties);
}

/**
 * Registeres a service.
 *
 * @param clazz      interface
 * @param service    service
 * @param properties properties
 *
 * @return service registration
 */
public ServiceRegistration registerService(String clazz, Object service, Dictionary<String, ?> properties) {
    ServiceRegistration retval = this.context.registerService(clazz, service, properties);
    System.out.println("registered service: " + retval.toString() + " for " + clazz);
    this.serviceRegistrations.add(retval);
    return retval;
}

/**
 * Returns a registered service.
 *
 * @param clazz interface
 *
 * @return service instance
 */
public Object getService(Class clazz) {
    if (clazz == null) {
        return null;
    }
    return this.getService(clazz.getCanonicalName());
}

/**
 * Returns a registered service.
 *
 * @param clazz interface
 *
 * @return service instance
 */
public Object getService(String clazz) {
    if (clazz == null) {
        return null;
    }
    System.out.println("Class: " + clazz);
    ServiceReference sr = this.context.getServiceReference(clazz);
    System.out.println("SR: " + sr);
    if (sr == null) {
        if (this.serviceReferences.containsKey(clazz)) {
            System.out.println("Unget service");
            this.context.ungetService(this.serviceReferences.get(clazz));
            this.serviceReferences.remove(clazz);
        }
        sr = this.context.getServiceReference(clazz);
        System.out.println("SR: " + sr);
        if (sr == null) {
            return null;
        }
    }

    try {
        this.context.addServiceListener(this, "(objectClass=" + clazz + ")");
    } catch (InvalidSyntaxException ex) {
        Logger.getLogger(BundleActivator.class.getName()).log(Level.SEVERE, null, ex);
    }

    this.serviceReferences.put(clazz, sr);
    return this.context.getService(sr);
}

@Override
public void start(BundleContext bc) throws Exception {
    ContextRegistry.getInstance().add(bc);

    this.context = bc;
    this.context.addBundleListener(this);
    this.afterStart(bc);
    System.out.println("Balindoo bundle activated: " + this.getClass().getPackage().getName());
}

@Override
public void stop(BundleContext bc) throws Exception {
    this.beforeStop(bc);

    for (ServiceRegistration sr : this.serviceRegistrations) {
        this.context.ungetService(sr.getReference());
        sr.unregister();
    }
    this.serviceRegistrations.clear();

    for (ServiceReference sr : this.serviceReferences.values()) {
        this.context.ungetService(sr);
    }
    this.serviceReferences.clear();

    ContextRegistry.getInstance().remove(bc);
    this.context.removeBundleListener(this);
    this.context = null;
    System.out.println("Balindoo bundle deactivated: " + this.getClass().getPackage().getName());
}

@Override
public void bundleChanged(BundleEvent be) {
    String name = be.getBundle().getSymbolicName();
    if (name.startsWith("com.vaadin")) {
        if (be.getType() == BundleEvent.STARTED && !ResourceProvider.getInstance().hasBundle(be.getBundle())) {
            ResourceProvider.getInstance().add(be.getBundle());
        } else if (be.getType() == BundleEvent.STOPPED && ResourceProvider.getInstance().hasBundle(be.getBundle())) {
            ResourceProvider.getInstance().remove(be.getBundle());
        }
    }

    for (ServiceReference sr : this.serviceReferences.values()) {
        this.context.ungetService(sr);
    }
    this.serviceReferences.clear();

    HashSet<Bundle> thisBundle = new HashSet<>();
    thisBundle.add(this.context.getBundle());
    thisBundle.add(be.getBundle());

    FrameworkWiring wiring = this.context.getBundle().adapt(FrameworkWiring.class);
    if (wiring != null) {
        System.out.println("FrameworkWiring:\n\tthis:\t" + this.context.getBundle().getSymbolicName() + "\n\tto  :\t" + be.getBundle().getSymbolicName());
        wiring.refreshBundles(thisBundle);
    }

    this.afterBundleChanged(be);
}

@Override
public void serviceChanged(ServiceEvent event) {
    switch (event.getType()) {
        case ServiceEvent.UNREGISTERING:
            System.out.println("unregister service");
            if (this.serviceReferences.containsValue(event.getServiceReference())) {
                //Remove
            }
            this.context.ungetService(event.getServiceReference());
            break;
    }
}

As you can see, i tried a lot to resolve this Problem, but nothing worked. What am I doing wrong?

Here is the Manifest for the bundle P (org.company.example.data). The interface is located in org.company.example.data.api which is in a separate bundle.

Manifest-Version: 1.0
Bnd-LastModified: 1381157007428
Build-Jdk: 1.7.0_21
Built-By: nspecht
Bundle-Activator: org.company.example.data.impl.BundleActivator
Bundle-Description: Example Bundle org.company.example.data 1.0.0
Bundle-ManifestVersion: 2
Bundle-Name: org.company.example.data
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-SymbolicName: org.company.org.company.example.data
Bundle-Vendor: Company Inc.
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Eclipse-BuddyPolicy: registered
Eclipse-RegisterBuddy: org.company.wrapper.hibernate
Export-Package: org.company.example.data.api;uses:="org.company.example.data.api.model";version="1.0.0",org.company.example.data.impl;uses:="org.company.example.data.api,org.company.utils.data.database,org.osgi.framework,org.company.example.data.api.model,org.company.utils.modulemanager.generic,org.hibernate,org.hibernate.criterion";version="1.0.0",org.company.example.data;version="1.0.0",org.company.example.data.api.impl;uses:="org.osgi.framework,org.company.utils.modulemanager.generic";version="1.0.0",org.company.example.data.api.model;uses:="org.company.utils.data.api";version="1.0.0",org.company.example.data.i18n;version="1.0.0"
Import-Package: org.company.utils.data.api;version="[1.0,2)",org.company.utils.data.database;version="[1.0,2)",org.company.utils.modulemanager.generic;version="[1.0,2)",org.hibernate;version="4.2,5)",org.hibernate.criterion;version="4.2,5)",org.osgi.framework;version="[1.6,2)"
Tool: Bnd-1.50.0

The Manifest for the Interface bundle:

Manifest-Version: 1.0
Bnd-LastModified: 1381156992131
Build-Jdk: 1.7.0_21
Built-By: nspecht
Bundle-Activator: org.company.example.data.api.impl.BundleActivator
Bundle-Description: Example Bundle org.company.example.data.api 1.0.0
Bundle-ManifestVersion: 2
Bundle-Name: org.company.example.data.api
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-SymbolicName: org.company.org.company.example.data.api
Bundle-Vendor: Company Inc.
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Eclipse-BuddyPolicy: registered
Export-Package: org.company.example.data.api;uses:="org.company.example.data.api.model";version="1.0.0",org.company.example.data.api.impl;uses:="org.osgi.framework,org.company.utils.modulemanager.generic";version="1.0.0",org.company.example.data.api.model;uses:="org.company.utils.data.api";version="1.0.0"
Import-Package: org.company.utils.data.api;version="[1.0,2)",org.company.utils.modulemanager.generic;version="[1.0,2)",org.osgi.framework;version="[1.6,2)"
Tool: Bnd-1.50.0

At least the interface for the Bundle U:

Manifest-Version: 1.0
Bnd-LastModified: 1381157008373
Build-Jdk: 1.7.0_21
Built-By: nspecht
Bundle-Activator: org.company.example.webui.impl.BundleActivator
Bundle-Description: Example Bundle org.company.example.webui 1.0.0
Bundle-ManifestVersion: 2
Bundle-Name: org.company.example.webui
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-SymbolicName: org.company.org.company.example.webui
Bundle-Vendor: Company Inc.
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Eclipse-BuddyPolicy: registered
Export-Package: org.company.example.webui.impl;uses:="org.company.utils.webui,org.company.example.data.api,org.company.example.webui.menu,org.osgi.framework,org.company.utils.webui.menu,org.company.example.webui.view,org.company.utils.modulemanager.generic,org.company.utils.modulemanager.exception";version="1.0.0",org.company.example.webui.menu;uses:="org.company.utils.webui,org.company.utils.webui.generics,org.company.utils.modulemanager.translation,org.company.example.webui.view,org.company.utils.webui.menu";version="1.0.0",org.company.example.webui.i18n;version="1.0.0",org.company.example.webui.view;uses:="org.company.example.data.api,com.vaadin.server,org.company.utils.modulemanager.translation,org.company.example.data.api.model,com.vaadin.ui,org.company.example.webui.impl,com.vaadin.event,org.company.utils.webui.exception,com.vaadin.data,com.vaadin.data.util,com.vaadin.navigator,org.company.utils.modulemanager.exception";version="1.0.0"
Import-Package: com.vaadin.data;version="[7.1,8)",com.vaadin.data.util;version="[7.1,8)",com.vaadin.event;version="[7.1,8)",com.vaadin.navigator;version="[7.1,8)",com.vaadin.server;version="[7.1,8)",com.vaadin.ui;version="[7.1,8)",org.company.example.data.api;version="[1.0,2)",org.company.example.data.api.model;version="[1.0,2)",org.company.utils.modulemanager.exception;version="[1.0,2)",org.company.utils.modulemanager.generic;version="[1.0,2)",org.company.utils.modulemanager.translation;version="[1.0,2)",org.company.utils.webui;version="[1.0,2)",org.company.utils.webui.exception;version="[1.0,2)",org.company.utils.webui.generics;version="[1.0,2)",org.company.utils.webui.menu;version="[1.0,2)",org.osgi.framework;version="[1.6,2)"
Tool: Bnd-1.50.0
Was it helpful?

Solution

Check who is exporting the package containing the service interface I. Both P and U must be wired to the same package. In order to ensure U can use the service object, the framework verifies that U is wired to the same package as P.

It appears that after updating P, the new P' is wired to a different revision of the package than U. So when P' registers the service, it comes from a different revision of the package.

This can occur if the package is contained in P and exported by P without having P also import the same package. A service provider should both export and import the service interface package. See http://blog.osgi.org/2007/04/importance-of-exporting-nd-importing.html

OTHER TIPS

you most likely need to "refresh" your consuming bundles (U) also, since usually the consuming bundle keeps a reference to the original bundle P and therefore it won't see your new Services. So you need to bring your bundle U back into the "resolving" state. At the GOGO shell you usually just issue the refresh command.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top