4. Services
4.2. Registering a Service
through direct usage of the OSGi Service Registry.
In this chapter though, we look at the nuts and bolts of services, in order to gain a firm foundation when advancing to higher-level abstractions.
4.2. Registering a Service
Recall that in Section 3.4 we created an implementation of the Mailbox in- terface. However, as its package was not exported, there was no way for any other bundle to actually use that implementation! By registering an instance of the FixedMailbox class as a service, other bundles can access the object without needing to have a dependency on its class.
Registering a service is an example of interaction with the OSGi framework, and as always we need to have aBundleContextin order to do that. Therefore we need to write an implementation of BundleActivatoras shown in Listing
4.2.
Listing 4.2 Welcome Mailbox Activator 1 p a c k a g e o r g.o s g i.b o o k.r e a d e r.f i x e d m a i l b o x; 3 i m p o r t o r g.o s g i.b o o k.r e a d e r.a p i.M a i l b o x; 4 i m p o r t o r g.o s g i.f r a m e w o r k.B u n d l e A c t i v a t o r; 5 i m p o r t o r g.o s g i.f r a m e w o r k.B u n d l e C o n t e x t; 7 p u b l i c c l a s s W e l c o m e M a i l b o x A c t i v a t o r i m p l e m e n t s B u n d l e A c t i v a t o r { 9 p u b l i c v o i d s t a r t(B u n d l e C o n t e x t c o n t e x t) t h r o w s E x c e p t i o n { 10 M a i l b o x m b o x = n e w F i x e d M a i l b o x( ) ; 11 c o n t e x t.r e g i s t e r S e r v i c e(M a i l b o x.c l a s s.g e t N a m e( ) , m b o x, n u l l) ; //1 12 } 14 p u b l i c v o i d s t o p(B u n d l e C o n t e x t c o n t e x t) t h r o w s E x c e p t i o n { 15 } 16 }
The first two lines of code simply create a mailbox with some hard-coded messages in it. The line marked //1 is the one that calls the framework to register the mailbox as a service, by calling theregisterServicemethod with three parameters:
1. The interface name under which the service is to be registered. This should be the name of a Java interface class, and will be the primary means by which clients will find the service.
2. Theservice objectitself, i.e. the mailbox object that was instantiated in the previous lines. This object must implement the interface named in the previous parameter.
3. A set of service properties, which here has been left blank by passing null. We will look at service properties shortly.
We say that a service object is registered “under” an interface name, because for consumers the most important fact about our service is the interface it implements. In fact, just as Java objects can be implementations of multiple interfaces, we can register a service under multiple interface names, by calling a variant of theregisterServicemethod that takes an array ofStrings as its first parameter. When we do this, consumers can find the service using any one of those interface names. There is still just one service object registered: the additional entries can be considered aliases.
Note that we could have passed a literal String for the interface name i.e., context.registerService("org.osgi.book.reader.api.Mailbox",mbox,null). However this is not good practice, because the class or package name might change in the future, for example when the code is refactored. It is better to use Mail- box.class.getName()because most IDEs can automatically update the im- port statement — and even if we are not using an IDE, we will get a helpful compilation error if we change the package name thatMailboxlives in without updating this source file.
Listing 4.3Bnd Descriptor for the Welcome Mailbox Bundle # w e l c o m e _ m a i l b o x.b n d
P r i v a t e−P a c k a g e: o r g.o s g i.b o o k.r e a d e r.f i x e d m a i l b o x B u n d l e−A c t i v a t o r: \
o r g.o s g i.b o o k.r e a d e r.f i x e d m a i l b o x.W e l c o m e M a i l b o x A c t i v a t o r
Let’s build this bundle and see what effect it has. Thebnddescriptor should look like the one in Listing 4.3. After building, installing and starting the bundle, try typingservices. You will see a long list of results, but somewhere within it you should see this:
o s g i> s e r v i c e s . . . {o r g.o s g i.b o o k.r e a d e r.a p i.M a i l b o x}={s e r v i c e.i d=24} R e g i s t e r e d b y b u n d l e: w e l c o m e _ m a i l b o x _ 0. 0 . 0 [ 2 ] N o b u n d l e s u s i n g s e r v i c e. . . .
This shows we have successfully registered a service under theMailboxinter- face, and it has been assigned a service ID of 24 — again, you will probably get a different ID when you run this for yourself. Incidentally you can try the services command on its own, without a bundle ID parameter, which will give you a list of all registered services by all bundles, although showing less detail.