You are on page 1of 5

Getting Started with OSGi: Registering a Service

At 10:26 AM on Feb 16, 2007, Neil Bartlett Javalobby Regulars wrote:

Welcome back to the EclipseZone OSGi mini-series. Finally, we're ready to get on to services. In my opinion, the service layer is
the most exciting part of OSGi, so these next few installments should be fun.

Last time we looked at the example of a MovieFinder interface, which we said would be used by a MovieLister to search for
movies. In fact you may recognize this example -- it is from Martin Fowler's famous paper on "Dependency Injection", also
known as "Inversion of Control" or IoC.

Recall the problem that IoC tries to solve. A MovieLister doesn't particularly care where the raw movie data comes from, so we
use the MovieFinder interface to hide such details from it. The idea is we can then substitute alternative implementations of
MovieFinder , such as one that goes to a database or even one that calls an Amazon Web Service, since MovieLister only
depends on the interface, not any particular implementation.

So far so good, but at some point we have to actually give a concrete implementation of MovieFinder to MovieLister . We do this
by having an external container "push" a suitable object into it, rather than letting MovieLister go out and call a lookup method.
Hence the term "Inversion of Control". Many such containers have been developed, for example PicoContainer, HiveMind,
Spring, and even EJB 3.0. However there is one limiting factor of all these containers to date: they are mostly static. Once a
MovieFinder is given to a MovieLister , it tends to be associated for the lifetime of the JVM.

OSGi also allows us to implement the IoC pattern, but in a dynamic way. It should be possible to dynamically supply
implementations of MovieFinder to MovieLister and later remove them. Then we can hot-swap from an application that looks up
movies in a flat text file to an application that looks them up with Amazon Web Services.

It is the Service Layer that helps us do this. Quite simply, we register a MovieFinder as a Service in the Service Registry. Later
the MovieLister can be supplied with that MovieFinder Service. A Service therefore is nothing more than a Java object -- a
POJO, if you will -- and it is registered under the name of a Java interface (a POJI?).

This time around, we will just look at registering the service with the registry. Later we will look at how to get the service out of
the registry and supplied to a MovieLister .

We're going to add the BasicMovieFinder bundle that we built last time. We don't need to modify any existing classes, we just
need to add a bundle activator. So copy this into osgitut/movies/impl/BasicMovieFinderActivator.java :

package osgitut.movies.impl;

import org.osgi.framework.*;

import osgitut.movies.*;
import java.util.Properties;
import java.util.Dictionary;

public class BasicMovieFinderActivator implements BundleActivator {


private ServiceRegistration registration;

public void start(BundleContext context) {


MovieFinder finder = new BasicMovieFinderImpl();

Dictionary props = new Properties();


props.put("category", "misc");

registration = context.registerService(
MovieFinder.class.getName(),
finder, props);
}

public void stop(BundleContext context) {


registration.unregister();
}
}

Now replace the content of BasicMovieFinder.mf :

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Basic Movie Finder
Bundle-SymbolicName: BasicMovieFinder
Bundle-Version: 1.0.0
Bundle-Activator: osgitut.movies.impl.BasicMovieFinderActivator
Import-Package: org.osgi.framework,
osgitut.movies;version="[1.0.0,2.0.0)"

There are two things added to this manifest since last time. First is the Bundle-Activator line, which tells the framework about
the new activator for our bundle -- we didn't need one last time. Also I have added org.osgi.framework to the imported packages.
As our previous version of the bundle didn't interact with the framework, it didn't need to import the OSGi API packages.

Now you can rebuild BasicMovieFinder.jar :

> javac -classpath equinox.jar:MoviesInterface.jar osgitut/movies/impl/*.java


> jar cfm BasicMovieFinder.jar BasicMovieFinder.mf osgitut/movies/impl/*.class

Back in the OSGi console, you should still have BasicMovieFinder.jar installed from last time. So you just need to tell OSGi to
update the bundle, by typing update N , where N is the numeric ID of the bundle (which you have found using ss ). Now start
the bundle with the command start N and you should see... very little happen.

Actually we've just registered our first service with the OSGi service registry, but unfortunately there's nobody on the "other
end", so the registration doesn't produce any visible effect. If we want to reassure ourselves that our code has actually done
something, we're going to have to go digging, and we do that with the following command:

services (objectClass=*MovieFinder)

We should see the following output:

{osgitut.movies.MovieFinder}={category=misc, service.id=22}
Registered by bundle: file:BasicMovieFinder.jar [4]
No bundles using service.

Great, our service is registered! And I'd love to go on and tell you how to lookup that service and use it in another bundle, but
that will have to wait until another day. In the meantime, see what you can do with the services command. For starters try typing
services without the expression in parentheses afterwards -- that was actually a filter which reduced the number of services
displayed to just the one we were interested in. Without the filter you will see all of the registered services. There are a
surprisingly large number of them!

16 replies so far ( R Post your own) Click Here!

ClReply
1. At 11:19 AM on Feb 18, 2007, Jin Blooming Javalobby Member wrote:

Re: Getting Started with OSGi: Registering a Service

Neil:
Good OSGi series articles! Is it possible to add other series articles' links in some place of each series' one? This allows
readers to navigate between those series more conveniently.
Best regards,
Jin
ClReply
3. At 12:44 PM on Feb 18, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Registering a Service


Jin,

Funny you should ask...

http://neilbartlett.name/blog/osgi-articles/
I will be keeping the links on that page updated as each new article comes out.

Glad you're enjoying them!


Neil
ClReply
4. At 4:57 AM on Feb 19, 2007, Jin Blooming Javalobby Member wrote:

Re: Getting Started with OSGi: Registering a Service


Neil, good blog, thanks^_^
ClReply
5. At 6:12 AM on Mar 4, 2007, Richard Mahn Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Registering a Service

Great set of articles !


Especially for someone like me who is just learning about the insides of eclipse & equinox.

I think there is a small typo.


In
> javac -classpath equinox.jar:MoviesInterface.jar osgitut/movies/impl/*.java
> jar cfm BasicMovieFinder.jar BasicMovieFinder.mf osgitut/movies/impl/*.class

in order to get the compile to work I had to change the ":" in the first line to a ";".

Also I'm using 3.3M5eh, with little experience on other versions. What I'm seeing is that I have to invoke the equinox.jar
with a "-clean" to get an osgi with only a bundle 0 showing with a ss. I don't know if this is a bug in 3.3M5eh or a feature
since the version of equinox you used in the articles.
ClReply
6. At 9:11 AM on Mar 4, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Registering a Service


Hi Richard,

It's not exactly a typo. You have to use colons and forward slashes on Linux, Mac OS etc, but semicolons and backslashes
on Windows. It was my assumption that most experienced Java developers would have made the translation automatically
:-)

You're right that invoking with -clean brings you back to a clean slate with none of the previously installed bundles present.
However it isn't really necessary to do that in order to follow the tutorial. Unfortunately, the output you see from the ss
command will inevitably diverge from what I get and what anybody else will get.

Regards
Neil
ClReply
7. At 11:58 AM on Mar 16, 2007, Amine C. Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Registering a Service

I went through this tutorial, but when I start the service (BasicMovieFinder) I am getting ClassNotFoundException for osgi
classes. It look the osgi doesn't find its own classes?

org.osgi.framework.BundleException: The activator osgitut.movies.impl.BasicMovieFinderActivator for bundle


BasicMovieFinder is invalid
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleActivator(AbstractBundle.java:141)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:962)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:317)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:256)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._start(FrameworkCommandProvider.java:239)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at
org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:145)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:293)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(FrameworkConsole.java:278)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:213)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NoClassDefFoundError: org/osgi/framework/BundleActivator
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.defineClass(DefaultClassLoader.java:160)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:498)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findClassImpl(ClasspathManager.java:468)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClassImpl(ClasspathManager.java:427)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:410)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:188)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findLocalClass(BundleLoader.java:334)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:386)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:347)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:83)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.eclipse.osgi.framework.internal.core.BundleLoader.loadClass(BundleLoader.java:278)
at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:227)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleActivator(AbstractBundle.java:134)
... 13 more
ClReply
8. At 12:37 PM on Mar 16, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Registering a Service


Hi Amine,

Could you check whether the package org.osgi.framework is listed in the Import-Package section of your bundle
manifest?

Regards,
Neil
ClReply
9. At 9:30 PM on Mar 18, 2007, Amine C. Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Registering a Service

Neil,

Yes that was the problem. When I updated "BasicMovieFinder.mf" I wrote it in the wrong path. Thanks.

Amine.
ClReply
10. At 7:08 PM on Mar 28, 2007, wtrichards Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Registering a Service


Neil,
I think that this tutorial is helping me understand the OSGI much better that just reading the specs.
However, I am getting the same problem as Amine. I have checked the pathing in the BasicMovieFinder.mf. It looks like
the following:
BasicMovieFinder.mf

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Basic Movie Finder
Bundle-SymbolicName: BasicMovieFinder
Bundle-Version: 1.0.0
Bundle-Activator: osgitut.movies.impl.BasicMovieFinderActivator
Import-Package: org.osgi.framework,
osgitut.movies;version="[1.0.0,2.0.0)"

What else is there to check? Is there a software bundle that has all the source files in it that could be downloaded. I might
have as spelling mistake some where.
Any help appreciated.
Wayne
ClReply
11. At 4:01 AM on Mar 29, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting Started with OSGi: Registering a Service


The formatting of the post may be screwing it up, but you need at least one space for the 'osgitut.movies' line below. You
can also put them on one line e.g.

Import:Package:org.osgi.framework,osgitut.movies

Alex.
ClReply
12. At 10:43 PM on Mar 29, 2007, wtrichards Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Registering a Service

That seems to fix the problem. Spaces in the paramater line due make a difference. Thanks
Wayne
ClReply
13. At 3:58 AM on Apr 12, 2007, wolverine.my Javalobby Newcomers wrote:

Re: Getting Started with OSGi: Registering a Service


If I have a service which will loop forever... e.g. monitoring a directory until there is one input file available; Do we need
to start another thread for this process?
ClReply
14. At 4:16 AM on Apr 12, 2007, Neil Bartlett Javalobby Regulars wrote:

Re: Getting Started with OSGi: Registering a Service

wolverine,

Yes. Whenever the OSGi framework calls into your bundle, e.g. the BundleActivator.start() method, it expects you to
return control to it in a reasonable amount of time.

You should therefore avoid writing infinite loops or doing anything that might block indefinitely, e.g. performing blocking
I/O or monitor acquisition without a timeout. Otherwise you risk starving another bundle.

Neil
ClReply
15. At 4:39 AM on Apr 12, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting Started with OSGi: Registering a Service

NB if this happens, the bundle's state is shown as STARTING in the console. Depending on how many threads that the
framework kicks off to start bundles, if you have too many of them it may prevent others from starting.

Of course, there's nothing to stop you starting off another Thread in the start() method; in fact, a number of things do this
(e.g. the Jetty web server). You should check, though, that when the activator's stop() method is called, that it terminates
any such started thread in a friendly way.

Alex.

Replies: 16 - Pages: 2 [ 1 2 | Next ] Threads: [ Previous | Next ]

thre

N P N N N U H R
Get Firefox! Powered by Jive Software Powered by Caucho Resin!
Eclipse(TM) is a registered trademark of the Eclipse Foundation

You might also like