SlideShare uma empresa Scribd logo
1 de 98
Baixar para ler offline
Developing Modular and
Extensible Systems using
OSGi
Alexandre de Alves, M.Sc.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Systems using OSGi
✤ Oracle GlassFish Application Server
✤ Oracle Complex Event Processing Server
✤ IBM Websphere
✤ (Redhat) JBoss Application Server
✤ SAP NetWeaver (in progress)
✤ Apache ServiceMix
✤ Apache Camel
✤ Apache Karaf
✤ Apache Sling
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
✤ Data encapsulation
✤ Dealing with changes
✤ Extensibility
✤ Building infrastructures
Agenda
Modularization Grade
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Data Encapsulation
“Information hiding achieves changeability,
comprehensibility, independent development”
- D. Parnas, 1972
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Data Encapsulation
✤ As brilliantly elaborated by D. Parnas in 1972
✤ The more code that is exposed, the more tests that are needed.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
public class Printer {
public void print(String message) {
System.out.println(message);
}
}
public class PrinterClient {
public void printMyMessage() {
new Printer().print("Hello World");
}
}
Simple example...
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
public class Printer {
public void print(String message) {
System.out.println(message);
}
}
public class PrinterClient {
public void printMyMessage() {
new Printer().print("Hello World");
}
}
Simple example...
Modules and information hiding
Let’s share this code with other Java clients. Create a Pri
imports the Printer class and invokes it:
package manning.osgi.helloworld.client;
import manning.osgi.helloworld.Printer;
public class PrinterClient {
public void printMyMessage() {
new Printer().print("Hello World");
}
}
Figure 2.1 demonstrates this interaction.
NOTE This book attempts to be goal oriented. Rather tha
technology for the technology’s sake, the discussion of a t
print(String message)
Printer
printMyMessage()
PrinterClientprint()
Figure 2.1
class invok
the Print
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
public class Printer {
public void print(String message) {
System.out.println(message);
}
}
public class PrinterClient {
public void printMyMessage() {
new Printer().print("Hello World");
}
}
Simple example...
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Objective
✤ Our goal is to minimize the number of exposed
interfaces
✤ For example, expose print() and not
printMyMessage()
Other Classesprint()
Printer
printMyMessage()
PrinterClientprint()
Other classes
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Modularization
package manning.osgi.helloworld;
public class Printer {
public void print(String message) {
System.out.println(message);
}
}
package manning.osgi.helloworld.client;
import manning.osgi.helloworld;
public class PrinterClient {
public void printMyMessage() {
new Printer().print("Hello World");
}
}
ld is exporting all of its public classes located in the
ld.
undle uses the manifest header Import-Package:
sgi.client
elloworld
t is importing all public classes in the package
Printer
helloworld
PrinterClient
helloworld.client
orld is exporting all of its public classes located in the
orld.
bundle uses the manifest header Import-Package:
osgi.client
helloworld
nt is importing all public classes in the package
e
d
n
-
r
d
Printer
helloworld
PrinterClient
helloworld.client
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Modules in OSGi
✤ A module in OSGi is called bundle
✤ A bundle is formally defined as:
✤ A JAR file
✤ OSGi-specific manifest header entries
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Modules in OSGi
CHAPTER 2 An OSGi framework primer
In OSGi, you accomplish this by having the provider bundle export the Java packages
that are meant to be shared, and then have the consumer bundle import the Java
packages that it needs.
To export Java packages, a bundle uses the manifest header Export-Package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exporting all of its public classes located in the
package manning.osgi.helloworld.
To import a Java package, a bundle uses the manifest header Import-Package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importing all public classes in the package
manning.osgi.helloworld.
As should be clear, we have
two bundles, helloworld and
helloworld.client, as shown in
figure 2.3. The bundle hello-
Printer
helloworld
PrinterClient
helloworld.client
20 CHAPTER 2 An OSGi framew
In OSGi, you accomplish this by having the pro
that are meant to be shared, and then have
packages that it needs.
To export Java packages, a bundle uses the
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exportin
package manning.osgi.helloworld.
To import a Java package, a bundle uses the
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importin
manning.osgi.helloworld.
orld is exporting all of its public classes located in the
orld.
bundle uses the manifest header Import-Package:
.osgi.client
.helloworld
nt is importing all public classes in the package
e
d
n
-
r
d
-
of
problem? That is, have we prohibited other classes
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
the bundle helloworld is exporting all of its public classes located in the
ning.osgi.helloworld.
t a Java package, a bundle uses the manifest header Import-Package:
rsion: 1.0
festVersion: 2
olicName: manning.osgi.client
age: manning.osgi.helloworld
helloworld.client is importing all public classes in the package
i.helloworld.
d be clear, we have
s, helloworld and
client, as shown in
The bundle hello-
udes the Printer
bundle helloworld
ludes the Printer-
which makes use of
class.
solved our initial problem? That is, have we prohibited other classes
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Modules in OSGi
CHAPTER 2 An OSGi framework primer
In OSGi, you accomplish this by having the provider bundle export the Java packages
that are meant to be shared, and then have the consumer bundle import the Java
packages that it needs.
To export Java packages, a bundle uses the manifest header Export-Package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exporting all of its public classes located in the
package manning.osgi.helloworld.
To import a Java package, a bundle uses the manifest header Import-Package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importing all public classes in the package
manning.osgi.helloworld.
As should be clear, we have
two bundles, helloworld and
helloworld.client, as shown in
figure 2.3. The bundle hello-
Printer
helloworld
PrinterClient
helloworld.client
20 CHAPTER 2 An OSGi framew
In OSGi, you accomplish this by having the pro
that are meant to be shared, and then have
packages that it needs.
To export Java packages, a bundle uses the
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exportin
package manning.osgi.helloworld.
To import a Java package, a bundle uses the
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importin
manning.osgi.helloworld.
orld is exporting all of its public classes located in the
orld.
bundle uses the manifest header Import-Package:
.osgi.client
.helloworld
nt is importing all public classes in the package
e
d
n
-
r
d
-
of
problem? That is, have we prohibited other classes
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
the bundle helloworld is exporting all of its public classes located in the
ning.osgi.helloworld.
t a Java package, a bundle uses the manifest header Import-Package:
rsion: 1.0
festVersion: 2
olicName: manning.osgi.client
age: manning.osgi.helloworld
helloworld.client is importing all public classes in the package
i.helloworld.
d be clear, we have
s, helloworld and
client, as shown in
The bundle hello-
udes the Printer
bundle helloworld
ludes the Printer-
which makes use of
class.
solved our initial problem? That is, have we prohibited other classes
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Modules in OSGi
CHAPTER 2 An OSGi framework primer
In OSGi, you accomplish this by having the provider bundle export the Java packages
that are meant to be shared, and then have the consumer bundle import the Java
packages that it needs.
To export Java packages, a bundle uses the manifest header Export-Package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exporting all of its public classes located in the
package manning.osgi.helloworld.
To import a Java package, a bundle uses the manifest header Import-Package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importing all public classes in the package
manning.osgi.helloworld.
As should be clear, we have
two bundles, helloworld and
helloworld.client, as shown in
figure 2.3. The bundle hello-
Printer
helloworld
PrinterClient
helloworld.client
20 CHAPTER 2 An OSGi framew
In OSGi, you accomplish this by having the pro
that are meant to be shared, and then have
packages that it needs.
To export Java packages, a bundle uses the
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exportin
package manning.osgi.helloworld.
To import a Java package, a bundle uses the
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importin
manning.osgi.helloworld.
orld is exporting all of its public classes located in the
orld.
bundle uses the manifest header Import-Package:
.osgi.client
.helloworld
nt is importing all public classes in the package
e
d
n
-
r
d
-
of
problem? That is, have we prohibited other classes
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
the bundle helloworld is exporting all of its public classes located in the
ning.osgi.helloworld.
t a Java package, a bundle uses the manifest header Import-Package:
rsion: 1.0
festVersion: 2
olicName: manning.osgi.client
age: manning.osgi.helloworld
helloworld.client is importing all public classes in the package
i.helloworld.
d be clear, we have
s, helloworld and
client, as shown in
The bundle hello-
udes the Printer
bundle helloworld
ludes the Printer-
which makes use of
class.
solved our initial problem? That is, have we prohibited other classes
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Validation
OtherClientprint()
Printer
printMyMessage()
PrinterClientprint()
import manning.osgi.helloworld.client;
...
new PrinterClient().printMyMessage();
...
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Validation
OtherClientprint()
Printer
printMyMessage()
PrinterClientprint()
import manning.osgi.helloworld.client;
...
new PrinterClient().printMyMessage();
...
org.osgi.framework.BundleException: Unresolved
constraint in bundle: package;
(package=manning.osgi.helloworld.client)
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Validation
Class<?> printerClientClass =
Class.forName("manning.osgi.helloworld.client.PrinterClient");
Object printerClientInstance =
printerClientClass.newInstance();
Method printMethod =
printerClientClass.getMethod("printMyMessage");
printMethod.invoke(printerClientInstance);
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Validation
Class<?> printerClientClass =
Class.forName("manning.osgi.helloworld.client.PrinterClient");
Object printerClientInstance =
printerClientClass.newInstance();
Method printMethod =
printerClientClass.getMethod("printMyMessage");
printMethod.invoke(printerClientInstance);
org.osgi.framework.BundleException: Unresolved
constraint in bundle: package;
(package=manning.osgi.helloworld.client)
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Advantages
✤ Formal contract between providers/consumers of interfaces
✤ Declarative and not intrusive
✤ Versioned
✤ Unit of reuse and management
✤ Has own life-cycle
, and then have the consumer bundle import the Java
a bundle uses the manifest header Export-Package:
world
gi.helloworld
oworld is exporting all of its public classes located in the
oworld.
a bundle uses the manifest header Import-Package:
ng.osgi.client
gi.helloworld
ient is importing all public classes in the package
have
and
n in
lo-
ter
rld
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
meant to be shared, and then have the consumer bundle import the Java
s that it needs.
xport Java packages, a bundle uses the manifest header Export-Package:
t-Version: 1.0
ManifestVersion: 2
SymbolicName: helloworld
Package: manning.osgi.helloworld
ase, the bundle helloworld is exporting all of its public classes located in the
manning.osgi.helloworld.
mport a Java package, a bundle uses the manifest header Import-Package:
t-Version: 1.0
ManifestVersion: 2
SymbolicName: manning.osgi.client
Package: manning.osgi.helloworld
ndle helloworld.client is importing all public classes in the package
.osgi.helloworld.
hould be clear, we have
ndles, helloworld and
rld.client, as shown in
2.3. The bundle hello-
includes the Printer
he bundle helloworld
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
manning.osgi.helloworld
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
✤ Data encapsulation
✤ Dealing with changes
✤ Extensibility
✤ Building infrastructures
Agenda
Modularization Grade
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Dealing with Changes
"but in the world nothing can be said to be
certain except death and taxes."
- Ben Franklin
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Interface Changes
package manning.osgi.helloworld;
import java.io.PrintStream;
public class Printer
{
public void println(PrintStream stream, String message)
{
stream.println(message);
}
}
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Interface Changes
java.lang.NoSuchMethodError:
manning.osgi.helloworld.Printer.print(Ljava/
lang/String;)V
bundle uses the manifest header Import-Package:
osgi.client
helloworld
nt is importing all public classes in the package
e
d
n
-
r
d
-
of
problem? That is, have we prohibited other classes
ent class? Yes, by not exporting the package
ent, we make sure that no other class outside the
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
t a Java package, a bundle uses the manifest header Import-Package:
rsion: 1.0
festVersion: 2
olicName: manning.osgi.client
age: manning.osgi.helloworld
helloworld.client is importing all public classes in the package
i.helloworld.
d be clear, we have
, helloworld and
client, as shown in
The bundle hello-
udes the Printer
bundle helloworld
udes the Printer-
which makes use of
class.
solved our initial problem? That is, have we prohibited other classes
the PrinterClient class? Yes, by not exporting the package
i.helloworld.client, we make sure that no other class outside the
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Versioning
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.1
Export-Package: manning.osgi.helloworld;version=1.1
port a Java package, a bundle uses the manifest header Import-Package:
-Version: 1.0
anifestVersion: 2
ymbolicName: manning.osgi.client
ackage: manning.osgi.helloworld
dle helloworld.client is importing all public classes in the package
osgi.helloworld.
ould be clear, we have
dles, helloworld and
ld.client, as shown in
3. The bundle hello-
ncludes the Printer
e bundle helloworld
includes the Printer-
ass, which makes use of
er class.
we solved our initial problem? That is, have we prohibited other classes
ng the PrinterClient class? Yes, by not exporting the package
osgi.helloworld.client, we make sure that no other class outside the
ld.client bundle can use it.
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Versioning
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.anotherclient
Bundle-Version: 1.0.0
Import-Package:
manning.osgi.helloworld;version="[1.1,1.1.9]"
helloworld.anotherclient
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Versioning
helloworld
1.1.0
helloworld
0.0.0
helloworld.client
helloworld.anotherclient
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Export-Package: manning.osgi.helloworld
In this case, the bundle helloworld is exporting all of its publ
package manning.osgi.helloworld.
To import a Java package, a bundle uses the manifest heade
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: manning.osgi.client
Import-Package: manning.osgi.helloworld
The bundle helloworld.client is importing all public c
manning.osgi.helloworld.
As should be clear, we have
two bundles, helloworld and
helloworld.client, as shown in
figure 2.3. The bundle hello-
world includes the Printer
class. The bundle helloworld
Printer
helloworld
Figure 2.3 The bundle hello
Versioning
Bundle-SymbolicName: helloworld
Bundle-Version: 1.1
ge, a bundle uses the manifest header Import-Package:
2
ning.osgi.client
osgi.helloworld
.client is importing all public classes in the package
d.
e have
d and
own in
hello-
rinter
oworld
inter-
use of
nitial problem? That is, have we prohibited other classes
erClient class? Yes, by not exporting the package
d.client, we make sure that no other class outside the
Printer
helloworld
PrinterClient
helloworld.client
Figure 2.3 The bundle helloworld includes the
Printer class. The bundle helloworld.client
includes the PrinterClient class.
Bundle ID:
symbolicName + version
1.0
1.1
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Versioning: details
First, we’ll create a new version of the helloworld b
a new bundle JAR file, which we’ll name helloworld_
JAR filename has no implications at runtime and does
ber. Bundle helloworld_1.1.0.jar has the same bundle
as bundle helloworld.jar. But, in addition, the bundle
number . number . number . (alphanumeric | '_' | '-' )+
Major Minor Micro er
Figure 2.4
four parts: m
first three t
takes alpha
zero is used
Version
Version specifications are used in several places. A version has the following grammar:
version ::=
major( '.' minor ( '.' micro ( '.' qualifier )? )? )?
major ::= number // See 1.3.2
minor ::= number
micro ::= number
qualifier ::= ( alphanum | ._. | '-' )+
A version must not contain any white space. The default value for a version is 0.0.0.
Version Ranges
A version range describes a range of versions using a mathematical interval notation. See [1
matical Convention for Interval Notation.
The syntax of a version range is:
version-range ::= interval | atleast
interval ::= ( '[' | '(' ) floor ',' ceiling ( ']' | ')' )
atleast ::= version
floor ::= version
ceiling ::= version
If a version range is specified as a single version, it must be interpreted as the range [version
default for a non-specified version range is 0, which maps to [0.0.0,∞).
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Versioning: details
dles
In the following table, for each specified range in the le
a member of the range if the predicate in the right-han
7 Filter Syntax
The OSGi specifications use filter expressions extensiv
description of a constraint.
Table 3.1 Examples of version ranges
Example Predicate
[1.2.3, 4.5.6) 1.2.3 <= x < 4.5.6
[1.2.3, 4.5.6] 1.2.3 <= x <= 4.5.6
(1.2.3, 4.5.6) 1.2.3 < x < 4.5.6
(1.2.3, 4.5.6] 1.2.3 < x <= 4.5.6
1.2.3 1.2.3 <= x
versão [versão, ∞)
(vazio) [0.0.0, ∞)
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Advantages
✤ Automatically maintains older versions while they are being used:
✤ For example, even after uninstalling helloworld:0.0, it is kept while
helloworld.client references to it.
✤ If helloworld.client is removed and there are no other references to
helloworld:0.0, then it is also removed.
✤ Allows the simultaneous use of different versions of the same
software component
✤ For example, different versions of commons logging in the same
runtime
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Implementation Changes
✤ In general, things are less ‘drastic’ and only involve implementation
changes
✤ For example, include date in Printer.print()
✤ Implementation changes must be transparent to consuming clients
✤ Re-compilation of client should not be needed
✤ Should be incorporated dynamically
✤ SERVICE ORIENTED IMPLEMENTATION
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Implementation Changes
Previously, we ran into a scenario where we needed to change the interface of a bun-
dle. Life isn’t always so dramatic, and most commonly you may need to change the
implementation of a bundle and not its exposed interface.
Let’s look again at our first version of the Printer class, from section 2.1. We’d like
to change it, as shown in the following listing, so that each printed message gets time-
stamped with the current time.
package manning.osgi.helloworld;
import java.text.DateFormat;
import java.util.Date;
public class Printer {
private static final String SEPARATOR = ": ";
public void print(String message) {
System.out.println(getCurrentTime() + SEPARATOR + message);
}
private String getCurrentTime() {
return DateFormat.getTimeInstance(DateFormat.LONG).
format(new Date());
}
}
You know the drill. Create a new version of bundle helloworld, and then as usual pro-
vision it in Felix. Here’s where it starts getting interesting. When would the existing
client bundles pick up this new version? For bundle helloworld.client to be able to
Listing 2.5 The Printer service implementation
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Implementation Changes
Previously, we ran into a scenario where we needed to change the interface of a bun-
dle. Life isn’t always so dramatic, and most commonly you may need to change the
implementation of a bundle and not its exposed interface.
Let’s look again at our first version of the Printer class, from section 2.1. We’d like
to change it, as shown in the following listing, so that each printed message gets time-
stamped with the current time.
package manning.osgi.helloworld;
import java.text.DateFormat;
import java.util.Date;
public class Printer {
private static final String SEPARATOR = ": ";
public void print(String message) {
System.out.println(getCurrentTime() + SEPARATOR + message);
}
private String getCurrentTime() {
return DateFormat.getTimeInstance(DateFormat.LONG).
format(new Date());
}
}
You know the drill. Create a new version of bundle helloworld, and then as usual pro-
vision it in Felix. Here’s where it starts getting interesting. When would the existing
client bundles pick up this new version? For bundle helloworld.client to be able to
Listing 2.5 The Printer service implementation
Interface and
implementation
dependency
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Services in OSGiIn these roles, the OSGi service registry acts as the mediator, isolating the provider
from the requestor. The service provider bundle owns the service interface, service
properties, and service implementation. The service requestor bundle uses the service
interface and service properties, but it can’t access the service implementation. A dia-
gram of the OSGi service registry is shown in figure 2.8.
Returning to our example, what do we need to do to change the Printer class into
a Printer service?
2.4.1 The Printer service
First, we must create a service interface for the Printer service. OSGi makes this a sim-
ple task. We’ll just create a Java interface for the Printer class:
package manning.osgi.helloworld;
public interface Printer {
public void print(String message);
}
The Printer service interface is defined by a Java interface with a single println
method. No implementation is needed to define the service interface. Technically, we
could use a Java class rather than a Java interface to define the OSGi service interface.
In this case, the service implementation would extend the Java class instead of imple-
menting the Java interface. But using a Java interface is cleaner, is easier to under-
stand, and keeps coupling between the service provider and the service requestor to a
minimum.
Service
properties
Service
implementation
Service
properties
Figure 2.8 The service provider bundle registers the service interface, service properties,
and service implementation into the OSGi service registry. The service requestor bundle
retrieves the service interface and the service properties from the OSGi service registry. Services and loose coupling
Next, we need a Java object to serve as the service implementation. Versio
the Printer class is almost good enough; we just need to change it so that
ments the service interface, as shown here.
package manning.osgi.helloworld.impl;
import java.text.DateFormat;
import java.util.Date;
import manning.osgi.helloworld.Printer;
public class PrinterImpl implements Printer {
private static final String SEPARATOR = ": ";
public void print(String message) {
System.out.println(getCurrentTime() + SEPARATOR + message);
}
private String getCurrentTime() {
return DateFormat.getTimeInstance(DateFormat.LONG).
format(new Date());
}
}
First, the service implementation must implement (or extend) the service in
Second, it’s important to use a different Java package for the implementati
what is used for the interface. The package used by the interface need
exported, whereas we don’t want to export the package used by the impleme
Otherwise, we might not be able to change the implementation easily witho
stalling the clients.
TIP Use different packages for the service interface and service implemen
Listing 2.6 Upgraded Printer service implementation
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Services in OSGiIn these roles, the OSGi service registry acts as the mediator, isolating the provider
from the requestor. The service provider bundle owns the service interface, service
properties, and service implementation. The service requestor bundle uses the service
interface and service properties, but it can’t access the service implementation. A dia-
gram of the OSGi service registry is shown in figure 2.8.
Returning to our example, what do we need to do to change the Printer class into
a Printer service?
2.4.1 The Printer service
First, we must create a service interface for the Printer service. OSGi makes this a sim-
ple task. We’ll just create a Java interface for the Printer class:
package manning.osgi.helloworld;
public interface Printer {
public void print(String message);
}
The Printer service interface is defined by a Java interface with a single println
method. No implementation is needed to define the service interface. Technically, we
could use a Java class rather than a Java interface to define the OSGi service interface.
In this case, the service implementation would extend the Java class instead of imple-
menting the Java interface. But using a Java interface is cleaner, is easier to under-
stand, and keeps coupling between the service provider and the service requestor to a
minimum.
Service
properties
Service
implementation
Service
properties
Figure 2.8 The service provider bundle registers the service interface, service properties,
and service implementation into the OSGi service registry. The service requestor bundle
retrieves the service interface and the service properties from the OSGi service registry. Services and loose coupling
Next, we need a Java object to serve as the service implementation. Versio
the Printer class is almost good enough; we just need to change it so that
ments the service interface, as shown here.
package manning.osgi.helloworld.impl;
import java.text.DateFormat;
import java.util.Date;
import manning.osgi.helloworld.Printer;
public class PrinterImpl implements Printer {
private static final String SEPARATOR = ": ";
public void print(String message) {
System.out.println(getCurrentTime() + SEPARATOR + message);
}
private String getCurrentTime() {
return DateFormat.getTimeInstance(DateFormat.LONG).
format(new Date());
}
}
First, the service implementation must implement (or extend) the service in
Second, it’s important to use a different Java package for the implementati
what is used for the interface. The package used by the interface need
exported, whereas we don’t want to export the package used by the impleme
Otherwise, we might not be able to change the implementation easily witho
stalling the clients.
TIP Use different packages for the service interface and service implemen
Listing 2.6 Upgraded Printer service implementation
interface implementação
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Services in OSGi
interface implementação
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.2
Export-Package:
manning.osgi.helloworld;version=1.2
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.impl
Bundle-Version: 1.0
Import-Package:
manning.osgi.helloworld;version=1.2
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Services in OSGi
interface implementação
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.2
Export-Package:
manning.osgi.helloworld;version=1.2
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.impl
Bundle-Version: 1.0
Import-Package:
manning.osgi.helloworld;version=1.2
Do not export
implementation
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Services in OSGi
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.client
Bundle-Version: 1.0
Import-Package:
manning.osgi.helloworld;version=1.2
interface implementação
cliente
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Services in OSGi
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.client
Bundle-Version: 1.0
Import-Package:
manning.osgi.helloworld;version=1.2
Do not import
implementation
interface implementação
cliente
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Repository
✤ Our system has three bundles:
✤ helloworld: provides Printer interface
✤ helloworld.impl: provides Printer implementation
✤ helloworld.client: consumes Printer service
✤ Now we need a way of the consumer finding the service itself!
Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
Service Repository
40 CHAPTER 2 An OSGi framework primer
In these roles, the OSGi service registry acts as the mediator, isolating the provi
from the requestor. The service provider bundle owns the service interface, ser
properties, and service implementation. The service requestor bundle uses the ser
interface and service properties, but it can’t access the service implementation. A
gram of the OSGi service registry is shown in figure 2.8.
Returning to our example, what do we need to do to change the Printer class i
a Printer service?
Service
properties
Requestor Provider
OSGi
service
registry
Register/unregisterRetrieve/release
Service
implementation
Service
interface
Service
properties
Service
interface
Figure 2.8 The service provider bundle registers the service interface, service properties,
and service implementation into the OSGi service registry. The service requestor bundle
retrieves the service interface and the service properties from the OSGi service registry.
✤ OSGi service:
✤ Interface
✤ Implementation
✤ Properties
✤ Providers and consumers
interact through the Service
Repository
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Providers42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Providers42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
We will take a look at
the BundleActivator
and the BundleContext
later
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Consumers
public void start(BundleContext bundleContext) throws Exception {
this.bundleContext = bundleContext;
serviceReference =
bundleContext.getServiceReference(Printer.class.getName());
if (serviceReference != null) {
Printer printer = (Printer)
bundleContext.getService(serviceReference);
if (printer != null) {
printer.print("Hello...");
}
}
}
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Advantages
vant to their tasks. For example, they don’t even have to know about other entities
we’ve discussed, such as auditors.
NOTE Modular systems are composed of modules that yield simple, highly
cohesive interfaces.
Furthermore, we’re able to leverage the OSGi service layer; we had to implement only
a few lines of code to retrieve an auction service that had the proper terms, such as the
proper style and duration.
Albeit being somewhat obvious, we can use the OSGi service registry as a general
registry of application services and thus implement a common design pattern known
as the registry design pattern, shown in figure 3.4.
Registry design pattern
Intent—Allows a consumer to find a service by knowing only its name or some attribute
of the service
Participants—Consuming bundle, Registry service, Provider bundle
Structure—Consuming bundle searches the registry using a name or attributes for a
particular service that has been registered by a provider bundle
Consequences—Consuming bundle doesn't know who provides the services or care how
Known uses—Data source service (see chapter 8)
Related patterns—Whiteboard pattern
Application
bundle
Service
OSGi
service
registry
Provider
bundle
Retrieve Register
Figure 3.4 In the registry design pattern, the application bundle retrieves the application service from
the OSGi service registry, and the providing bundle registers the service objects.
✤ Clear separation of concerns between providers and consumers
✤ Dynamic
✤ Change of implementation without impacting consumer
✤ Service Repository
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
✤ Data encapsulation
✤ Dealing with changes
✤ Extensibility
✤ Building infrastructures
Agenda
Modularization Grade
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Extensibility
"Technology does not drive change - it
enables change."
- Unknown
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Selection
being exchanged with other parties. A user can
the message.
Hash functions used for this purpose have th
sages that differ will have the same hash value. T
sage and its hash value to a receiver, which can
the received message. The generated hash valu
only if the message has not been altered.
We can define our fingerprint service as follo
public interface FingerprintService {
byte [] hash(String input);
}
There are several implementations of hash func
and MD5 algorithms, both invented by Rivest.
attacks for it, whereas MD5 is slower but safer. M
differences; they just want to get some default
bly be MD5. When dealing with security, we alw
users who may be more educated on the subjec
rithm. How do you solve this problem in the OS
First of all, you should register these two diffe
ing some additional service property that high
you can define a PERFORMANCE property whose
MD4 MD5
Rápido
Segurança baixa
Devagar
Segurança alta
FingerprintService
Fast
Less secure
Slow
More secure
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Selection
MD4 MD5
Rápido
Segurança baixa
Devagar
Segurança alta
FingerprintService
Diferent policies per
customer
Fast
Less secure
Slow
More secure
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Properties
Dictionary<String, Object> md5Properties =
new Hashtable<String, Object>();
md5Properties.put("PERFORMANCE", "SLOW");
md5Properties.put("ALGORITHM", "MD5");
md5Properties.put("SECURITY_LEVEL", "HIGH");
registration = bundleContext.registerService(
FingerprintService.class.getName(),
MD5FingerprintServiceImpl,
md5Properties
);
Dictionary<String, Object> md4Properties =
new Hashtable<String, Object>();
md4Properties.put("PERFORMANCE", "FAST");
md4Properties.put("ALGORITHM", "MD4");
md4Properties.put("SECURITY_LEVEL", "MEDIUM");
registration = bundleContext.registerService(
FingerprintService.class.getName(),
MD4FingerprintServiceImpl,
md4Properties
);
Properties associated
to FingerprintService
Service properties are key-
value pairs
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Filters
String filter =
"(&(objectClass=manning.osgi.fingerprint.FingerprintService)" +
" (PERFORMANCE=FAST)" +
")";
ServiceReference[] serviceReferences =
bundleContext.getServiceReferences(null, filter);
if (serviceReferences != null)
{
FingerprintService service =
(FingerprintService) bundleContext.getService(serviceReferences[0]);
//
}
Service filters specified
as in LDAP
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
LDAP
sively binary and are specified in prefix form, so you can associate any numbe
operations with them. The last operator is unary as expected; that is, it modifies a
gle operation.
The parse tree shown in figure 4.14 describes an OSGi filter that verifies if all
conditions are met.
You can associate several operations together using a single expression opera
For example, consider the following Java expression:
if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3)) { … }
This can be expressed using the following OSGi filter:
(&(attr1=value1)(attr2=value2)(attr3=value3))
Also, the slightly more complicated Java expression,
if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3))) { … }
can be expressed using the following OSGi filter:
(&(attr1=value1)(|(attr2=value2)(attr3=value3)))
So there you have it; you’re now an expert on the OSGi filter syntax. Don’t feel
though if you still prefer the infix style, such as that used in Java, instead of the pr
style used here. You’re not alone.
In the next section, we’ll look at how to distinguish services that share the sa
tion (not) operator (!). The first two operators, contrary to the norm
sively binary and are specified in prefix form, so you can associate
operations with them. The last operator is unary as expected; that is, i
gle operation.
The parse tree shown in figure 4.14 describes an OSGi filter that v
conditions are met.
You can associate several operations together using a single expre
For example, consider the following Java expression:
if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3))
This can be expressed using the following OSGi filter:
(&(attr1=value1)(attr2=value2)(attr3=value3))
Also, the slightly more complicated Java expression,
if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3)
can be expressed using the following OSGi filter:
(&(attr1=value1)(|(attr2=value2)(attr3=value3)))
So there you have it; you’re now an expert on the OSGi filter syntax.
though if you still prefer the infix style, such as that used in Java, inste
style used here. You’re not alone.
In the next section, we’ll look at how to distinguish services that
tion (not) operator (!). The first two operators, contrary to the norm, aren’t exc
sively binary and are specified in prefix form, so you can associate any number
operations with them. The last operator is unary as expected; that is, it modifies a s
gle operation.
The parse tree shown in figure 4.14 describes an OSGi filter that verifies if all t
conditions are met.
You can associate several operations together using a single expression operat
For example, consider the following Java expression:
if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3)) { … }
This can be expressed using the following OSGi filter:
(&(attr1=value1)(attr2=value2)(attr3=value3))
Also, the slightly more complicated Java expression,
if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3))) { … }
can be expressed using the following OSGi filter:
(&(attr1=value1)(|(attr2=value2)(attr3=value3)))
So there you have it; you’re now an expert on the OSGi filter syntax. Don’t feel b
though if you still prefer the infix style, such as that used in Java, instead of the pre
style used here. You’re not alone.
tion (not) operator (!). The first two operators, contrary to the norm
sively binary and are specified in prefix form, so you can associate
operations with them. The last operator is unary as expected; that is, i
gle operation.
The parse tree shown in figure 4.14 describes an OSGi filter that v
conditions are met.
You can associate several operations together using a single expre
For example, consider the following Java expression:
if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3))
This can be expressed using the following OSGi filter:
(&(attr1=value1)(attr2=value2)(attr3=value3))
Also, the slightly more complicated Java expression,
if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3)
can be expressed using the following OSGi filter:
(&(attr1=value1)(|(attr2=value2)(attr3=value3)))
So there you have it; you’re now an expert on the OSGi filter syntax.
though if you still prefer the infix style, such as that used in Java, inste
infix (e.g. Java)
prefix
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
LDAP
✤ Comparison operators:
✤ =, >=, <=, ~= (approximation), =* (existence)
✤ Logical operators:
✤ & (conjunction)
✤ | (disjunction)
✤ ! (negation)
✤ Lists: true if matches at least one element
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Priority
MD4 MD5
Rápido
Segurança baixa
Devagar
Segurança alta
FingerprintService
Which service to use?
Fast
Less secure
Slow
More secure
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Priority
MD4 MD5
Rápido
Segurança baixa
Devagar
Segurança alta
FingerprintService
Which service to use?
Selection is not
deterministic
Fast
Less secure
Slow
More secure
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Priority
MD4 MD5
Rápido
Segurança baixa
Devagar
Segurança alta
FingerprintService
Which service to use?
Selection is not
deterministic
Use priorities to make
selection deterministic.
For example, select
safest algorithm by
default
Fast
Less secure
Slow
More secure
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Service Priority
119Decoupling bundles using services
In this case, you want to avoid this nondeterminism; you’d like the MD5 service
implementation to have priority over the MD4 implementation. This can be done
through the use of the predefined SERVICE_RANKING property, whose value is of type
Integer. When multiple qualifying service implementations exist, the OSGi frame-
work selects the one with the highest SERVICE_RANKING property, as shown in the fol-
lowing listing.
Dictionary<String, Object> md5Properties =
new Hashtable<String, Object>();
md5Properties.put("PERFORMANCE", "SLOW");
md5Properties.put("ALGORITHM", "MD5");
md5Properties.put("SECURITY_LEVEL", "HIGH");
md5Properties.put(Constants.SERVICE_RANKING, 10);
registration = bundleContext.registerService(
FingerprintService.class.getName(),
MD5FingerprintServiceImpl,
md5Properties
);
Dictionary<String, Object> md4Properties =
new Hashtable<String, Object>();
md4Properties.put("PERFORMANCE", "FAST");
md4Properties.put("ALGORITHM", "MD4");
md4Properties.put("SECURITY_LEVEL", "MEDIUM");
md4Properties.put(Constants.SERVICE_RANKING, 5);
registration = bundleContext.registerService(
FingerprintService.class.getName(),
MD4FingerprintServiceImpl,
md4Properties
);
The MD5 service implementation has a service ranking of 10 B, whereas the MD4 ser-
vice implementation has a ranking of 5 c. Thus the OSGi framework selects the MD5
Listing 4.7 Service rankings for the fingerprint service
Higher service
priorityb
Lower service
priorityc
Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
Plugins
✤ How to add new security
algorithms for the Fingerprint
application?
✤ We need a systematic approach
to support application plugins.
Wednesday, August 28, 13
application
bundle
service
OSGI
service
registry
framework
bundle
retrieve register
All Content and Rights Reserved (2013)
Whiteboard design pattern
✤ Roles:
✤ Provider (plugin)
✤ Consumer (application)
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Whiteboard design pattern
✤ Application looks for all registered FingerprintService services
✤ Out-of-the-box: MD4, MD5
ServiceReference[] serviceReferences =
bundleContext.getAllServiceReferences(
FingerprintService.class.getName(), null);
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Whiteboard design pattern
✤ Next, application registers to be notified when a new service is added
or removed dynamically
String filter = "(objectClass="
+ FingerprintService.class.getName() + ")";
bundleContext.addServiceListener(new MyServiceListener(bundleContext),
filter);
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
ServiceListener
public class MyServiceListener implements ServiceListener {
private BundleContext bundleContext;
private Map<String, FingerprintService> services =
new HashMap<String, FingerprintService>();
public MyServiceListener(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
public void serviceChanged(ServiceEvent serviceEvent) {
ServiceReference ref =
serviceEvent.getServiceReference();
switch (serviceEvent.getType()) {
case ServiceEvent.REGISTERED: {
FingerprintService newService =
(FingerprintService) bundleContext.getService(ref);
services.put((String) ref.getProperty("ALGORITHM"), newService);
break;
}
case ServiceEvent.UNREGISTERING: {
services.remove((String) ref.getProperty("ALGORITHM"));
break;
}
}
}
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Whiteboard design pattern
✤ Providers (Bundle Plugin) simply register new service
implementations as needed
✤ It is not necessary for provider (plugin) to learn any new API
properties.put("PERFORMANCE", "SLOW");
properties.put("ALGORITHM", "MD6");
properties.put("SECURITY_LEVEL", "HIGHEST");
registration = bundleContext.registerService(
FingerprintService.class.getName(),
MD6FingerprintServiceImpl,
properties
);
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Advantages
✤ OSGi’s service architecture allows one to create applications that can
be systematically extended
✤ Service properties
✤ Service selection and filtering
✤ Whiteboard design-pattern
✤ The onus of extensibility lies on infrastructure and not on plugin
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
✤ Data encapsulation
✤ Dealing with changes
✤ Extensibility
✤ Building infrastructures
Agenda
Modularization Grade
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Building infrastructures
"Ah, to build, to build! That is the noblest art
of all arts."
- Henry Longfellow, 1807
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
The OSGi Platform
7The OSGi technology
guration Admin Declarative serviceDeployment Admin
User-defined services and applications
OSGI framework
OSGI service platform
Java
Dynamic Java modules (bundles)
Service management
Figure 1.5 The OSGi Service Platform comprises the OSGi framework and the OSGI services.
✤ A modular platform in itself
✤ OSGi has several layers:
✤ The framework, the core services, the optional services, and the application layer
Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
The OSGi Framework
✤ Execution environment:
✤ Java SE, Java ME, e other
environments
✤ Module, Lifecycle layers
✤ Bundles
✤ BundleContext
✤ Service layer
✤ OSGi services
function normally, but now it uses the new Printer service implementation. Congrat-
ulations, you changed the implementation of a running application!
This simple hello world application allowed us to investigate several important fea-
tures from OSGi, ranging from versioning, to package restriction and accessibility, to
service management. In the next section, we’ll discuss the role of these features in the
overall architecture of the OSGi framework.
2.5 The OSGi layered architecture
The OSGi framework is implemented
using a layered architecture,
depicted in figure 2.11.
The bottom layer is the execution
environment. Even though the OSGi
framework is running on top of a
JVM, the JVM itself can have different
versions and profiles. For instance,
there’s a Java Micro Edition of the
JVM, which is named Java ME; there’s
also a Java Standard Edition and a
Java Enterprise Edition. On top of
that, each edition may have several
versions, such as Java SE 1.5 and 1.6.
Because the developer can be using
bundles provided by different ven-
Execution environment
Module layer
Lifecycle layer
Service layer
Security
Figure 2.11 OSGi’s layered architecture is
composed of four layers: the execution environment,
the module layer, the lifecycle layer, and the serviceWednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
Optional Services
✤ Residencial
✤ Enterprise
✤ Management
✤ Configuration
✤ Distribution
✤ Data Access
Examples of enterprise features, as shown in figure 1.6, are the following:
I Management and configuration—This group includes the Configuration A
service as well as the JMX Management Model service and the Metatype se
I Distribution—This feature allows the communication of end points bet
remote instances of OSGi framework instances. Some of the services in
group are the Remote Service and the SCA Configuration Type.
I Data access—This feature includes support for JDBC, JPA, and JTA and allow
manipulation of persisted objects.
Before getting into the details of the OSGi technology itself, you should under
the high-level benefits of using OSGi as your development platform. We addres
topic in the next section.
OSGi framework
JMX
Metatype Admin
guration Admin
guration
JTA
JPA
JDBC
Data access
DistributionRemote service SCA
Figure 1.6 Enterprise OSGi consists of the OSGi framework and several OSGi services;
together they provide enterprise features.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Core Services
✤ Permission Admin Service
✤ URL Handlers Service
✤ Resolver Hook Service
✤ Bundle Hook Service
✤ Service Hook Service
✤ Weaving Hook
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Enterprise OSGi & JEE
✤ OSGi makes use of several JEE standards:
✤ HTTP Servlets, JMX, JNDI, JTA, JPA, JDBC, JCA, etc
✤ Specific modifications needed to conform to the OSGi environment, for
example, such as the removal of static elements
✤ Also uses other enterprise specifications:
✤ SCA (Software Component Architecture)
✤ And defines some of its own:
✤ Meta-type, Configuration, etc.
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Implementations
✤ Framework
✤ Eclipse Equinox
✤ Apache Felix
✤ Knopflerfish
✤ Enterprise
✤ Eclipse Gemini/Virgo
✤ Apache Aries
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Next, you need to install the helloworld and helloworld.client bundles into the
framework.
We have two bundles, or JAR files: helloworld.jar and helloworld.client.jar. The
archived content of the helloworld.jar bundle is
META-INF/MANIFEST.MF
manning/osgi/helloworld/Printer.class
And for the helloworld.client.jar, it’s
META-INF/MANIFEST.MF
manning/osgi/helloworld/client/PrinterClient.class
manning/osgi/helloworld/client/PrinterClientActivator.class
Copy helloworld.jar and helloworld.client.jar to the Felix installation to make it easier
to reference the files. Create a dist directory underneath the install directory, and
place the JAR files there.
NOTE Don’t place the hello world bundles in the bundle directory, because
this directory is by default configured as Felix’s autodeploy directory, a fea-
ture that we’ll talk about in later chapters.
Now, you can install these bundles with the install command typed in the Felix shell:
g! felix:install file:dist/helloworld.jar
Bundle ID: 5
g! felix:install file:dist/helloworld.client.jar
Bundle ID: 6
Each time you install a bundle, Felix provides a unique bundle ID, which is needed
later by the other commands.
NOTE The Gogo shell commands, such as felix:install, can be specified
without the prefix (that is, felix, obr, gogo) if they’re unique. But generally
it’s good to keep the prefix because it helps with backward compatibility for
future versions of Felix.
Did you expect to see “Hello World” printed? We’re almost there.
Felix
✤ Bootstrap
23Running and testing OSGi
Open a shell, and change directory to Felix’s installation home. You can run Felix
with the following command:
felix-framework-3.0.6$ java -jar bin/felix.jar
____________________________
Welcome to Apache Felix Gogo
g!
Conventions
Before we continue, here are some assumptions and conventions you should know:
I We’ll assume that the Java program is in your shell’s path. This is generally the
case.
I We’ll be using JDK 1.5.0_16 to run the examples.
I We’ll be using UNIX commands, as executed in a bash shell, as the convention.
Thanks to Java, we’re mostly isolated from the operating system, except for a
few file-related commands.
I If you’re using Windows, you may have to replace the forward slash (/) with a
backward slash () in file-related commands. As an example, this command,
java -jar bin/felix.jar
should be changed to the following in a Windows environment:
✤ Installing bundles
✤ Activating bundles
CHAPTER 2 An OSGi framework primer
4 Starting the bundles in Felix
To start a bundle, you must use the start command in the Felix shell. As expected,
the start command triggers the BundleActivator.start() callback. Let’s try it out:
g! felix:start 4
g! felix:start 5
Note that you must use the ID returned by the install command.
You should get a stack trace and still no “Hello World” message, which probably
isn’t what you expected. If you go down the stack, you’ll eventually notice the follow-Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
Bundle lifecycle
✤ Installation:
✤ Resolves the export and
import package contracts
✤ Activation:
✤ Register the OSGi services
during invocation of
BundleActivator.start()
callback
Frameworks Life Cycle Layer
Figure 4.3 State diagram Framework
4.2.4 Initializing the Framework
Before the framework can be used, it must be initialized. Initialization is caused by the in
implicitly the start method. An initialized framework is operational, but none of its bun
active. This is reflected in the STARTING state. As long as the framework is in this state,
INSTALLED
STARTING
STOPPING
ACTIVE
init
newFramework
RESOLVED
update
init, start
stop
update
stop start
stop
init
start
stop
update
updatestart
init
start
stop
update
init
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Helloworld revisited...
Bundle ID: 70
g! felix:start 70
g! 11:06:54 PM PST: Hello...
And the problem is still there. But in this case, if you refresh the helloworld.client
bundle, which is something you won’t like to do, you’ll get the right message.
The issue is that the PrinterImpl class is located in the same bundle as the
Printer service interface. When you uninstall the PrinterImpl class, you’re also unin-
stalling the Printer class, which is used in the contract with the helloworld.client
bundle. Because the packages can’t be changed without refreshing the bundle, what
happens is that the OSGi framework keeps around an old version of the helloworld
bundle associated with the helloworld.client bundle and will only pick up the new
version of helloworld when the packages are resolved again. This behavior is vendor
specific, which makes it an even bigger problem.
What you need to do to avoid all the confusion is to move the PrinterImpl class to
another bundle separate from the bundle that includes the service interface. You do
this by creating a third bundle named helloworld.impl_1.4.0.jar, which includes the
PrinterImpl and PrinterActivator classes, as shown in figure 2.10.
Printer
helloworld_1.4.0 helloworld.client_1.1.0
PrinterClientActivator
RunnablePrinterClient
helloworld.impl_1.4.0
PrinterActivator
PrinterImpl
Figure 2.10 Bundle helloworld version 1.4 includes the Printer class. Bundle
helloworld.impl version 1.4 includes the PrinterActivator and PrinterImpl classes.
Bundle helloworld.client version 1.1 includes the PrinterClientActivator and
✤ Bundles:
✤ API: helloworld
✤ Implementation: helloworld.impl
✤ Client: helloworld.client
Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
BundleActivator42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
BundleActivator
42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Manifest-Version: 1.0
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
51Services and loose coupling
The bundle helloworld.impl needs to import the package manning.osgi.
helloworld, but it doesn’t need to export any packages. The MANIFEST.MF file for
helloworld.impl_1.4.0.jar is shown here:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.impl
Bundle-Version: 1.4
Import-Package: manning.osgi.helloworld;version=1.4.0,org.osgi.framework
Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator
In the helloworld_1.4.0.jar bundle, we keep only the Printer class, and we no longer
need to import the org.osgi.framework package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.4
Export-Package: manning.osgi.helloworld;version=1.4.0
Let’s retest:
g! felix:lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.0.6)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
2|Active | 1|Apache Felix Gogo Command (0.6.1)
3|Active | 1|Apache Felix Gogo Runtime (0.6.1)
4|Active | 1|Apache Felix Gogo Shell (0.6.1)
g! felix:install file:dist/helloworld_1.4.0.jar
Bundle ID: 63
g! felix:start 63
g! felix:install file:dist/helloworld.impl_1.4.0.jarWednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
BundleActivator
42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Manifest-Version: 1.0
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
51Services and loose coupling
The bundle helloworld.impl needs to import the package manning.osgi.
helloworld, but it doesn’t need to export any packages. The MANIFEST.MF file for
helloworld.impl_1.4.0.jar is shown here:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.impl
Bundle-Version: 1.4
Import-Package: manning.osgi.helloworld;version=1.4.0,org.osgi.framework
Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator
In the helloworld_1.4.0.jar bundle, we keep only the Printer class, and we no longer
need to import the org.osgi.framework package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.4
Export-Package: manning.osgi.helloworld;version=1.4.0
Let’s retest:
g! felix:lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.0.6)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
2|Active | 1|Apache Felix Gogo Command (0.6.1)
3|Active | 1|Apache Felix Gogo Runtime (0.6.1)
4|Active | 1|Apache Felix Gogo Shell (0.6.1)
g! felix:install file:dist/helloworld_1.4.0.jar
Bundle ID: 63
g! felix:start 63
g! felix:install file:dist/helloworld.impl_1.4.0.jarWednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
BundleActivator
42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Manifest-Version: 1.0
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
51Services and loose coupling
The bundle helloworld.impl needs to import the package manning.osgi.
helloworld, but it doesn’t need to export any packages. The MANIFEST.MF file for
helloworld.impl_1.4.0.jar is shown here:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld.impl
Bundle-Version: 1.4
Import-Package: manning.osgi.helloworld;version=1.4.0,org.osgi.framework
Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator
In the helloworld_1.4.0.jar bundle, we keep only the Printer class, and we no longer
need to import the org.osgi.framework package:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.4
Export-Package: manning.osgi.helloworld;version=1.4.0
Let’s retest:
g! felix:lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.0.6)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
2|Active | 1|Apache Felix Gogo Command (0.6.1)
3|Active | 1|Apache Felix Gogo Runtime (0.6.1)
4|Active | 1|Apache Felix Gogo Shell (0.6.1)
g! felix:install file:dist/helloworld_1.4.0.jar
Bundle ID: 63
g! felix:start 63
g! felix:install file:dist/helloworld.impl_1.4.0.jarWednesday, August 28, 13
All Content and Rights Reserved (2013)
Simplifying the programming
model
42 CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Simplifying the programming
model
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Simplifying the programming
model
CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.4
Export-Package: manning.osgi.helloworld;version=1.4.0
Import-Package: org.osgi.framework
Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator
In the start method, you instantiate the service by specifying its interface B and
implementation c, and you register it in the service registry using the bundle-
Context.registerService() method. This method returns a serviceRegistration
object, which represents the registered service.
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Simplifying the programming
model
<blueprint xmlns="http://www.osgi.org/xmlns/
blueprint/v1.0.0">
	 <bean id="impl"
class="manning.osgi.helloworld.impl.PrinterImpl" />
	
	 <service
interface="manning.osgi.helloworld.Printer"
	 	 ref="impl" />
</blueprint>
CHAPTER 2 An OSGi framework primer
package manning.osgi.helloworld.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import manning.osgi.helloworld.Printer;
public class PrinterActivator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
serviceRegistration =
bundleContext.registerService(
Printer.class.getName(),
new PrinterImpl(),
null);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
You can archive the Printer interface, the Printer implementation, and the
PrinterActivator classes into version 1.4.0 of the helloworld bundle:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: helloworld
Bundle-Version: 1.4
Export-Package: manning.osgi.helloworld;version=1.4.0
Import-Package: org.osgi.framework
Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator
In the start method, you instantiate the service by specifying its interface B and
implementation c, and you register it in the service registry using the bundle-
Context.registerService() method. This method returns a serviceRegistration
object, which represents the registered service.
Listing 2.7 Registering the Printer service in the OSGi service registry
Printer service
interface
b
Printer service
implementationc
Unregister
serviced
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Blueprint (Spring dm)
✤ Bundle client (helloworld.client)
✤ META-INF/spring/blueprint.xml
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
	 <reference id="printer" interface="manning.osgi.helloworld.Printer" />
	 <bean id="client" class="manning.osgi.helloworld.PrinterClient" >
	 	 <property name="printerService" ref="printer" />
	 </bean>
	
</blueprint>
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Blueprint (Spring dm)
✤ Bundle client (helloworld.client)
✤ META-INF/spring/blueprint.xml
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
	 <reference id="printer" interface="manning.osgi.helloworld.Printer" />
	 <bean id="client" class="manning.osgi.helloworld.PrinterClient" >
	 	 <property name="printerService" ref="printer" />
	 </bean>
	
</blueprint>
Specification of the
application components
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Vertical Solutions
✤ OSGi allows the creation of layered frameworks:
✤ Spring-dm
✤ Service integration
✤ Creation of new programming models
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Simplifying the
FingerprintService
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
	 <fingerprint id="fingerprint" type="MD4" />
	 <bean id="client" class="manning.osgi.FingerprintClient" />
	
</blueprint>	
public class FingerprintClient {
public void setHash(byte [] hash)
{
//
}
}
Infrastructure automatically calls
setHash() using toString() in the client
instance.
client.setHash(
fingerprint.hash(client.toString()))
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Simplifying the
FingerprintService
✤ Customer only has to create JAR (bundle) with:
✤ FingerprintClient class
✤ blueprint.xml
✤ MANIFEST.MF with OSGi header entries
✤ Bundle-SymbolicName: fingerprintClient
✤ In this case, it is not necessary for the customer to import a particular
package or to make use of a particular service.
public class FingerprintClient {
public void setHash(byte [] hash)
{
//
}
}
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
OtherVertical Bundles
idea of containers and application bundles.
13.1 Application bundles and their containers
As you’ve seen in the previous chapters, a common pattern for enabling a bundle with
a new feature is to annotate the bundle’s manifest file. For example, to enable a bun-
dle to persist its Java classes, you can add the Meta-Persistence header entry to its
MANIFEST.MF file. The following table summarizes some of the standard manifest
header entries used to create feature-specific powered bundles, or, perhaps a bit more col-
orful, bundle flavors.
Table 13.1 Flavored bundles
Name Description Manifest header
WAB Web application bundle Web-ContextPath
Persistence bundle Bundle with persistence units Meta-Persistence
SCA config bundle Bundle with SCA configuration SCA-Configuration
Component bundle Bundle with declarative components Service-Component
Blueprint bundle Bundle with Blueprint components Bundle-Blueprint
Endpoint bundle Bundle with endpoint descriptions Remote-Service
Application bundles
Table 13.1 lists just a few examples of the different flavors of bundles that exist. Some
of them have been discussed in previous chapters, but some of them are out of theWednesday, August 28, 13
All Content and Rights Reserved (2013)
Vertical Servers: Oracle Event
Processing
✤ Started as a vertical server for processing events for financial markets
✤ Defines its own programming model for event processing
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Vertical Servers: Oracle Event
Processing
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
Conclusion
✤ OSGi helps in the development of systems that are:
✤ modular
✤ bundles
✤ extensible
✤ services
✤ Modular and extensible systems allows one to create their own
vertical infrastructure or framework
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
In the trenches with OEP
✤ Use tooling, especially PMD
✤ Introspects Java classes and generates proper MANIFEST header
entries for imports and exports
✤ Be careful not to overdue it and simply export and import
everything. Know what you are doing when using wildcards
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
In the trenches with OEP
✤ Do Semantic Versioning (http://www.osgi.org/wiki/uploads/
Links/SemanticVersioning.pdf)
✤ Change minor version for implementation changes
✤ Change major version for interface changes
✤ Import as [X.Y,X+1.0) (for example: [1.2,2.0))
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
In the trenches with OEP
✤ All features should have at least two bundles: an interface and an
implementation bundle
✤ Some features may even more, for example, one for management,
one for SPIs, etc.
✤ Also, all features should have a ‘test bundle’ that runs as a Junit
test-case
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
In the trenches with OEP
✤ Don’t use statics, instead create singleton services
✤ Don’t use JDK’s service property files, these are just another type of
‘static’
✤ Don’t expect to be able to cheat by using ‘Reflection’
✤ For example, to implement a general purpose configuration
system, we had to pass along the application’s (bundle) class-
loader, otherwise there is infra bundles can’t see application
bundle’s resources
Wednesday, August 28, 13
All Content and Rights Reserved (2013)
In the trenches with OEP
✤ Getting the right order of installation and start-up is hard!
✤ Make sure your service registration and retrieval go through
ServiceTracker or some other mechanism that avoids temporal
cohesion
✤ Create layers of features, such as: core, domain-feature, application,
etc.
Wednesday, August 28, 13
Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012)
Developing Modular
and Extensible
Systems using OSGi
adcalves@gmail.com
alex.alves@oracle.com
http://www.manning.com/alves/
http://adcalves.wordpress.com
http://www.oracle.com/technetwork/middleware/complex-event-
processing/overview/index.html
Wednesday, August 28, 13

Mais conteúdo relacionado

Destaque

Careers opportunities in finance
Careers opportunities in financeCareers opportunities in finance
Careers opportunities in financeShantilal Hajeri
 
A Last Look - Day 2
A Last Look - Day 2A Last Look - Day 2
A Last Look - Day 2jmori1
 
The Film Industry
The Film IndustryThe Film Industry
The Film IndustryNShuttle
 
Manifestação da República do Paraná contra Lula
Manifestação da República do Paraná contra LulaManifestação da República do Paraná contra Lula
Manifestação da República do Paraná contra LulaMiguel Rosario
 
Kudavi 1.30.2016
Kudavi 1.30.2016Kudavi 1.30.2016
Kudavi 1.30.2016Tom Currier
 
Teatro de la sensacion cursos de verano teatro infantil-2016
Teatro de la sensacion  cursos de verano teatro infantil-2016Teatro de la sensacion  cursos de verano teatro infantil-2016
Teatro de la sensacion cursos de verano teatro infantil-2016Miguel Muñoz de Morales
 
366/14 MediaKey /// Creatività: Made in Tunnel Studios
366/14 MediaKey /// Creatività: Made in Tunnel Studios366/14 MediaKey /// Creatività: Made in Tunnel Studios
366/14 MediaKey /// Creatività: Made in Tunnel StudiosTunnel Studios
 

Destaque (18)

Q4 10
Q4 10Q4 10
Q4 10
 
Careers opportunities in finance
Careers opportunities in financeCareers opportunities in finance
Careers opportunities in finance
 
Network Layer
Network LayerNetwork Layer
Network Layer
 
Us2aware
Us2awareUs2aware
Us2aware
 
AEF4 2C 1
AEF4 2C 1AEF4 2C 1
AEF4 2C 1
 
A Last Look - Day 2
A Last Look - Day 2A Last Look - Day 2
A Last Look - Day 2
 
The Film Industry
The Film IndustryThe Film Industry
The Film Industry
 
Confessions & Lessons
Confessions & LessonsConfessions & Lessons
Confessions & Lessons
 
Unit 57 terminology becky doyle
Unit 57 terminology becky doyleUnit 57 terminology becky doyle
Unit 57 terminology becky doyle
 
Manifestação da República do Paraná contra Lula
Manifestação da República do Paraná contra LulaManifestação da República do Paraná contra Lula
Manifestação da República do Paraná contra Lula
 
M robby f_mi2b_tugas 2
M robby f_mi2b_tugas 2M robby f_mi2b_tugas 2
M robby f_mi2b_tugas 2
 
Unit 57 terminology becky doyle
Unit 57 terminology becky doyleUnit 57 terminology becky doyle
Unit 57 terminology becky doyle
 
Aef4 05
Aef4 05Aef4 05
Aef4 05
 
Kudavi 1.30.2016
Kudavi 1.30.2016Kudavi 1.30.2016
Kudavi 1.30.2016
 
Ig3 2012_assignment
 Ig3 2012_assignment Ig3 2012_assignment
Ig3 2012_assignment
 
Teatro de la sensacion cursos de verano teatro infantil-2016
Teatro de la sensacion  cursos de verano teatro infantil-2016Teatro de la sensacion  cursos de verano teatro infantil-2016
Teatro de la sensacion cursos de verano teatro infantil-2016
 
366/14 MediaKey /// Creatività: Made in Tunnel Studios
366/14 MediaKey /// Creatività: Made in Tunnel Studios366/14 MediaKey /// Creatività: Made in Tunnel Studios
366/14 MediaKey /// Creatività: Made in Tunnel Studios
 
Final
FinalFinal
Final
 

Semelhante a Developing Modular Systems using OSGi

Core Java- An advanced review of features
Core Java- An advanced review of featuresCore Java- An advanced review of features
Core Java- An advanced review of featuresvidyamittal
 
Unit4 java
Unit4 javaUnit4 java
Unit4 javamrecedu
 
Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2
 Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2   Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2
Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2 Adil Khan
 
OSGi Enablement For Apache Tuscany
OSGi Enablement For Apache TuscanyOSGi Enablement For Apache Tuscany
OSGi Enablement For Apache TuscanyRaymond Feng
 
Introduction to OSGi
Introduction to OSGiIntroduction to OSGi
Introduction to OSGipradeepfn
 
Eclipse_Building_Blocks
Eclipse_Building_BlocksEclipse_Building_Blocks
Eclipse_Building_BlocksRahul Shukla
 
MobileConf 2021 Slides: Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides:  Let's build macOS CLI Utilities using SwiftMobileConf 2021 Slides:  Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides: Let's build macOS CLI Utilities using SwiftDiego Freniche Brito
 
Generic Synchronization Policies in C++
Generic Synchronization Policies in C++Generic Synchronization Policies in C++
Generic Synchronization Policies in C++Ciaran McHale
 
Unit2 java
Unit2 javaUnit2 java
Unit2 javamrecedu
 
The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202Mahmoud Samir Fayed
 

Semelhante a Developing Modular Systems using OSGi (20)

Core Java- An advanced review of features
Core Java- An advanced review of featuresCore Java- An advanced review of features
Core Java- An advanced review of features
 
Unit4 java
Unit4 javaUnit4 java
Unit4 java
 
Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2
 Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2   Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2
Recipe to build open splice dds 6.3.xxx Hello World example over Qt 5.2
 
OSGi Enablement For Apache Tuscany
OSGi Enablement For Apache TuscanyOSGi Enablement For Apache Tuscany
OSGi Enablement For Apache Tuscany
 
Devtools cheatsheet
Devtools cheatsheetDevtools cheatsheet
Devtools cheatsheet
 
Devtools cheatsheet
Devtools cheatsheetDevtools cheatsheet
Devtools cheatsheet
 
Introduction to OSGi
Introduction to OSGiIntroduction to OSGi
Introduction to OSGi
 
Java Programming - 05 access control in java
Java Programming - 05 access control in javaJava Programming - 05 access control in java
Java Programming - 05 access control in java
 
Java packages oop
Java packages oopJava packages oop
Java packages oop
 
Eclipse_Building_Blocks
Eclipse_Building_BlocksEclipse_Building_Blocks
Eclipse_Building_Blocks
 
MobileConf 2021 Slides: Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides:  Let's build macOS CLI Utilities using SwiftMobileConf 2021 Slides:  Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides: Let's build macOS CLI Utilities using Swift
 
Unit 2 notes.pdf
Unit 2 notes.pdfUnit 2 notes.pdf
Unit 2 notes.pdf
 
Generic Synchronization Policies in C++
Generic Synchronization Policies in C++Generic Synchronization Policies in C++
Generic Synchronization Policies in C++
 
GNURAdioDoc-8
GNURAdioDoc-8GNURAdioDoc-8
GNURAdioDoc-8
 
GNURAdioDoc-8
GNURAdioDoc-8GNURAdioDoc-8
GNURAdioDoc-8
 
Unit2 java
Unit2 javaUnit2 java
Unit2 java
 
The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202
 
Stepping into Scala
Stepping into ScalaStepping into Scala
Stepping into Scala
 
Readme
ReadmeReadme
Readme
 
Packages and interfaces
Packages and interfacesPackages and interfaces
Packages and interfaces
 

Mais de Alexandre de Castro Alves

Mais de Alexandre de Castro Alves (7)

A Guideline to Statistical and Machine Learning
A Guideline to Statistical and Machine LearningA Guideline to Statistical and Machine Learning
A Guideline to Statistical and Machine Learning
 
Speeding up big data with event processing
Speeding up big data with event processingSpeeding up big data with event processing
Speeding up big data with event processing
 
A General Extension System for Event Processing Languages
A General Extension System for Event Processing LanguagesA General Extension System for Event Processing Languages
A General Extension System for Event Processing Languages
 
Ts 4783 1
Ts 4783 1Ts 4783 1
Ts 4783 1
 
Bpel4 Ws 1.1 To Ws Bpel 2.0
Bpel4 Ws 1.1 To Ws Bpel 2.0Bpel4 Ws 1.1 To Ws Bpel 2.0
Bpel4 Ws 1.1 To Ws Bpel 2.0
 
Introduction to OSGi
Introduction to OSGiIntroduction to OSGi
Introduction to OSGi
 
Alves Mea Pch1 Free
Alves Mea Pch1 FreeAlves Mea Pch1 Free
Alves Mea Pch1 Free
 

Último

Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 

Último (20)

Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 

Developing Modular Systems using OSGi

  • 1. Developing Modular and Extensible Systems using OSGi Alexandre de Alves, M.Sc. Wednesday, August 28, 13
  • 2. All Content and Rights Reserved (2013) Systems using OSGi ✤ Oracle GlassFish Application Server ✤ Oracle Complex Event Processing Server ✤ IBM Websphere ✤ (Redhat) JBoss Application Server ✤ SAP NetWeaver (in progress) ✤ Apache ServiceMix ✤ Apache Camel ✤ Apache Karaf ✤ Apache Sling Wednesday, August 28, 13
  • 3. All Content and Rights Reserved (2013) ✤ Data encapsulation ✤ Dealing with changes ✤ Extensibility ✤ Building infrastructures Agenda Modularization Grade Wednesday, August 28, 13
  • 4. All Content and Rights Reserved (2013) Data Encapsulation “Information hiding achieves changeability, comprehensibility, independent development” - D. Parnas, 1972 Wednesday, August 28, 13
  • 5. All Content and Rights Reserved (2013) Data Encapsulation ✤ As brilliantly elaborated by D. Parnas in 1972 ✤ The more code that is exposed, the more tests that are needed. Wednesday, August 28, 13
  • 6. All Content and Rights Reserved (2013) public class Printer { public void print(String message) { System.out.println(message); } } public class PrinterClient { public void printMyMessage() { new Printer().print("Hello World"); } } Simple example... Wednesday, August 28, 13
  • 7. All Content and Rights Reserved (2013) public class Printer { public void print(String message) { System.out.println(message); } } public class PrinterClient { public void printMyMessage() { new Printer().print("Hello World"); } } Simple example... Modules and information hiding Let’s share this code with other Java clients. Create a Pri imports the Printer class and invokes it: package manning.osgi.helloworld.client; import manning.osgi.helloworld.Printer; public class PrinterClient { public void printMyMessage() { new Printer().print("Hello World"); } } Figure 2.1 demonstrates this interaction. NOTE This book attempts to be goal oriented. Rather tha technology for the technology’s sake, the discussion of a t print(String message) Printer printMyMessage() PrinterClientprint() Figure 2.1 class invok the Print Wednesday, August 28, 13
  • 8. All Content and Rights Reserved (2013) public class Printer { public void print(String message) { System.out.println(message); } } public class PrinterClient { public void printMyMessage() { new Printer().print("Hello World"); } } Simple example... Wednesday, August 28, 13
  • 9. All Content and Rights Reserved (2013) Objective ✤ Our goal is to minimize the number of exposed interfaces ✤ For example, expose print() and not printMyMessage() Other Classesprint() Printer printMyMessage() PrinterClientprint() Other classes Wednesday, August 28, 13
  • 10. All Content and Rights Reserved (2013) Modularization package manning.osgi.helloworld; public class Printer { public void print(String message) { System.out.println(message); } } package manning.osgi.helloworld.client; import manning.osgi.helloworld; public class PrinterClient { public void printMyMessage() { new Printer().print("Hello World"); } } ld is exporting all of its public classes located in the ld. undle uses the manifest header Import-Package: sgi.client elloworld t is importing all public classes in the package Printer helloworld PrinterClient helloworld.client orld is exporting all of its public classes located in the orld. bundle uses the manifest header Import-Package: osgi.client helloworld nt is importing all public classes in the package e d n - r d Printer helloworld PrinterClient helloworld.client Wednesday, August 28, 13
  • 11. All Content and Rights Reserved (2013) Modules in OSGi ✤ A module in OSGi is called bundle ✤ A bundle is formally defined as: ✤ A JAR file ✤ OSGi-specific manifest header entries Wednesday, August 28, 13
  • 12. All Content and Rights Reserved (2013) Modules in OSGi CHAPTER 2 An OSGi framework primer In OSGi, you accomplish this by having the provider bundle export the Java packages that are meant to be shared, and then have the consumer bundle import the Java packages that it needs. To export Java packages, a bundle uses the manifest header Export-Package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exporting all of its public classes located in the package manning.osgi.helloworld. To import a Java package, a bundle uses the manifest header Import-Package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importing all public classes in the package manning.osgi.helloworld. As should be clear, we have two bundles, helloworld and helloworld.client, as shown in figure 2.3. The bundle hello- Printer helloworld PrinterClient helloworld.client 20 CHAPTER 2 An OSGi framew In OSGi, you accomplish this by having the pro that are meant to be shared, and then have packages that it needs. To export Java packages, a bundle uses the Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exportin package manning.osgi.helloworld. To import a Java package, a bundle uses the Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importin manning.osgi.helloworld. orld is exporting all of its public classes located in the orld. bundle uses the manifest header Import-Package: .osgi.client .helloworld nt is importing all public classes in the package e d n - r d - of problem? That is, have we prohibited other classes Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. the bundle helloworld is exporting all of its public classes located in the ning.osgi.helloworld. t a Java package, a bundle uses the manifest header Import-Package: rsion: 1.0 festVersion: 2 olicName: manning.osgi.client age: manning.osgi.helloworld helloworld.client is importing all public classes in the package i.helloworld. d be clear, we have s, helloworld and client, as shown in The bundle hello- udes the Printer bundle helloworld ludes the Printer- which makes use of class. solved our initial problem? That is, have we prohibited other classes Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. Wednesday, August 28, 13
  • 13. All Content and Rights Reserved (2013) Modules in OSGi CHAPTER 2 An OSGi framework primer In OSGi, you accomplish this by having the provider bundle export the Java packages that are meant to be shared, and then have the consumer bundle import the Java packages that it needs. To export Java packages, a bundle uses the manifest header Export-Package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exporting all of its public classes located in the package manning.osgi.helloworld. To import a Java package, a bundle uses the manifest header Import-Package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importing all public classes in the package manning.osgi.helloworld. As should be clear, we have two bundles, helloworld and helloworld.client, as shown in figure 2.3. The bundle hello- Printer helloworld PrinterClient helloworld.client 20 CHAPTER 2 An OSGi framew In OSGi, you accomplish this by having the pro that are meant to be shared, and then have packages that it needs. To export Java packages, a bundle uses the Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exportin package manning.osgi.helloworld. To import a Java package, a bundle uses the Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importin manning.osgi.helloworld. orld is exporting all of its public classes located in the orld. bundle uses the manifest header Import-Package: .osgi.client .helloworld nt is importing all public classes in the package e d n - r d - of problem? That is, have we prohibited other classes Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. the bundle helloworld is exporting all of its public classes located in the ning.osgi.helloworld. t a Java package, a bundle uses the manifest header Import-Package: rsion: 1.0 festVersion: 2 olicName: manning.osgi.client age: manning.osgi.helloworld helloworld.client is importing all public classes in the package i.helloworld. d be clear, we have s, helloworld and client, as shown in The bundle hello- udes the Printer bundle helloworld ludes the Printer- which makes use of class. solved our initial problem? That is, have we prohibited other classes Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. Wednesday, August 28, 13
  • 14. All Content and Rights Reserved (2013) Modules in OSGi CHAPTER 2 An OSGi framework primer In OSGi, you accomplish this by having the provider bundle export the Java packages that are meant to be shared, and then have the consumer bundle import the Java packages that it needs. To export Java packages, a bundle uses the manifest header Export-Package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exporting all of its public classes located in the package manning.osgi.helloworld. To import a Java package, a bundle uses the manifest header Import-Package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importing all public classes in the package manning.osgi.helloworld. As should be clear, we have two bundles, helloworld and helloworld.client, as shown in figure 2.3. The bundle hello- Printer helloworld PrinterClient helloworld.client 20 CHAPTER 2 An OSGi framew In OSGi, you accomplish this by having the pro that are meant to be shared, and then have packages that it needs. To export Java packages, a bundle uses the Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exportin package manning.osgi.helloworld. To import a Java package, a bundle uses the Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importin manning.osgi.helloworld. orld is exporting all of its public classes located in the orld. bundle uses the manifest header Import-Package: .osgi.client .helloworld nt is importing all public classes in the package e d n - r d - of problem? That is, have we prohibited other classes Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. the bundle helloworld is exporting all of its public classes located in the ning.osgi.helloworld. t a Java package, a bundle uses the manifest header Import-Package: rsion: 1.0 festVersion: 2 olicName: manning.osgi.client age: manning.osgi.helloworld helloworld.client is importing all public classes in the package i.helloworld. d be clear, we have s, helloworld and client, as shown in The bundle hello- udes the Printer bundle helloworld ludes the Printer- which makes use of class. solved our initial problem? That is, have we prohibited other classes Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. Wednesday, August 28, 13
  • 15. All Content and Rights Reserved (2013) Validation OtherClientprint() Printer printMyMessage() PrinterClientprint() import manning.osgi.helloworld.client; ... new PrinterClient().printMyMessage(); ... Wednesday, August 28, 13
  • 16. All Content and Rights Reserved (2013) Validation OtherClientprint() Printer printMyMessage() PrinterClientprint() import manning.osgi.helloworld.client; ... new PrinterClient().printMyMessage(); ... org.osgi.framework.BundleException: Unresolved constraint in bundle: package; (package=manning.osgi.helloworld.client) Wednesday, August 28, 13
  • 17. All Content and Rights Reserved (2013) Validation Class<?> printerClientClass = Class.forName("manning.osgi.helloworld.client.PrinterClient"); Object printerClientInstance = printerClientClass.newInstance(); Method printMethod = printerClientClass.getMethod("printMyMessage"); printMethod.invoke(printerClientInstance); Wednesday, August 28, 13
  • 18. All Content and Rights Reserved (2013) Validation Class<?> printerClientClass = Class.forName("manning.osgi.helloworld.client.PrinterClient"); Object printerClientInstance = printerClientClass.newInstance(); Method printMethod = printerClientClass.getMethod("printMyMessage"); printMethod.invoke(printerClientInstance); org.osgi.framework.BundleException: Unresolved constraint in bundle: package; (package=manning.osgi.helloworld.client) Wednesday, August 28, 13
  • 19. All Content and Rights Reserved (2013) Advantages ✤ Formal contract between providers/consumers of interfaces ✤ Declarative and not intrusive ✤ Versioned ✤ Unit of reuse and management ✤ Has own life-cycle , and then have the consumer bundle import the Java a bundle uses the manifest header Export-Package: world gi.helloworld oworld is exporting all of its public classes located in the oworld. a bundle uses the manifest header Import-Package: ng.osgi.client gi.helloworld ient is importing all public classes in the package have and n in lo- ter rld Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the meant to be shared, and then have the consumer bundle import the Java s that it needs. xport Java packages, a bundle uses the manifest header Export-Package: t-Version: 1.0 ManifestVersion: 2 SymbolicName: helloworld Package: manning.osgi.helloworld ase, the bundle helloworld is exporting all of its public classes located in the manning.osgi.helloworld. mport a Java package, a bundle uses the manifest header Import-Package: t-Version: 1.0 ManifestVersion: 2 SymbolicName: manning.osgi.client Package: manning.osgi.helloworld ndle helloworld.client is importing all public classes in the package .osgi.helloworld. hould be clear, we have ndles, helloworld and rld.client, as shown in 2.3. The bundle hello- includes the Printer he bundle helloworld Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the manning.osgi.helloworld Wednesday, August 28, 13
  • 20. All Content and Rights Reserved (2013) ✤ Data encapsulation ✤ Dealing with changes ✤ Extensibility ✤ Building infrastructures Agenda Modularization Grade Wednesday, August 28, 13
  • 21. All Content and Rights Reserved (2013) Dealing with Changes "but in the world nothing can be said to be certain except death and taxes." - Ben Franklin Wednesday, August 28, 13
  • 22. All Content and Rights Reserved (2013) Interface Changes package manning.osgi.helloworld; import java.io.PrintStream; public class Printer { public void println(PrintStream stream, String message) { stream.println(message); } } Wednesday, August 28, 13
  • 23. All Content and Rights Reserved (2013) Interface Changes java.lang.NoSuchMethodError: manning.osgi.helloworld.Printer.print(Ljava/ lang/String;)V bundle uses the manifest header Import-Package: osgi.client helloworld nt is importing all public classes in the package e d n - r d - of problem? That is, have we prohibited other classes ent class? Yes, by not exporting the package ent, we make sure that no other class outside the Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. t a Java package, a bundle uses the manifest header Import-Package: rsion: 1.0 festVersion: 2 olicName: manning.osgi.client age: manning.osgi.helloworld helloworld.client is importing all public classes in the package i.helloworld. d be clear, we have , helloworld and client, as shown in The bundle hello- udes the Printer bundle helloworld udes the Printer- which makes use of class. solved our initial problem? That is, have we prohibited other classes the PrinterClient class? Yes, by not exporting the package i.helloworld.client, we make sure that no other class outside the Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. Wednesday, August 28, 13
  • 24. All Content and Rights Reserved (2013) Versioning Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.1 Export-Package: manning.osgi.helloworld;version=1.1 port a Java package, a bundle uses the manifest header Import-Package: -Version: 1.0 anifestVersion: 2 ymbolicName: manning.osgi.client ackage: manning.osgi.helloworld dle helloworld.client is importing all public classes in the package osgi.helloworld. ould be clear, we have dles, helloworld and ld.client, as shown in 3. The bundle hello- ncludes the Printer e bundle helloworld includes the Printer- ass, which makes use of er class. we solved our initial problem? That is, have we prohibited other classes ng the PrinterClient class? Yes, by not exporting the package osgi.helloworld.client, we make sure that no other class outside the ld.client bundle can use it. Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. Wednesday, August 28, 13
  • 25. All Content and Rights Reserved (2013) Versioning Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.anotherclient Bundle-Version: 1.0.0 Import-Package: manning.osgi.helloworld;version="[1.1,1.1.9]" helloworld.anotherclient Wednesday, August 28, 13
  • 26. All Content and Rights Reserved (2013) Versioning helloworld 1.1.0 helloworld 0.0.0 helloworld.client helloworld.anotherclient Wednesday, August 28, 13
  • 27. All Content and Rights Reserved (2013) Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Export-Package: manning.osgi.helloworld In this case, the bundle helloworld is exporting all of its publ package manning.osgi.helloworld. To import a Java package, a bundle uses the manifest heade Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: manning.osgi.client Import-Package: manning.osgi.helloworld The bundle helloworld.client is importing all public c manning.osgi.helloworld. As should be clear, we have two bundles, helloworld and helloworld.client, as shown in figure 2.3. The bundle hello- world includes the Printer class. The bundle helloworld Printer helloworld Figure 2.3 The bundle hello Versioning Bundle-SymbolicName: helloworld Bundle-Version: 1.1 ge, a bundle uses the manifest header Import-Package: 2 ning.osgi.client osgi.helloworld .client is importing all public classes in the package d. e have d and own in hello- rinter oworld inter- use of nitial problem? That is, have we prohibited other classes erClient class? Yes, by not exporting the package d.client, we make sure that no other class outside the Printer helloworld PrinterClient helloworld.client Figure 2.3 The bundle helloworld includes the Printer class. The bundle helloworld.client includes the PrinterClient class. Bundle ID: symbolicName + version 1.0 1.1 Wednesday, August 28, 13
  • 28. All Content and Rights Reserved (2013) Versioning: details First, we’ll create a new version of the helloworld b a new bundle JAR file, which we’ll name helloworld_ JAR filename has no implications at runtime and does ber. Bundle helloworld_1.1.0.jar has the same bundle as bundle helloworld.jar. But, in addition, the bundle number . number . number . (alphanumeric | '_' | '-' )+ Major Minor Micro er Figure 2.4 four parts: m first three t takes alpha zero is used Version Version specifications are used in several places. A version has the following grammar: version ::= major( '.' minor ( '.' micro ( '.' qualifier )? )? )? major ::= number // See 1.3.2 minor ::= number micro ::= number qualifier ::= ( alphanum | ._. | '-' )+ A version must not contain any white space. The default value for a version is 0.0.0. Version Ranges A version range describes a range of versions using a mathematical interval notation. See [1 matical Convention for Interval Notation. The syntax of a version range is: version-range ::= interval | atleast interval ::= ( '[' | '(' ) floor ',' ceiling ( ']' | ')' ) atleast ::= version floor ::= version ceiling ::= version If a version range is specified as a single version, it must be interpreted as the range [version default for a non-specified version range is 0, which maps to [0.0.0,∞). Wednesday, August 28, 13
  • 29. All Content and Rights Reserved (2013) Versioning: details dles In the following table, for each specified range in the le a member of the range if the predicate in the right-han 7 Filter Syntax The OSGi specifications use filter expressions extensiv description of a constraint. Table 3.1 Examples of version ranges Example Predicate [1.2.3, 4.5.6) 1.2.3 <= x < 4.5.6 [1.2.3, 4.5.6] 1.2.3 <= x <= 4.5.6 (1.2.3, 4.5.6) 1.2.3 < x < 4.5.6 (1.2.3, 4.5.6] 1.2.3 < x <= 4.5.6 1.2.3 1.2.3 <= x versão [versão, ∞) (vazio) [0.0.0, ∞) Wednesday, August 28, 13
  • 30. All Content and Rights Reserved (2013) Advantages ✤ Automatically maintains older versions while they are being used: ✤ For example, even after uninstalling helloworld:0.0, it is kept while helloworld.client references to it. ✤ If helloworld.client is removed and there are no other references to helloworld:0.0, then it is also removed. ✤ Allows the simultaneous use of different versions of the same software component ✤ For example, different versions of commons logging in the same runtime Wednesday, August 28, 13
  • 31. All Content and Rights Reserved (2013) Implementation Changes ✤ In general, things are less ‘drastic’ and only involve implementation changes ✤ For example, include date in Printer.print() ✤ Implementation changes must be transparent to consuming clients ✤ Re-compilation of client should not be needed ✤ Should be incorporated dynamically ✤ SERVICE ORIENTED IMPLEMENTATION Wednesday, August 28, 13
  • 32. All Content and Rights Reserved (2013) Implementation Changes Previously, we ran into a scenario where we needed to change the interface of a bun- dle. Life isn’t always so dramatic, and most commonly you may need to change the implementation of a bundle and not its exposed interface. Let’s look again at our first version of the Printer class, from section 2.1. We’d like to change it, as shown in the following listing, so that each printed message gets time- stamped with the current time. package manning.osgi.helloworld; import java.text.DateFormat; import java.util.Date; public class Printer { private static final String SEPARATOR = ": "; public void print(String message) { System.out.println(getCurrentTime() + SEPARATOR + message); } private String getCurrentTime() { return DateFormat.getTimeInstance(DateFormat.LONG). format(new Date()); } } You know the drill. Create a new version of bundle helloworld, and then as usual pro- vision it in Felix. Here’s where it starts getting interesting. When would the existing client bundles pick up this new version? For bundle helloworld.client to be able to Listing 2.5 The Printer service implementation Wednesday, August 28, 13
  • 33. All Content and Rights Reserved (2013) Implementation Changes Previously, we ran into a scenario where we needed to change the interface of a bun- dle. Life isn’t always so dramatic, and most commonly you may need to change the implementation of a bundle and not its exposed interface. Let’s look again at our first version of the Printer class, from section 2.1. We’d like to change it, as shown in the following listing, so that each printed message gets time- stamped with the current time. package manning.osgi.helloworld; import java.text.DateFormat; import java.util.Date; public class Printer { private static final String SEPARATOR = ": "; public void print(String message) { System.out.println(getCurrentTime() + SEPARATOR + message); } private String getCurrentTime() { return DateFormat.getTimeInstance(DateFormat.LONG). format(new Date()); } } You know the drill. Create a new version of bundle helloworld, and then as usual pro- vision it in Felix. Here’s where it starts getting interesting. When would the existing client bundles pick up this new version? For bundle helloworld.client to be able to Listing 2.5 The Printer service implementation Interface and implementation dependency Wednesday, August 28, 13
  • 34. All Content and Rights Reserved (2013) Services in OSGiIn these roles, the OSGi service registry acts as the mediator, isolating the provider from the requestor. The service provider bundle owns the service interface, service properties, and service implementation. The service requestor bundle uses the service interface and service properties, but it can’t access the service implementation. A dia- gram of the OSGi service registry is shown in figure 2.8. Returning to our example, what do we need to do to change the Printer class into a Printer service? 2.4.1 The Printer service First, we must create a service interface for the Printer service. OSGi makes this a sim- ple task. We’ll just create a Java interface for the Printer class: package manning.osgi.helloworld; public interface Printer { public void print(String message); } The Printer service interface is defined by a Java interface with a single println method. No implementation is needed to define the service interface. Technically, we could use a Java class rather than a Java interface to define the OSGi service interface. In this case, the service implementation would extend the Java class instead of imple- menting the Java interface. But using a Java interface is cleaner, is easier to under- stand, and keeps coupling between the service provider and the service requestor to a minimum. Service properties Service implementation Service properties Figure 2.8 The service provider bundle registers the service interface, service properties, and service implementation into the OSGi service registry. The service requestor bundle retrieves the service interface and the service properties from the OSGi service registry. Services and loose coupling Next, we need a Java object to serve as the service implementation. Versio the Printer class is almost good enough; we just need to change it so that ments the service interface, as shown here. package manning.osgi.helloworld.impl; import java.text.DateFormat; import java.util.Date; import manning.osgi.helloworld.Printer; public class PrinterImpl implements Printer { private static final String SEPARATOR = ": "; public void print(String message) { System.out.println(getCurrentTime() + SEPARATOR + message); } private String getCurrentTime() { return DateFormat.getTimeInstance(DateFormat.LONG). format(new Date()); } } First, the service implementation must implement (or extend) the service in Second, it’s important to use a different Java package for the implementati what is used for the interface. The package used by the interface need exported, whereas we don’t want to export the package used by the impleme Otherwise, we might not be able to change the implementation easily witho stalling the clients. TIP Use different packages for the service interface and service implemen Listing 2.6 Upgraded Printer service implementation Wednesday, August 28, 13
  • 35. All Content and Rights Reserved (2013) Services in OSGiIn these roles, the OSGi service registry acts as the mediator, isolating the provider from the requestor. The service provider bundle owns the service interface, service properties, and service implementation. The service requestor bundle uses the service interface and service properties, but it can’t access the service implementation. A dia- gram of the OSGi service registry is shown in figure 2.8. Returning to our example, what do we need to do to change the Printer class into a Printer service? 2.4.1 The Printer service First, we must create a service interface for the Printer service. OSGi makes this a sim- ple task. We’ll just create a Java interface for the Printer class: package manning.osgi.helloworld; public interface Printer { public void print(String message); } The Printer service interface is defined by a Java interface with a single println method. No implementation is needed to define the service interface. Technically, we could use a Java class rather than a Java interface to define the OSGi service interface. In this case, the service implementation would extend the Java class instead of imple- menting the Java interface. But using a Java interface is cleaner, is easier to under- stand, and keeps coupling between the service provider and the service requestor to a minimum. Service properties Service implementation Service properties Figure 2.8 The service provider bundle registers the service interface, service properties, and service implementation into the OSGi service registry. The service requestor bundle retrieves the service interface and the service properties from the OSGi service registry. Services and loose coupling Next, we need a Java object to serve as the service implementation. Versio the Printer class is almost good enough; we just need to change it so that ments the service interface, as shown here. package manning.osgi.helloworld.impl; import java.text.DateFormat; import java.util.Date; import manning.osgi.helloworld.Printer; public class PrinterImpl implements Printer { private static final String SEPARATOR = ": "; public void print(String message) { System.out.println(getCurrentTime() + SEPARATOR + message); } private String getCurrentTime() { return DateFormat.getTimeInstance(DateFormat.LONG). format(new Date()); } } First, the service implementation must implement (or extend) the service in Second, it’s important to use a different Java package for the implementati what is used for the interface. The package used by the interface need exported, whereas we don’t want to export the package used by the impleme Otherwise, we might not be able to change the implementation easily witho stalling the clients. TIP Use different packages for the service interface and service implemen Listing 2.6 Upgraded Printer service implementation interface implementação Wednesday, August 28, 13
  • 36. All Content and Rights Reserved (2013) Services in OSGi interface implementação Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.2 Export-Package: manning.osgi.helloworld;version=1.2 Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.impl Bundle-Version: 1.0 Import-Package: manning.osgi.helloworld;version=1.2 Wednesday, August 28, 13
  • 37. All Content and Rights Reserved (2013) Services in OSGi interface implementação Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.2 Export-Package: manning.osgi.helloworld;version=1.2 Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.impl Bundle-Version: 1.0 Import-Package: manning.osgi.helloworld;version=1.2 Do not export implementation Wednesday, August 28, 13
  • 38. All Content and Rights Reserved (2013) Services in OSGi Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.client Bundle-Version: 1.0 Import-Package: manning.osgi.helloworld;version=1.2 interface implementação cliente Wednesday, August 28, 13
  • 39. All Content and Rights Reserved (2013) Services in OSGi Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.client Bundle-Version: 1.0 Import-Package: manning.osgi.helloworld;version=1.2 Do not import implementation interface implementação cliente Wednesday, August 28, 13
  • 40. All Content and Rights Reserved (2013) Service Repository ✤ Our system has three bundles: ✤ helloworld: provides Printer interface ✤ helloworld.impl: provides Printer implementation ✤ helloworld.client: consumes Printer service ✤ Now we need a way of the consumer finding the service itself! Wednesday, August 28, 13
  • 41. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) Service Repository 40 CHAPTER 2 An OSGi framework primer In these roles, the OSGi service registry acts as the mediator, isolating the provi from the requestor. The service provider bundle owns the service interface, ser properties, and service implementation. The service requestor bundle uses the ser interface and service properties, but it can’t access the service implementation. A gram of the OSGi service registry is shown in figure 2.8. Returning to our example, what do we need to do to change the Printer class i a Printer service? Service properties Requestor Provider OSGi service registry Register/unregisterRetrieve/release Service implementation Service interface Service properties Service interface Figure 2.8 The service provider bundle registers the service interface, service properties, and service implementation into the OSGi service registry. The service requestor bundle retrieves the service interface and the service properties from the OSGi service registry. ✤ OSGi service: ✤ Interface ✤ Implementation ✤ Properties ✤ Providers and consumers interact through the Service Repository Wednesday, August 28, 13
  • 42. All Content and Rights Reserved (2013) Service Providers42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced Wednesday, August 28, 13
  • 43. All Content and Rights Reserved (2013) Service Providers42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced We will take a look at the BundleActivator and the BundleContext later Wednesday, August 28, 13
  • 44. All Content and Rights Reserved (2013) Service Consumers public void start(BundleContext bundleContext) throws Exception { this.bundleContext = bundleContext; serviceReference = bundleContext.getServiceReference(Printer.class.getName()); if (serviceReference != null) { Printer printer = (Printer) bundleContext.getService(serviceReference); if (printer != null) { printer.print("Hello..."); } } } Wednesday, August 28, 13
  • 45. All Content and Rights Reserved (2013) Advantages vant to their tasks. For example, they don’t even have to know about other entities we’ve discussed, such as auditors. NOTE Modular systems are composed of modules that yield simple, highly cohesive interfaces. Furthermore, we’re able to leverage the OSGi service layer; we had to implement only a few lines of code to retrieve an auction service that had the proper terms, such as the proper style and duration. Albeit being somewhat obvious, we can use the OSGi service registry as a general registry of application services and thus implement a common design pattern known as the registry design pattern, shown in figure 3.4. Registry design pattern Intent—Allows a consumer to find a service by knowing only its name or some attribute of the service Participants—Consuming bundle, Registry service, Provider bundle Structure—Consuming bundle searches the registry using a name or attributes for a particular service that has been registered by a provider bundle Consequences—Consuming bundle doesn't know who provides the services or care how Known uses—Data source service (see chapter 8) Related patterns—Whiteboard pattern Application bundle Service OSGi service registry Provider bundle Retrieve Register Figure 3.4 In the registry design pattern, the application bundle retrieves the application service from the OSGi service registry, and the providing bundle registers the service objects. ✤ Clear separation of concerns between providers and consumers ✤ Dynamic ✤ Change of implementation without impacting consumer ✤ Service Repository Wednesday, August 28, 13
  • 46. All Content and Rights Reserved (2013) ✤ Data encapsulation ✤ Dealing with changes ✤ Extensibility ✤ Building infrastructures Agenda Modularization Grade Wednesday, August 28, 13
  • 47. All Content and Rights Reserved (2013) Extensibility "Technology does not drive change - it enables change." - Unknown Wednesday, August 28, 13
  • 48. All Content and Rights Reserved (2013) Service Selection being exchanged with other parties. A user can the message. Hash functions used for this purpose have th sages that differ will have the same hash value. T sage and its hash value to a receiver, which can the received message. The generated hash valu only if the message has not been altered. We can define our fingerprint service as follo public interface FingerprintService { byte [] hash(String input); } There are several implementations of hash func and MD5 algorithms, both invented by Rivest. attacks for it, whereas MD5 is slower but safer. M differences; they just want to get some default bly be MD5. When dealing with security, we alw users who may be more educated on the subjec rithm. How do you solve this problem in the OS First of all, you should register these two diffe ing some additional service property that high you can define a PERFORMANCE property whose MD4 MD5 Rápido Segurança baixa Devagar Segurança alta FingerprintService Fast Less secure Slow More secure Wednesday, August 28, 13
  • 49. All Content and Rights Reserved (2013) Service Selection MD4 MD5 Rápido Segurança baixa Devagar Segurança alta FingerprintService Diferent policies per customer Fast Less secure Slow More secure Wednesday, August 28, 13
  • 50. All Content and Rights Reserved (2013) Service Properties Dictionary<String, Object> md5Properties = new Hashtable<String, Object>(); md5Properties.put("PERFORMANCE", "SLOW"); md5Properties.put("ALGORITHM", "MD5"); md5Properties.put("SECURITY_LEVEL", "HIGH"); registration = bundleContext.registerService( FingerprintService.class.getName(), MD5FingerprintServiceImpl, md5Properties ); Dictionary<String, Object> md4Properties = new Hashtable<String, Object>(); md4Properties.put("PERFORMANCE", "FAST"); md4Properties.put("ALGORITHM", "MD4"); md4Properties.put("SECURITY_LEVEL", "MEDIUM"); registration = bundleContext.registerService( FingerprintService.class.getName(), MD4FingerprintServiceImpl, md4Properties ); Properties associated to FingerprintService Service properties are key- value pairs Wednesday, August 28, 13
  • 51. All Content and Rights Reserved (2013) Filters String filter = "(&(objectClass=manning.osgi.fingerprint.FingerprintService)" + " (PERFORMANCE=FAST)" + ")"; ServiceReference[] serviceReferences = bundleContext.getServiceReferences(null, filter); if (serviceReferences != null) { FingerprintService service = (FingerprintService) bundleContext.getService(serviceReferences[0]); // } Service filters specified as in LDAP Wednesday, August 28, 13
  • 52. All Content and Rights Reserved (2013) LDAP sively binary and are specified in prefix form, so you can associate any numbe operations with them. The last operator is unary as expected; that is, it modifies a gle operation. The parse tree shown in figure 4.14 describes an OSGi filter that verifies if all conditions are met. You can associate several operations together using a single expression opera For example, consider the following Java expression: if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3)) { … } This can be expressed using the following OSGi filter: (&(attr1=value1)(attr2=value2)(attr3=value3)) Also, the slightly more complicated Java expression, if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3))) { … } can be expressed using the following OSGi filter: (&(attr1=value1)(|(attr2=value2)(attr3=value3))) So there you have it; you’re now an expert on the OSGi filter syntax. Don’t feel though if you still prefer the infix style, such as that used in Java, instead of the pr style used here. You’re not alone. In the next section, we’ll look at how to distinguish services that share the sa tion (not) operator (!). The first two operators, contrary to the norm sively binary and are specified in prefix form, so you can associate operations with them. The last operator is unary as expected; that is, i gle operation. The parse tree shown in figure 4.14 describes an OSGi filter that v conditions are met. You can associate several operations together using a single expre For example, consider the following Java expression: if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3)) This can be expressed using the following OSGi filter: (&(attr1=value1)(attr2=value2)(attr3=value3)) Also, the slightly more complicated Java expression, if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3) can be expressed using the following OSGi filter: (&(attr1=value1)(|(attr2=value2)(attr3=value3))) So there you have it; you’re now an expert on the OSGi filter syntax. though if you still prefer the infix style, such as that used in Java, inste style used here. You’re not alone. In the next section, we’ll look at how to distinguish services that tion (not) operator (!). The first two operators, contrary to the norm, aren’t exc sively binary and are specified in prefix form, so you can associate any number operations with them. The last operator is unary as expected; that is, it modifies a s gle operation. The parse tree shown in figure 4.14 describes an OSGi filter that verifies if all t conditions are met. You can associate several operations together using a single expression operat For example, consider the following Java expression: if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3)) { … } This can be expressed using the following OSGi filter: (&(attr1=value1)(attr2=value2)(attr3=value3)) Also, the slightly more complicated Java expression, if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3))) { … } can be expressed using the following OSGi filter: (&(attr1=value1)(|(attr2=value2)(attr3=value3))) So there you have it; you’re now an expert on the OSGi filter syntax. Don’t feel b though if you still prefer the infix style, such as that used in Java, instead of the pre style used here. You’re not alone. tion (not) operator (!). The first two operators, contrary to the norm sively binary and are specified in prefix form, so you can associate operations with them. The last operator is unary as expected; that is, i gle operation. The parse tree shown in figure 4.14 describes an OSGi filter that v conditions are met. You can associate several operations together using a single expre For example, consider the following Java expression: if ((attr1 == value1) && (attr2 == value2) && (attr3 == value3)) This can be expressed using the following OSGi filter: (&(attr1=value1)(attr2=value2)(attr3=value3)) Also, the slightly more complicated Java expression, if ((attr1 == value1) && ((attr2 == value2) || (attr3 == value3) can be expressed using the following OSGi filter: (&(attr1=value1)(|(attr2=value2)(attr3=value3))) So there you have it; you’re now an expert on the OSGi filter syntax. though if you still prefer the infix style, such as that used in Java, inste infix (e.g. Java) prefix Wednesday, August 28, 13
  • 53. All Content and Rights Reserved (2013) LDAP ✤ Comparison operators: ✤ =, >=, <=, ~= (approximation), =* (existence) ✤ Logical operators: ✤ & (conjunction) ✤ | (disjunction) ✤ ! (negation) ✤ Lists: true if matches at least one element Wednesday, August 28, 13
  • 54. All Content and Rights Reserved (2013) Service Priority MD4 MD5 Rápido Segurança baixa Devagar Segurança alta FingerprintService Which service to use? Fast Less secure Slow More secure Wednesday, August 28, 13
  • 55. All Content and Rights Reserved (2013) Service Priority MD4 MD5 Rápido Segurança baixa Devagar Segurança alta FingerprintService Which service to use? Selection is not deterministic Fast Less secure Slow More secure Wednesday, August 28, 13
  • 56. All Content and Rights Reserved (2013) Service Priority MD4 MD5 Rápido Segurança baixa Devagar Segurança alta FingerprintService Which service to use? Selection is not deterministic Use priorities to make selection deterministic. For example, select safest algorithm by default Fast Less secure Slow More secure Wednesday, August 28, 13
  • 57. All Content and Rights Reserved (2013) Service Priority 119Decoupling bundles using services In this case, you want to avoid this nondeterminism; you’d like the MD5 service implementation to have priority over the MD4 implementation. This can be done through the use of the predefined SERVICE_RANKING property, whose value is of type Integer. When multiple qualifying service implementations exist, the OSGi frame- work selects the one with the highest SERVICE_RANKING property, as shown in the fol- lowing listing. Dictionary<String, Object> md5Properties = new Hashtable<String, Object>(); md5Properties.put("PERFORMANCE", "SLOW"); md5Properties.put("ALGORITHM", "MD5"); md5Properties.put("SECURITY_LEVEL", "HIGH"); md5Properties.put(Constants.SERVICE_RANKING, 10); registration = bundleContext.registerService( FingerprintService.class.getName(), MD5FingerprintServiceImpl, md5Properties ); Dictionary<String, Object> md4Properties = new Hashtable<String, Object>(); md4Properties.put("PERFORMANCE", "FAST"); md4Properties.put("ALGORITHM", "MD4"); md4Properties.put("SECURITY_LEVEL", "MEDIUM"); md4Properties.put(Constants.SERVICE_RANKING, 5); registration = bundleContext.registerService( FingerprintService.class.getName(), MD4FingerprintServiceImpl, md4Properties ); The MD5 service implementation has a service ranking of 10 B, whereas the MD4 ser- vice implementation has a ranking of 5 c. Thus the OSGi framework selects the MD5 Listing 4.7 Service rankings for the fingerprint service Higher service priorityb Lower service priorityc Wednesday, August 28, 13
  • 58. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) Plugins ✤ How to add new security algorithms for the Fingerprint application? ✤ We need a systematic approach to support application plugins. Wednesday, August 28, 13
  • 59. application bundle service OSGI service registry framework bundle retrieve register All Content and Rights Reserved (2013) Whiteboard design pattern ✤ Roles: ✤ Provider (plugin) ✤ Consumer (application) Wednesday, August 28, 13
  • 60. All Content and Rights Reserved (2013) Whiteboard design pattern ✤ Application looks for all registered FingerprintService services ✤ Out-of-the-box: MD4, MD5 ServiceReference[] serviceReferences = bundleContext.getAllServiceReferences( FingerprintService.class.getName(), null); Wednesday, August 28, 13
  • 61. All Content and Rights Reserved (2013) Whiteboard design pattern ✤ Next, application registers to be notified when a new service is added or removed dynamically String filter = "(objectClass=" + FingerprintService.class.getName() + ")"; bundleContext.addServiceListener(new MyServiceListener(bundleContext), filter); Wednesday, August 28, 13
  • 62. All Content and Rights Reserved (2013) ServiceListener public class MyServiceListener implements ServiceListener { private BundleContext bundleContext; private Map<String, FingerprintService> services = new HashMap<String, FingerprintService>(); public MyServiceListener(BundleContext bundleContext) { this.bundleContext = bundleContext; } public void serviceChanged(ServiceEvent serviceEvent) { ServiceReference ref = serviceEvent.getServiceReference(); switch (serviceEvent.getType()) { case ServiceEvent.REGISTERED: { FingerprintService newService = (FingerprintService) bundleContext.getService(ref); services.put((String) ref.getProperty("ALGORITHM"), newService); break; } case ServiceEvent.UNREGISTERING: { services.remove((String) ref.getProperty("ALGORITHM")); break; } } } Wednesday, August 28, 13
  • 63. All Content and Rights Reserved (2013) Whiteboard design pattern ✤ Providers (Bundle Plugin) simply register new service implementations as needed ✤ It is not necessary for provider (plugin) to learn any new API properties.put("PERFORMANCE", "SLOW"); properties.put("ALGORITHM", "MD6"); properties.put("SECURITY_LEVEL", "HIGHEST"); registration = bundleContext.registerService( FingerprintService.class.getName(), MD6FingerprintServiceImpl, properties ); Wednesday, August 28, 13
  • 64. All Content and Rights Reserved (2013) Advantages ✤ OSGi’s service architecture allows one to create applications that can be systematically extended ✤ Service properties ✤ Service selection and filtering ✤ Whiteboard design-pattern ✤ The onus of extensibility lies on infrastructure and not on plugin Wednesday, August 28, 13
  • 65. All Content and Rights Reserved (2013) ✤ Data encapsulation ✤ Dealing with changes ✤ Extensibility ✤ Building infrastructures Agenda Modularization Grade Wednesday, August 28, 13
  • 66. All Content and Rights Reserved (2013) Building infrastructures "Ah, to build, to build! That is the noblest art of all arts." - Henry Longfellow, 1807 Wednesday, August 28, 13
  • 67. All Content and Rights Reserved (2013) The OSGi Platform 7The OSGi technology guration Admin Declarative serviceDeployment Admin User-defined services and applications OSGI framework OSGI service platform Java Dynamic Java modules (bundles) Service management Figure 1.5 The OSGi Service Platform comprises the OSGi framework and the OSGI services. ✤ A modular platform in itself ✤ OSGi has several layers: ✤ The framework, the core services, the optional services, and the application layer Wednesday, August 28, 13
  • 68. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) The OSGi Framework ✤ Execution environment: ✤ Java SE, Java ME, e other environments ✤ Module, Lifecycle layers ✤ Bundles ✤ BundleContext ✤ Service layer ✤ OSGi services function normally, but now it uses the new Printer service implementation. Congrat- ulations, you changed the implementation of a running application! This simple hello world application allowed us to investigate several important fea- tures from OSGi, ranging from versioning, to package restriction and accessibility, to service management. In the next section, we’ll discuss the role of these features in the overall architecture of the OSGi framework. 2.5 The OSGi layered architecture The OSGi framework is implemented using a layered architecture, depicted in figure 2.11. The bottom layer is the execution environment. Even though the OSGi framework is running on top of a JVM, the JVM itself can have different versions and profiles. For instance, there’s a Java Micro Edition of the JVM, which is named Java ME; there’s also a Java Standard Edition and a Java Enterprise Edition. On top of that, each edition may have several versions, such as Java SE 1.5 and 1.6. Because the developer can be using bundles provided by different ven- Execution environment Module layer Lifecycle layer Service layer Security Figure 2.11 OSGi’s layered architecture is composed of four layers: the execution environment, the module layer, the lifecycle layer, and the serviceWednesday, August 28, 13
  • 69. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) Optional Services ✤ Residencial ✤ Enterprise ✤ Management ✤ Configuration ✤ Distribution ✤ Data Access Examples of enterprise features, as shown in figure 1.6, are the following: I Management and configuration—This group includes the Configuration A service as well as the JMX Management Model service and the Metatype se I Distribution—This feature allows the communication of end points bet remote instances of OSGi framework instances. Some of the services in group are the Remote Service and the SCA Configuration Type. I Data access—This feature includes support for JDBC, JPA, and JTA and allow manipulation of persisted objects. Before getting into the details of the OSGi technology itself, you should under the high-level benefits of using OSGi as your development platform. We addres topic in the next section. OSGi framework JMX Metatype Admin guration Admin guration JTA JPA JDBC Data access DistributionRemote service SCA Figure 1.6 Enterprise OSGi consists of the OSGi framework and several OSGi services; together they provide enterprise features. Wednesday, August 28, 13
  • 70. All Content and Rights Reserved (2013) Core Services ✤ Permission Admin Service ✤ URL Handlers Service ✤ Resolver Hook Service ✤ Bundle Hook Service ✤ Service Hook Service ✤ Weaving Hook Wednesday, August 28, 13
  • 71. All Content and Rights Reserved (2013) Enterprise OSGi & JEE ✤ OSGi makes use of several JEE standards: ✤ HTTP Servlets, JMX, JNDI, JTA, JPA, JDBC, JCA, etc ✤ Specific modifications needed to conform to the OSGi environment, for example, such as the removal of static elements ✤ Also uses other enterprise specifications: ✤ SCA (Software Component Architecture) ✤ And defines some of its own: ✤ Meta-type, Configuration, etc. Wednesday, August 28, 13
  • 72. All Content and Rights Reserved (2013) Implementations ✤ Framework ✤ Eclipse Equinox ✤ Apache Felix ✤ Knopflerfish ✤ Enterprise ✤ Eclipse Gemini/Virgo ✤ Apache Aries Wednesday, August 28, 13
  • 73. All Content and Rights Reserved (2013) Next, you need to install the helloworld and helloworld.client bundles into the framework. We have two bundles, or JAR files: helloworld.jar and helloworld.client.jar. The archived content of the helloworld.jar bundle is META-INF/MANIFEST.MF manning/osgi/helloworld/Printer.class And for the helloworld.client.jar, it’s META-INF/MANIFEST.MF manning/osgi/helloworld/client/PrinterClient.class manning/osgi/helloworld/client/PrinterClientActivator.class Copy helloworld.jar and helloworld.client.jar to the Felix installation to make it easier to reference the files. Create a dist directory underneath the install directory, and place the JAR files there. NOTE Don’t place the hello world bundles in the bundle directory, because this directory is by default configured as Felix’s autodeploy directory, a fea- ture that we’ll talk about in later chapters. Now, you can install these bundles with the install command typed in the Felix shell: g! felix:install file:dist/helloworld.jar Bundle ID: 5 g! felix:install file:dist/helloworld.client.jar Bundle ID: 6 Each time you install a bundle, Felix provides a unique bundle ID, which is needed later by the other commands. NOTE The Gogo shell commands, such as felix:install, can be specified without the prefix (that is, felix, obr, gogo) if they’re unique. But generally it’s good to keep the prefix because it helps with backward compatibility for future versions of Felix. Did you expect to see “Hello World” printed? We’re almost there. Felix ✤ Bootstrap 23Running and testing OSGi Open a shell, and change directory to Felix’s installation home. You can run Felix with the following command: felix-framework-3.0.6$ java -jar bin/felix.jar ____________________________ Welcome to Apache Felix Gogo g! Conventions Before we continue, here are some assumptions and conventions you should know: I We’ll assume that the Java program is in your shell’s path. This is generally the case. I We’ll be using JDK 1.5.0_16 to run the examples. I We’ll be using UNIX commands, as executed in a bash shell, as the convention. Thanks to Java, we’re mostly isolated from the operating system, except for a few file-related commands. I If you’re using Windows, you may have to replace the forward slash (/) with a backward slash () in file-related commands. As an example, this command, java -jar bin/felix.jar should be changed to the following in a Windows environment: ✤ Installing bundles ✤ Activating bundles CHAPTER 2 An OSGi framework primer 4 Starting the bundles in Felix To start a bundle, you must use the start command in the Felix shell. As expected, the start command triggers the BundleActivator.start() callback. Let’s try it out: g! felix:start 4 g! felix:start 5 Note that you must use the ID returned by the install command. You should get a stack trace and still no “Hello World” message, which probably isn’t what you expected. If you go down the stack, you’ll eventually notice the follow-Wednesday, August 28, 13
  • 74. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) Bundle lifecycle ✤ Installation: ✤ Resolves the export and import package contracts ✤ Activation: ✤ Register the OSGi services during invocation of BundleActivator.start() callback Frameworks Life Cycle Layer Figure 4.3 State diagram Framework 4.2.4 Initializing the Framework Before the framework can be used, it must be initialized. Initialization is caused by the in implicitly the start method. An initialized framework is operational, but none of its bun active. This is reflected in the STARTING state. As long as the framework is in this state, INSTALLED STARTING STOPPING ACTIVE init newFramework RESOLVED update init, start stop update stop start stop init start stop update updatestart init start stop update init Wednesday, August 28, 13
  • 75. All Content and Rights Reserved (2013) Helloworld revisited... Bundle ID: 70 g! felix:start 70 g! 11:06:54 PM PST: Hello... And the problem is still there. But in this case, if you refresh the helloworld.client bundle, which is something you won’t like to do, you’ll get the right message. The issue is that the PrinterImpl class is located in the same bundle as the Printer service interface. When you uninstall the PrinterImpl class, you’re also unin- stalling the Printer class, which is used in the contract with the helloworld.client bundle. Because the packages can’t be changed without refreshing the bundle, what happens is that the OSGi framework keeps around an old version of the helloworld bundle associated with the helloworld.client bundle and will only pick up the new version of helloworld when the packages are resolved again. This behavior is vendor specific, which makes it an even bigger problem. What you need to do to avoid all the confusion is to move the PrinterImpl class to another bundle separate from the bundle that includes the service interface. You do this by creating a third bundle named helloworld.impl_1.4.0.jar, which includes the PrinterImpl and PrinterActivator classes, as shown in figure 2.10. Printer helloworld_1.4.0 helloworld.client_1.1.0 PrinterClientActivator RunnablePrinterClient helloworld.impl_1.4.0 PrinterActivator PrinterImpl Figure 2.10 Bundle helloworld version 1.4 includes the Printer class. Bundle helloworld.impl version 1.4 includes the PrinterActivator and PrinterImpl classes. Bundle helloworld.client version 1.1 includes the PrinterClientActivator and ✤ Bundles: ✤ API: helloworld ✤ Implementation: helloworld.impl ✤ Client: helloworld.client Wednesday, August 28, 13
  • 76. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) BundleActivator42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced Wednesday, August 28, 13
  • 77. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) BundleActivator 42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Manifest-Version: 1.0 Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced 51Services and loose coupling The bundle helloworld.impl needs to import the package manning.osgi. helloworld, but it doesn’t need to export any packages. The MANIFEST.MF file for helloworld.impl_1.4.0.jar is shown here: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.impl Bundle-Version: 1.4 Import-Package: manning.osgi.helloworld;version=1.4.0,org.osgi.framework Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator In the helloworld_1.4.0.jar bundle, we keep only the Printer class, and we no longer need to import the org.osgi.framework package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.4 Export-Package: manning.osgi.helloworld;version=1.4.0 Let’s retest: g! felix:lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (3.0.6) 1|Active | 1|Apache Felix Bundle Repository (1.6.2) 2|Active | 1|Apache Felix Gogo Command (0.6.1) 3|Active | 1|Apache Felix Gogo Runtime (0.6.1) 4|Active | 1|Apache Felix Gogo Shell (0.6.1) g! felix:install file:dist/helloworld_1.4.0.jar Bundle ID: 63 g! felix:start 63 g! felix:install file:dist/helloworld.impl_1.4.0.jarWednesday, August 28, 13
  • 78. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) BundleActivator 42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Manifest-Version: 1.0 Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced 51Services and loose coupling The bundle helloworld.impl needs to import the package manning.osgi. helloworld, but it doesn’t need to export any packages. The MANIFEST.MF file for helloworld.impl_1.4.0.jar is shown here: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.impl Bundle-Version: 1.4 Import-Package: manning.osgi.helloworld;version=1.4.0,org.osgi.framework Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator In the helloworld_1.4.0.jar bundle, we keep only the Printer class, and we no longer need to import the org.osgi.framework package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.4 Export-Package: manning.osgi.helloworld;version=1.4.0 Let’s retest: g! felix:lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (3.0.6) 1|Active | 1|Apache Felix Bundle Repository (1.6.2) 2|Active | 1|Apache Felix Gogo Command (0.6.1) 3|Active | 1|Apache Felix Gogo Runtime (0.6.1) 4|Active | 1|Apache Felix Gogo Shell (0.6.1) g! felix:install file:dist/helloworld_1.4.0.jar Bundle ID: 63 g! felix:start 63 g! felix:install file:dist/helloworld.impl_1.4.0.jarWednesday, August 28, 13
  • 79. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) BundleActivator 42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Manifest-Version: 1.0 Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced 51Services and loose coupling The bundle helloworld.impl needs to import the package manning.osgi. helloworld, but it doesn’t need to export any packages. The MANIFEST.MF file for helloworld.impl_1.4.0.jar is shown here: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld.impl Bundle-Version: 1.4 Import-Package: manning.osgi.helloworld;version=1.4.0,org.osgi.framework Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator In the helloworld_1.4.0.jar bundle, we keep only the Printer class, and we no longer need to import the org.osgi.framework package: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.4 Export-Package: manning.osgi.helloworld;version=1.4.0 Let’s retest: g! felix:lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (3.0.6) 1|Active | 1|Apache Felix Bundle Repository (1.6.2) 2|Active | 1|Apache Felix Gogo Command (0.6.1) 3|Active | 1|Apache Felix Gogo Runtime (0.6.1) 4|Active | 1|Apache Felix Gogo Shell (0.6.1) g! felix:install file:dist/helloworld_1.4.0.jar Bundle ID: 63 g! felix:start 63 g! felix:install file:dist/helloworld.impl_1.4.0.jarWednesday, August 28, 13
  • 80. All Content and Rights Reserved (2013) Simplifying the programming model 42 CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced Wednesday, August 28, 13
  • 81. All Content and Rights Reserved (2013) Simplifying the programming model Wednesday, August 28, 13
  • 82. All Content and Rights Reserved (2013) Simplifying the programming model CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.4 Export-Package: manning.osgi.helloworld;version=1.4.0 Import-Package: org.osgi.framework Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator In the start method, you instantiate the service by specifying its interface B and implementation c, and you register it in the service registry using the bundle- Context.registerService() method. This method returns a serviceRegistration object, which represents the registered service. Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced Wednesday, August 28, 13
  • 83. All Content and Rights Reserved (2013) Simplifying the programming model <blueprint xmlns="http://www.osgi.org/xmlns/ blueprint/v1.0.0"> <bean id="impl" class="manning.osgi.helloworld.impl.PrinterImpl" /> <service interface="manning.osgi.helloworld.Printer" ref="impl" /> </blueprint> CHAPTER 2 An OSGi framework primer package manning.osgi.helloworld.impl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import manning.osgi.helloworld.Printer; public class PrinterActivator implements BundleActivator { private ServiceRegistration serviceRegistration; public void start(BundleContext bundleContext) throws Exception { serviceRegistration = bundleContext.registerService( Printer.class.getName(), new PrinterImpl(), null); } public void stop(BundleContext bundleContext) throws Exception { serviceRegistration.unregister(); } } You can archive the Printer interface, the Printer implementation, and the PrinterActivator classes into version 1.4.0 of the helloworld bundle: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: helloworld Bundle-Version: 1.4 Export-Package: manning.osgi.helloworld;version=1.4.0 Import-Package: org.osgi.framework Bundle-Activator: manning.osgi.helloworld.impl.PrinterActivator In the start method, you instantiate the service by specifying its interface B and implementation c, and you register it in the service registry using the bundle- Context.registerService() method. This method returns a serviceRegistration object, which represents the registered service. Listing 2.7 Registering the Printer service in the OSGi service registry Printer service interface b Printer service implementationc Unregister serviced Wednesday, August 28, 13
  • 84. All Content and Rights Reserved (2013) Blueprint (Spring dm) ✤ Bundle client (helloworld.client) ✤ META-INF/spring/blueprint.xml <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <reference id="printer" interface="manning.osgi.helloworld.Printer" /> <bean id="client" class="manning.osgi.helloworld.PrinterClient" > <property name="printerService" ref="printer" /> </bean> </blueprint> Wednesday, August 28, 13
  • 85. All Content and Rights Reserved (2013) Blueprint (Spring dm) ✤ Bundle client (helloworld.client) ✤ META-INF/spring/blueprint.xml <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <reference id="printer" interface="manning.osgi.helloworld.Printer" /> <bean id="client" class="manning.osgi.helloworld.PrinterClient" > <property name="printerService" ref="printer" /> </bean> </blueprint> Specification of the application components Wednesday, August 28, 13
  • 86. All Content and Rights Reserved (2013) Vertical Solutions ✤ OSGi allows the creation of layered frameworks: ✤ Spring-dm ✤ Service integration ✤ Creation of new programming models Wednesday, August 28, 13
  • 87. All Content and Rights Reserved (2013) Simplifying the FingerprintService <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <fingerprint id="fingerprint" type="MD4" /> <bean id="client" class="manning.osgi.FingerprintClient" /> </blueprint> public class FingerprintClient { public void setHash(byte [] hash) { // } } Infrastructure automatically calls setHash() using toString() in the client instance. client.setHash( fingerprint.hash(client.toString())) Wednesday, August 28, 13
  • 88. All Content and Rights Reserved (2013) Simplifying the FingerprintService ✤ Customer only has to create JAR (bundle) with: ✤ FingerprintClient class ✤ blueprint.xml ✤ MANIFEST.MF with OSGi header entries ✤ Bundle-SymbolicName: fingerprintClient ✤ In this case, it is not necessary for the customer to import a particular package or to make use of a particular service. public class FingerprintClient { public void setHash(byte [] hash) { // } } Wednesday, August 28, 13
  • 89. All Content and Rights Reserved (2013) OtherVertical Bundles idea of containers and application bundles. 13.1 Application bundles and their containers As you’ve seen in the previous chapters, a common pattern for enabling a bundle with a new feature is to annotate the bundle’s manifest file. For example, to enable a bun- dle to persist its Java classes, you can add the Meta-Persistence header entry to its MANIFEST.MF file. The following table summarizes some of the standard manifest header entries used to create feature-specific powered bundles, or, perhaps a bit more col- orful, bundle flavors. Table 13.1 Flavored bundles Name Description Manifest header WAB Web application bundle Web-ContextPath Persistence bundle Bundle with persistence units Meta-Persistence SCA config bundle Bundle with SCA configuration SCA-Configuration Component bundle Bundle with declarative components Service-Component Blueprint bundle Bundle with Blueprint components Bundle-Blueprint Endpoint bundle Bundle with endpoint descriptions Remote-Service Application bundles Table 13.1 lists just a few examples of the different flavors of bundles that exist. Some of them have been discussed in previous chapters, but some of them are out of theWednesday, August 28, 13
  • 90. All Content and Rights Reserved (2013) Vertical Servers: Oracle Event Processing ✤ Started as a vertical server for processing events for financial markets ✤ Defines its own programming model for event processing Wednesday, August 28, 13
  • 91. All Content and Rights Reserved (2013) Vertical Servers: Oracle Event Processing Wednesday, August 28, 13
  • 92. All Content and Rights Reserved (2013) Conclusion ✤ OSGi helps in the development of systems that are: ✤ modular ✤ bundles ✤ extensible ✤ services ✤ Modular and extensible systems allows one to create their own vertical infrastructure or framework Wednesday, August 28, 13
  • 93. All Content and Rights Reserved (2013) In the trenches with OEP ✤ Use tooling, especially PMD ✤ Introspects Java classes and generates proper MANIFEST header entries for imports and exports ✤ Be careful not to overdue it and simply export and import everything. Know what you are doing when using wildcards Wednesday, August 28, 13
  • 94. All Content and Rights Reserved (2013) In the trenches with OEP ✤ Do Semantic Versioning (http://www.osgi.org/wiki/uploads/ Links/SemanticVersioning.pdf) ✤ Change minor version for implementation changes ✤ Change major version for interface changes ✤ Import as [X.Y,X+1.0) (for example: [1.2,2.0)) Wednesday, August 28, 13
  • 95. All Content and Rights Reserved (2013) In the trenches with OEP ✤ All features should have at least two bundles: an interface and an implementation bundle ✤ Some features may even more, for example, one for management, one for SPIs, etc. ✤ Also, all features should have a ‘test bundle’ that runs as a Junit test-case Wednesday, August 28, 13
  • 96. All Content and Rights Reserved (2013) In the trenches with OEP ✤ Don’t use statics, instead create singleton services ✤ Don’t use JDK’s service property files, these are just another type of ‘static’ ✤ Don’t expect to be able to cheat by using ‘Reflection’ ✤ For example, to implement a general purpose configuration system, we had to pass along the application’s (bundle) class- loader, otherwise there is infra bundles can’t see application bundle’s resources Wednesday, August 28, 13
  • 97. All Content and Rights Reserved (2013) In the trenches with OEP ✤ Getting the right order of installation and start-up is hard! ✤ Make sure your service registration and retrieval go through ServiceTracker or some other mechanism that avoids temporal cohesion ✤ Create layers of features, such as: core, domain-feature, application, etc. Wednesday, August 28, 13
  • 98. Todos os direitos reservados a Alexandre de Castro Alves / All Content and Rights Reserved (2012) Developing Modular and Extensible Systems using OSGi adcalves@gmail.com alex.alves@oracle.com http://www.manning.com/alves/ http://adcalves.wordpress.com http://www.oracle.com/technetwork/middleware/complex-event- processing/overview/index.html Wednesday, August 28, 13