Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

Java, the OLPC, and community responsibility

The "One Laptop Per Child" project has a great device ready to ship, but there's no Java on there. Let's think about working together to put Java on OLPC!
Replies: 14 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

Getting Started with OSGi: Consuming a Service

At 11:23 AM on Feb 21, 2007, Neil Bartlett Javalobby Regulars wrote:

In our last part we looked at how to register a service. Now we need to work out how to lookup and use that service from another bundle.

We will put the problem in the context of our requirements, which as before are inspired by Martin Fowler's paper on dependency injection. We have built a MovieFinder as a service and registered it with the service registry. Now we want to build a MovieLister that uses the MovieFinder to search for movies directed by a specific director. Our assumption is that the MovieLister itself will be a service to be consumed by some other bundle, e.g. a GUI application. The trouble is, OSGi services are dynamic... they come and they go. That means sometimes we want to call the MovieFinder service but it just isn't available!

So, what should the MovieLister do if the MovieFinder service is not present? Clearly the call to the MovieFinder is a critical part of the work done by MovieLister , so there only a few choices available to us:

  1. Produce an error, e.g. return null or throw an exception.
  2. Wait.
  3. Don't be there in the first place.

In this article we're going to look at the first two options, as they are quite simple. The third option may not even make any sense to you yet, but hopefully it will after we look at some of the implications of the first two.

The first thing we need to do is define the interface for the MovieLister service. Copy the following into osgitut/movies/MovieLister.java :
package osgitut.movies;
 
import java.util.List;
 
public interface MovieLister {
    List listByDirector(String name);
}

Now create the file osgitut/movies/impl/MovieListerImpl.java :
package osgitut.movies.impl;
 
import java.util.*;
import osgitut.movies.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
 
public class MovieListerImpl implements MovieLister {
    private final ServiceTracker finderTrack;
 
    public MovieListerImpl(ServiceTracker finderTrack) {
        this.finderTrack = finderTrack;
    }
 
    public List listByDirector(String name) {
        MovieFinder finder = (MovieFinder) finderTrack.getService();
        if(finder == null) {
            return null;
        } else {
            return doSearch(name, finder);
        }
    }
 
    private List doSearch(String name, MovieFinder finder) {
        Movie[] movies = finder.findAll();
        List result = new LinkedList();
        for (int i = 0; i < movies.length; i++) {
            if(movies[i].getDirector().indexOf(name) > -1) {
                result.add(movies[i]);
            }
        }
 
        return result;
    }
}


This is probably our longest code sample so far! So what's going on here? Firstly you notice that the logic of actually searching for movies is separated into a doSearch(String,MovieFinder) method, to help us isolate the OSGi-specific code. Incidentally, the way we're performing the search is pretty stupid and inefficient, but that's not really important for the purposes of the tutorial. We only have two movies in our database anyway!

The interesting part is in the listByDirector(String name) method, which uses a ServiceTracker object to obtain a MovieFinder from the service registry. ServiceTracker is a very useful class which abstracts away a lot of unpleasant detail in the lowest levels of the OSGi API. However we still have to check whether the service was actually present. We assume that the ServiceTracker will be passed to us in our constructor.

Note that you may have seen elsewhere code that retrieves a service from the registry without using ServiceTracker . For example, it is possible to use the getServiceReference and getService calls on BundleContext . However the code you have to write is quite complex and it has to be careful to clear up after itself. In my opinion, there is very little benefit in dropping down to the low level API, and lots of problems with it. It's better to use ServiceTracker almost exclusively.

A good place to create a ServiceTracker is in the bundle activator. Copy this code into osgitut/movies/impl/MovieListerActivator.java :
package osgitut.movies.impl;
 
import java.util.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
import osgitut.movies.*;
 
public class MovieListerActivator implements BundleActivator {
 
    private ServiceTracker finderTracker;
    private ServiceRegistration listerReg;
 
    public void start(BundleContext context) throws Exception {
        // Create and open the MovieFinder ServiceTracker
        finderTracker = new ServiceTracker(context, MovieFinder.class.getName(), null);
        finderTracker.open();
 
        // Create the MovieLister and register as a service
        MovieLister lister = new MovieListerImpl(finderTracker);
        listerReg = context.registerService(MovieLister.class.getName(), lister, null);
 
        // Execute the sample search
        doSampleSearch(lister);
    }
 
    public void stop(BundleContext context) throws Exception {
        // Unregister the MovieLister service
        listerReg.unregister();
        
        // Close the MovieFinder ServiceTracker
        finderTracker.close();
    }
 
    private void doSampleSearch(MovieLister lister) {
        List movies = lister.listByDirector("Miyazaki");
        if(movies == null) {
            System.err.println("Could not retrieve movie list");
        } else {
            for (Iterator it = movies.iterator(); it.hasNext();) {
                Movie movie = (Movie) it.next();
                System.out.println("Title: " + movie.getTitle());
            }
        }
    }
}


Now this activator is starting to look interesting. Firstly in the start method it creates a ServiceTracker object, which is used by the MovieLister we just wrote. It then "opens" the ServiceTracker which tells it to start tracking instances of the MovieFinder service in the registry. Then it creates our MovieListerImpl object and registers it in the service registry under the interface name "MovieLister" . Finally, just for the sake of being able to see something interesting when we start the bundle, the activator runs a simple search against the MovieLister and prints the result.

We need to build and install this bundle. I'm not going to give full instructions this time -- you should be able to refer back to the previous installments and work it out. Remember you also need to create a manifest file, and it has to refer to the osgitut.movies.impl.MovieListerActivator class as its Bundle-Activator . Also your Import-Package line needs to include the three packages that we're importing from other bundles, namely org.osgi.framework , org.osgi.util.tracker and osgitut.movies .

Once you have installed MovieLister.jar into the Equinox runtime, you can start it. At that point you will see one of two messages, depending on whether the BasicMovieFinder bundle is still running from last time. If it's not running you will see:
osgi> start 2
Could not retrieve movie list

However if it is running you will see following:
osgi> start 2
Title: Spirited Away

By stopping and starting each bundle, you should be able to get either message to appear at will. And that is almost all for this installment, except remember I said that one of the things you can do when a service is not available is to wait for it? With the code we already have, this is actually trivial: simply change line 16 of MovieListerImpl to call waitForService(5000) on the ServiceTracker instead of getService() , and add a try/catch block for the InterruptedException .

This will cause the listByDirector() method to hang for up to 5000 milliseconds waiting for the MovieFinder service to appear. If a MovieFinder service is installed in that time -- or, of course, if it was already there -- then we will immediately get it an be able to use it.

Generally though I would advise against suspending threads like this. Particularly in this case, it could be dangerous because the listByDirector() method is actually called from the start method of our bundle activator, which was called from a framework thread. Activators are meant to return quickly, because a number of other things need to happen when a bundle is activated. In fact in the worst case we could cause a deadlock, because we are effectively entering a synchronized block on an object owned by the framework, which might already by locked by something else. The general guideline is never perform any long-running or blocking operations in a bundle activator start method, or in any code called directly from the framework.

In the next installment we will take a look at the mysterious third option for dealing with absent dependencies: "Don't exist in the first place". Stay tuned!
  Click to reply to this thread Reply
1. At 10:28 AM on Feb 23, 2007, BJ Hargrave Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

In many ServiceTracker examples, we do not see the call to ServiceTracker.close(). If one uses a ServiceTrackerCustomizer implementation, it may be important to call ServiceTracker.close so the customizer can be called at removingService for each tracked service to do any untrack processing. This could include persistently saving data or something. So I think it is always wise to show the close call in example code. Without the call to close, the framework will properly unregister the ServiceTracker's ServiceListener and unget any services being tracked when the bundle is stopped but removingService will not be called. In your example, that is OK since all the default removingService method implementation does is unget a tracked service.
  Click to reply to this thread Reply
2. At 12:25 PM on Feb 23, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Consuming a Service

Thanks BJ, you're right that it's an important step.

The example code I gave does actually close the tracker, but perhaps I should draw more attention to that in the surrounding text.
  Click to reply to this thread Reply
3. At 2:42 PM on Feb 23, 2007, BJ Hargrave Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

Oh. Somehow I missed that. Well... Nevermind. Move along... nothing to see here.
  Click to reply to this thread Reply
4. At 3:49 PM on Feb 23, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting Started with OSGi: Consuming a Service

Of course, normally you'd have the bundle.start() method open a tracker, bundle.stop() close a tracker, and then do (probably more than one) request whilst the bundle is alive. Since this code only shows the processing once at startup, this subtlety is missed.

Alex.
  Click to reply to this thread Reply
5. At 3:17 AM on Mar 28, 2007, Basten li Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

How can i look the MovieLister result (maybe call log information)? In fact, When i stop MovieFinder service, i can see this error information "Could not retrieve movie list".
  Click to reply to this thread Reply
6. At 11:17 PM on Mar 29, 2007, wtrichards Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

I have created the bundles. I think correctly to have a MovieListerInterface.jar (which has only the MovieLister interface) and a MovieLister.jar (which has the MovieListerImpl and MovieListerActivator)

The MovieListerInterface.mf looks like
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Movie Lister Interface
Bundle-SymbolicName: MovieLister
Bundle-Version: 1.0.0
Bundle-Activator: osgitut.movies.impl.MovieListerActivator
Import-Package: org.osgi.framework,org.osgi.util.tracker,osgitut.movies

Then MovieLister.mf looks like
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Movie Lister
Bundle-SymbolicName: MovieListerImpl
Bundle-Version: 1.0.0
Bundle-Activator: osgitut.movies.impl.MovieListerActivator
Import-Package: org.osgi.framework ,org.osgi.util.tracker,osgitut.movies

The bundles both install without errors.
In the Console when starting 3 the following error occurs
osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE system.bundle_3.2.2.R32x_v20070118
1 ACTIVE MoviesInterface_1.0.0
2 ACTIVE BasicMovieFinder_1.0.0
3 INSTALLED MovieLister_1.0.0
4 INSTALLED MovieListerImpl_1.0.0

osgi> start 3
org.osgi.framework.BundleException: The activator osgitut.movies.impl.MovieListe
rActivator for bundle MovieLister is invalid
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
ivator(AbstractBundle.java:141)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
leContextImpl.java:962)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
eHost.java:317)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
tBundle.java:256)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
art(FrameworkCommandProvider.java:239)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
execute(FrameworkCommandInterpreter.java:145)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
rameworkConsole.java:293)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
meworkConsole.java:278)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
rkConsole.java:213)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.ClassNotFoundException: osgitut.movies.impl.MovieListerActi
vator
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(Bundl
eLoader.java:402)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(Bundl
eLoader.java:347)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(De
faultClassLoader.java:83)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at org.eclipse.osgi.framework.internal.core.BundleLoader.loadClass(Bundl
eLoader.java:278)
at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleH
ost.java:227)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
ivator(AbstractBundle.java:134)
... 13 more
Nested Exception:
java.lang.ClassNotFoundException: osgitut.movies.impl.MovieListerActivator
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(Bundl
eLoader.java:402)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(Bundl
eLoader.java:347)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(De
faultClassLoader.java:83)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at org.eclipse.osgi.framework.internal.core.BundleLoader.loadClass(Bundl
eLoader.java:278)
at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleH
ost.java:227)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
ivator(AbstractBundle.java:134)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
leContextImpl.java:962)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
eHost.java:317)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
tBundle.java:256)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
art(FrameworkCommandProvider.java:239)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
execute(FrameworkCommandInterpreter.java:145)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
rameworkConsole.java:293)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
meworkConsole.java:278)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
rkConsole.java:213)
at java.lang.Thread.run(Thread.java:595)
Nested Exception:
java.lang.ClassNotFoundException: osgitut.movies.impl.MovieListerActivator
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(Bundl
eLoader.java:402)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(Bundl
eLoader.java:347)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(De
faultClassLoader.java:83)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at org.eclipse.osgi.framework.internal.core.BundleLoader.loadClass(Bundl
eLoader.java:278)
at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleH
ost.java:227)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
ivator(AbstractBundle.java:134)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
leContextImpl.java:962)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
eHost.java:317)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
tBundle.java:256)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
art(FrameworkCommandProvider.java:239)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
execute(FrameworkCommandInterpreter.java:145)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
rameworkConsole.java:293)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
meworkConsole.java:278)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
rkConsole.java:213)
at java.lang.Thread.run(Thread.java:595)

Starting 4 produces the following
osgi> start 4
Title: Spirited Away

osgi>

Would this be correct?
Wayne
  Click to reply to this thread Reply
8. At 4:13 AM on Mar 30, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Consuming a Service

Wayne,

It was not really necessary to split the interface and the implementation into two bundles, although there's no problem with that either.

The reason for the error appears to be that you have osgitut.movies.impl.MovieListerActivator as the activator for both the interface bundle ("MovieLister") and the implenentation bundle ("MovieListerImpl"). However the interface bundle doesn't contain the class osgitut.movies.impl.MovieListerActivator


Simply remove the Bundle-Activator line from the manifest of the interface bundle – you don't need an activator for a bundle that only exports API to other bundles.

Regards
Neil.
  Click to reply to this thread Reply
9. At 2:49 AM on Apr 12, 2007, wolverine.my Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

Hi!

Why the finderTrack.getSerive() returns null? Why do we want to check this while we already registered the service on the other side?

public List listByDirector(String name) {
MovieFinder finder = (MovieFinder) finderTrack.getService();
if(finder == null) {
return null;
} else {
return doSearch(name, finder);
}
}
  Click to reply to this thread Reply
10. At 3:20 AM on Apr 12, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Consuming a Service

Hi wolverine,

We have to check the return from getService() because the service could be registered or unregistered at any time.

Regards
Neil
  Click to reply to this thread Reply
11. At 9:04 AM on Apr 26, 2007, Cédric GAVA Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

Hi, and thank you for your tutorial

I feel a little bit confused between packages and bundles , as I thought that two different bundles shall be split into two different packages , and, on the other side, that one package shall contain only one bundle .

On your previous tutorial, I made the following bundle :
Bundle : MoviesInterface
Movie (package osgitut.movies)
MovieFinder (package osgitut.movies)

Bundle : BasicMovieFinder
BasicMovieFinderImpl (package osgitut.movies.impl)
BasicMovieFinderActivator (package osgitut.movies.impl)

At this point, everything was clear. But,
In this turorial, I create the following classes :
Bundle : MoviesInterface
MovieLister (package osgitut.movies)

Bundle : MovieLister ?
MovieListerImpl (package osgitut.movies.impl)
MovieListerActivator (package osgitut.movies.impl)

It's not possible to put MovieListerImpl/Activator and BasicMovieFinderImpl/Activator because there must be only one activator. So I create another Bundle : MovieLister.
But, according to your source, there are in the same package, regardind to java syntax : so, we can have many bundle in the same package.

Can you tell us more about this?
  Click to reply to this thread Reply
12. At 2:01 PM on Apr 26, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting Started with OSGi: Consuming a Service

It's a good question, but in fact, the same package can exist in multiple bundles. It's good practice (at times) to ensure that each bundle has its own package name, but that's just so that you can find/guess which bundle a class/package came from. This is referred to as 'split packages' in the OSGi/Equinox documentation.

One reason for split packages is that your bundles have been refactored but you need to keep the same code API. This happens in Eclipse, as some of the 'org.eclipse.core.runtime' packages have been moved from the runtime bundle into org.eclipse equinox.common, whilst keeping the same package name.

(If you do split packages, you should both Export-Package and Import-Package the split package name, by the way; that prevents weird classloading errors later)

Re: the activator; you're right, a bundle can only have one activator. However, it's fairly easy to set up code that allows you do run multiple pieces of code (as well as allowing you to merge the activators manually). For example:

public class MyActivator implements BundleActivator {
  public MyActivator() {
    a = new OtherActivator();
    b = new AnotherActivator();
    ...
  }
  public void start() {
    a.start();
    b.start();
    ...
  }
}


So, whilst you can only have a single Activator class, you can easily chain it to do other pieces of work.

Hope this helps,

Alex.
  Click to reply to this thread Reply
13. At 3:49 AM on Sep 20, 2007, dshitd Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

Hello Neil,

I got a problem when try the above sample.

My mf file content is:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Movie Lister
Bundle-SymbolicName: MovieLister
Bundle-Version: 1.0.0
Bundle-Activator: osgitut.movies.impl.MovieListerActivator
Import-Package: org.osgi.framework,org.osgi.util.tracker,osgitut.movies;version="[1.0.0,2.0.0)"

I packaged only those two Lister related classes and the mf into the MovieLister.jar, the MovieInterface.jar has also been updated with the MovieLister (the interface) in it.

But, if I run it in windows command line, it shows that:

java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357)
at java.lang.Class.getConstructor0(Class.java:2671)
at java.lang.Class.newInstance0(Class.java:321)
at java.lang.Class.newInstance(Class.java:303)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
ivator(AbstractBundle.java:136)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
leContextImpl.java:970)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
eHost.java:346)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
tBundle.java:260)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
tBundle.java:252)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
art(FrameworkCommandProvider.java:260)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
execute(FrameworkCommandInterpreter.java:145)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
rameworkConsole.java:291)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
meworkConsole.java:276)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
rkConsole.java:218)
at java.lang.Thread.run(Thread.java:595)

But, it works fine in the Eclipse envirment.... I would like to know why. Thanks!
  Click to reply to this thread Reply
14. At 8:35 AM on Oct 11, 2007, Divaa Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Consuming a Service

I had no any problem with the service registration example but with tracking service, i am get the following error message.
Error during the operation Error Invoking Method: org.osgi.framework.BundleException: java.lang.NullPointerException

com.prosyst.mbs.services.pmp.PMPException: Error Invoking Method: org.osgi.framework.BundleException: java.lang.NullPointerException
at com.prosyst.mbs.impl.services.pmp.Connection.invoke(Connection.java:317)
at com.prosyst.mbs.impl.services.pmp.RemoteMethodImpl.invoke(RemoteMethodImpl.java:66)
at com.prosyst.mc.impl.mbs.login.GatewayAdministratorImpl.startBundle(GatewayAdministratorImpl.java:246)
at com.prosyst.mc.impl.mbs.login.DeployedBundleImpl.start(DeployedBundleImpl.java:102)
at com.prosyst.mc.impl.mbs.mbsgam.events.GAMRemoteManager.startBundle(GAMRemoteManager.java:152)
at com.prosyst.mc.impl.mbs.mbsgam.events.GAMRemoteManager.run(GAMRemoteManager.java:111)
at java.lang.Thread.run(Unknown Source)

Please Help!!
  Click to reply to this thread Reply
15. At 4:27 PM on May 17, 2008, Frederic Conrotte Blooming Javalobby Member wrote:

Re: Getting Started with OSGi: Consuming a Service

In my case, to get the MovieLister bundle starting properly, I had first to repackage the MoviesInterfaces bundle so that it also contains the osgitut.movies.MovieLister class:

jar -cfm MoviesInterface.jar MoviesInterface.mf osgitut/movie

Otherwise i had the following exception on MovieLister bundle start:

java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)

I think it's coming from the confusion that the same package (osgitut.movies) is :
- defined in both MoviesInterface and MovieLister bundles.
- exported by MoviesInterface
- imported by MovieLister

If you check OSGi R4 specs, on page 52-278, section 3.8.4 Overall Search Order, you will read:

"3. If the class is in a package that is imported using Import-Package or was imported dynamically in a previous load, then the request is delegated to the exporting bundle’s class loader; (...) If the request is delegated to an exporting class loader and the class or resource is not found, then the search terminates and the request fails"

In our case the Framework resolves the MovieLister.mf "Import-Package: osgitut.movies" with the MoviesInterface.mf "Export-Package: osgitut.movies"

then the osgitut.movies.MovieLister.class has to be package with exporter MoviesInterface or the class loading request fails.

thread.rss_message