Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Example

...

2

...

-

...

Dictionary

...

Service

...

Bundle

...

This

...

example

...

creates

...

a

...

bundle

...

that

...

implements

...

an

...

OSGi

...

service.

...

Implementing

...

an

...

OSGi

...

service

...

is

...

a

...

two-step

...

process,

...

first

...

we

...

must

...

define

...

the

...

interface

...

of

...

the

...

service

...

and

...

then

...

we

...

must

...

define

...

an

...

implementation

...

of

...

the

...

service

...

interface.

...

In

...

this

...

particular

...

example,

...

we

...

will

...

create

...

a

...

dictionary

...

service

...

that

...

we

...

can

...

use

...

to

...

check

...

if

...

a

...

word

...

exists,

...

which

...

indicates

...

if

...

the

...

word

...

is

...

spelled correctly

...

or

...

not.

...

First,

...

we

...

will

...

start

...

by

...

defining

...

a

...

simple

...

dictionary

...

service

...

interface

...

in

...

a

...

file

...

called

...

DictionaryService.java:

Code Block


/*
 * Apache Felix OSGi tutorial.
**/

package tutorial.example2.service;

/**
 * A simple service interface that defines a dictionary service.
 * A dictionary service simply verifies the existence of a word.
**/
public interface DictionaryService
{
    /**
     * Check for the existence of a word.
     * @param word the word to be checked.
     * @return true if the word is in the dictionary,
     *         false otherwise.
    **/
    public boolean checkWord(String word);
}

The

...

service

...

interface

...

is

...

quite

...

simple,

...

with

...

only

...

one

...

method

...

that

...

needs

...

to

...

be

...

implemented.

...

Notice

...

that

...

we

...

put

...

the

...

service

...

interface

...

in

...

the

...

package

...

tutorial.example2.service,

...

instead

...

of

...

just

...

putting

...

it

...

in

...

tutorial.example2.

...

We

...

did

...

this

...

because

...

we

...

need

...

to

...

share

...

the

...

interface

...

definition

...

with

...

other

...

bundles,

...

therefore

...

it

...

is

...

better

...

to

...

separate

...

service

...

interfaces

...

that

...

need

...

to

...

be

...

shared

...

from

...

code

...

that

...

does

...

not

...

need

...

to

...

be

...

shared.

...

Such

...

an

...

approach

...

ensures

...

a

...

strong

...

separation

...

between

...

interface

...

and

...

implementation.

...

In

...

the

...

following

...

source

...

code,

...

the

...

bundle

...

uses

...

its

...

bundle

...

context

...

to

...

register

...

the

...

dictionary

...

service.

...

We

...

implement

...

the

...

dictionary

...

service

...

as

...

an

...

inner

...

class

...

of

...

the

...

bundle

...

activator

...

class,

...

but

...

we

...

could

...

have

...

also

...

put

...

it

...

in

...

a

...

separate

...

file.

...

The

...

source

...

code

...

for

...

our

...

bundle

...

is

...

as

...

follows

...

in

...

a

...

file

...

called

...

Activator.java:

Code Block


/*
 * OSGiApache and Gravity Service Binder tutorial.
 * Copyright (c) 2003  Richard S. Hall
 * http://oscar-osgi.sourceforge.netFelix OSGi tutorial.
**/

package tutorial.example2;

import java.util.Properties;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceEvent;

import tutorial.example2.service.DictionaryService;

/**
 * This class implements a simple bundle that uses the bundle
 * context to register an English language dictionary service
 * with the OSGi framework. The dictionary service interface is
 * defined in a separate class file and is implemented by an
 * inner class.
**/
public class Activator implements BundleActivator
{
    /**
     * Implements BundleActivator.start(). Registers an
     * instance of a dictionary service using the bundle context;
     * attaches properties to the service that can be queried
     * when performing a service look-up.
     * @param context the framework context for the bundle.
    **/
    public void start(BundleContext context)
    {
        Properties props = new Properties();
        props.put("Language", "English");
        context.registerService(
            DictionaryService.class.getName(), new DictionaryImpl(), props);
    }

    /**
     * Implements BundleActivator.stop(). Does nothing since
     * the framework will automatically unregister any registered services.
     * @param context the framework context for the bundle.
    **/
    public void stop(BundleContext context)
    {
        // NOTE: The service is automatically unregistered.
    }

    /**
     * A private inner class that implements a dictionary service;
     * see DictionaryService for details of the service.
    **/
    private static class DictionaryImpl implements DictionaryService
    {
        // The set of words contained in the dictionary.
        String[] m_dictionary =
            { "welcome", "to", "the", "osgi", "tutorial" };

        /**
         * Implements DictionaryService.checkWord(). Determines
         * if the passed in word is contained in the dictionary.
         * @param word the word to be checked.
         * @return true if the word is in the dictionary,
         *         false otherwise.
        **/
        public boolean checkWord(String word)
        {
            word = word.toLowerCase();

            // This is very inefficient
            for (int i = 0; i < m_dictionary.length; i++)
            {
                if (m_dictionary[i].equals(word))
                {
                    return true;
                }
            }
            return false;
        }
    }
}

Note

...

that

...

we

...

do

...

not

...

need

...

to

...

unregister

...

the

...

service

...

in

...

the

...

stop()

...

method,

...

because

...

the

...

OSGi

...

framework

...

will

...

automatically

...

do

...

so

...

for

...

us.

...

The

...

dictionary

...

service

...

that

...

we

...

have

...

implemented

...

is

...

very

...

simple;

...

its

...

dictionary

...

is

...

a

...

static

...

array

...

of

...

only

...

five

...

words,

...

so

...

this

...

solution

...

is

...

not

...

optimal

...

and

...

is

...

only

...

intended

...

for

...

educational

...

purposes.

...

We

...

must

...

create

...

a

...

manifest.mf

...

file

...

that

...

contains

...

the meta-data for our bundle;

...

the

...

manifest

...

file

...

contains

...

the

...

following:

No Format


Bundle-Activator: tutorial.example2.Activator
Export-Package: tutorial.example2.service
Bundle-Name: English dictionary
Bundle-Description: A bundle that registers an English dictionary service
Bundle-Vendor: Richard Hall
Bundle-Version: 1.0.0

As

...

before,

...

much

...

of the meta-data in the manifest file above is for human consumption. We specify which class is used to activate our bundle via the Bundle-Activator attribute (this is the class that implements the BundleActivator interface) and also specify that our bundle exports a shared package using the Export-Package attribute. The Export-Package attribute makes it possible for other bundles to import our dictionary service interface.

To compile our source code, we need the felix.jar file (found in Felix' bin directory) in our class path. We compile the source file using a command like:

No Format

 the metadata in the manifest file above is for human consumption. We specify which class implements the Bundle-Activator interface and also specify that our bundle exports a shared package using the Export-Package attribute. This attribute makes it possible for other bundles to import our dictionary service interface.

To compile our source code, we need to have the osgi.jar file (found in Oscar's lib directory) in our class path. We compile the source file using a command like:

    javac -d c:\classes *.java

This

...

command

...

compiles

...

all

...

source

...

files

...

and

...

outputs

...

the

...

generated

...

classes

...

into

...

a

...

subdirectory

...

of

...

the

...

c:\classes

...

directory;

...

this

...

subdirectory

...

is

...

tutorial\example2,

...

named

...

after

...

the

...

package

...

we

...

specified

...

in

...

the

...

source

...

file.

...

For

...

the

...

above

...

command

...

to

...

work,

...

the

...

c:\classes

...

directory

...

must

...

exist.

...

After

...

compiling,

...

we

...

need

...

to

...

create

...

a

...

JAR

...

file

...

containing

...

the

...

generated

...

package

...

directories.

...

We

...

will

...

also

...

add

...

our

...

manifest

...

file

...

that

...

contains

...

the

...

bundle's

...

meta-data to the JAR file.

...

To

...

create

...

the

...

JAR

...

file,

...

we

...

issue

...

the

...

command:

No Format



    jar cfm example2.jar manifest.mf -C c:\classes tutorial\example2

This

...

command

...

creates

...

a

...

JAR

...

file

...

using

...

the

...

manifest

...

file

...

we

...

created

...

and

...

includes

...

all

...

of

...

the

...

classes

...

in

...

the

...

tutorial\example2

...

directory

...

inside

...

of

...

the

...

c:\classes

...

directory.

...

Once

...

the

...

JAR

...

file

...

is

...

created,

...

we

...

are

...

ready

...

to

...

install

...

and

...

start

...

the

...

bundle.

...

To

...

run

...

Felix,

...

we

...

follow

...

the

...

instructions

...

described

...

in

...

usage.html.

...

When

...

we

...

start

...

Felix,

...

it

...

asks

...

for

...

a

...

profile

...

name,

...

we

...

will

...

put

...

all

...

of

...

our

...

bundles

...

in

...

a

...

profile

...

named

...

tutorial.

...

After

...

running

...

Felix,

...

we

...

should

...

make

...

sure

...

that

...

the

...

bundle

...

from

...

Example

...

1

...

is

...

active.

...

We

...

can

...

use

...

the

...

Felix ps

...

shell

...

command

...

to

...

get

...

a

...

list

...

of

...

all

...

bundles,

...

their

...

state,

...

and

...

their

...

bundle

...

identifier

...

number.

...

If

...

the

...

Example

...

1

...

bundle

...

is

...

not

...

active,

...

we

...

should

...

start

...

the

...

bundle

...

using

...

the

...

start

...

command

...

and

...

the

...

bundle's

...

identifier

...

number

...

that

...

is

...

displayed

...

by

...

the

...

ps

...

command.

...

Now

...

we

...

can

...

install

...

and

...

start

...

our

...

dictionary

...

service

...

bundle.

...

Assuming

...

that

...

we

...

created

...

our

...

bundle

...

in

...

the

...

directory

...

c:\tutorial,

...

we

...

can

...

install

...

and

...

start

...

it

...

in

...

Felix'

...

shell

...

using

...

the

...

following

...

command:

No Format



    start file:/c:/tutorial/example2.jar

The

...

above

...

command

...

installs

...

and

...

starts

...

the

...

bundle

...

in

...

a

...

single

...

step;

...

it

...

is

...

also

...

possible

...

to

...

install

...

and

...

start

...

the

...

bundle

...

in

...

two

...

steps

...

by

...

using

...

the

...

Felix install

...

and

...

start

...

shell

...

commands.

...

To

...

stop

...

the

...

bundle,

...

use

...

the

...

Felix stop

...

shell

...

command.

...

If

...

the

...

bundle

...

from

...

Example

...

1

...

is

...

still

...

active,

...

then

...

we

...

should

...

see

...

it

...

print

...

out

...

the

...

details

...

of

...

the

...

service

...

event

...

it

...

receives

...

when

...

our

...

new

...

bundle

...

registers

...

its

...

dictionary

...

service.

...

Using

...

the

...

Felix shell

...

ps

...

command

...

to

...

get

...

the

...

bundle

...

identifier

...

number

...

for

...

our

...

dictionary

...

service

...

bundle

...

and

...

we

...

can

...

stop

...

and

...

restart

...

it

...

at

...

will

...

using

...

the

...

stop

...

and

...

start

...

commands,

...

respectively.

...

Each

...

time

...

we

...

start

...

and

...

stop

...

our

...

dictionary

...

service

...

bundle,

...

we

...

should

...

see

...

the

...

details

...

of

...

the

...

associated

...

service

...

event

...

printed

...

from

...

the

...

bundle

...

from

...

Example

...

1.

...

In

...

Example

...

3,

...

we

...

will

...

create

...

a

...

client

...

for

...

our

...

dictionary

...

service.

...

To

...

exit

...

Felix,

...

we

...

use

...

the

...

shutdown

...

command.

...