OSGi bootcamp - part 1
- 2. Agenda
• Introduction to OSGi
• The core framework
• creating bundles, working with services, dealing
with the dynamics and version resolution
- 3. OSGi history
• Started as an embedded platform for the “home gateway”
• Originally under the JCP as JSR-8 (1999)
• OSGi alliance, consists of a large number of big companies, with
the following mission:
• Maintaining and publicising the OSGi specification
• Certifying implementations
• Organising events
• Current version: OSGi Release 6
- 4. OSGi releases
• R1: long ago :)
• R2: October 2001 - JES, Oscar
• R3: March 2003 - Knopflerfish
• R4: August 2005 - Equinox
• 4.1: May 2007 - small updates
• 4.2: September 2009 - moving to the Enterprise
• 4.3: April 2011 - generics & framework hooks
• R5: June 2012 - generic resource/capability model
• R6: June 2014 - framework updates
• R7: 2016? - IoT ?
- 5. OSGi today
OSGi technology is the dynamic module system for Java™
OSGi technology is Universal Middleware.
OSGi technology provides a service-oriented, component-
based environment for developers and offers standardized
ways to manage the software lifecycle. These capabilities
greatly increase the value of a wide range of computers and
devices that use the Java™ platform.
- 6. OSGi Alliance
• Expert Groups:
• core platform (CPEG)
• enterprise (EEG)
• residential (REG)
• IoT (IEG)
• Working Groups:
• marketing
• requirements
• technical steering committee
- 9. OSGi Framework Layering
Provides a publish/find/bind service
model to for bundles to
communicate in a decoupled way
service
module
life-cycle
Creates the concept of bundles that
share classes in a controlled way
according to constraints
Manages the life cycle of bundles in
a framework without requiring the
VM be restarted
- 10. Module Layer (1/3)
• A bundle is:
• a JAR file
• unit of deployment
• own class loader
• isolation
• bundle classpath
store
Store.class
Key.class
store.fs
StoreImpl.class
FileSystem.class
StreamU4l.class
bundle
store.fs.osgi
Ac4vator.class
META%INF/MANIFEST.MF
Bundle%SymbolicName::store.fs
Bundle%Version::1.0.2
Bundle%Classpath::.,:lib/fsuGl.jar
Bundle%AcGvator:
:store.fs.osgi.AcGvator
- 12. Module Layer (3/3)
ModuleBundle Bundle Bundle Bundle
exports
imports
exports
imports
exports
exports
org.apache.u5l61.0
org.apache.u5l61.1org.apache.log62.3
org.apache.db61.4
• Consistency
- ensures constraints are not
violated
• Class visibility
- exporters may include/exclude
specific classes
• Bundle fragments
- a single logical module in
multiple physical bundles
• Bundle dependencies
- Allows for tight coupling when
required
- 13. • Imagine bundle A somehow gets servlet instances
from bundle B
Importing & Exporting a
Package (1/4)
A
B
import
javax.servlet
export
javax.servlet
.class
one3copy3of
javax.servlet
- 14. • What if bundle A also wanted to get servlet instances
somehow from bundle C?
Importing & Exporting a
Package (1/4)
A
B
import
javax.servlet
export
javax.servlet
.class
one3copy3of
javax.servlet
- 15. • Bundle C could import from bundle B, but then it is
dependent on it
Importing & Exporting a
Package (2/4)
A
B
import
javax.servlet
export
javax.servlet
.class
one3copy3of
javax.servlet
C
import
javax.servlet
- 16. • Bundle C could export its own servlet package, but
bundle A could only see either C or B
Importing & Exporting a
Package (3/4)
A
C
import
javax.servlet
export
javax.servlet
.class
two3copies3of
javax.servlet
B
export
javax.servlet
.class
???
- 17. Importing & Exporting a
Package (4/4)
• Bundle C could both import and export servlet to solve
the dilemma
A
C
import
javax.servlet
export1and1import
javax.servlet
.class
B
.class
export1and1import
javax.servlet
- 18. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
Interface
package org.foo.http;
import javax.servlet;
public interface HttpService {
void registerServlet(Sting alias, Servlet servlet);
}
Metadata
Export-Package: org.foo.http; version="1.0.0"
Import-Package: javax.servlet; version="2.3.0"
- 19. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
HTTP$
service
A
import
javax.servlet
version=2.3.0
export
javax.servlet
version=2.3.0
export
org.foo.h=p
- 20. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
HTTP$
service
A
import
javax.servlet
version=2.3.0
export
javax.servlet
version=2.3.0
export
org.foo.h=p
HTTP$
client
import
org.foo.h=p
import
javax.servlet
version=2.4.0
- 21. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
HTTP$
service
A
export
javax.servlet
version=2.3.0
export
org.foo.h<p
HTTP$
client
B
export
javax.servlet
version=2.4.0
- 22. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
HTTP$
service
A
export
javax.servlet
version=2.3.0
export
org.foo.h<p
HTTP$
client
B
export
javax.servlet
version=2.4.0
This would result in a
ClassCastException,
why?
- 23. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
HTTP$
service
A
export
javax.servlet
version=2.3.0
export
org.foo.h<p
HTTP$
client
B
export
javax.servlet
version=2.4.0
- 24. Advanced Consistency
Checking
• Sometimes more advanced consistency checking is
necessary, consider this:
HTTP$
service
A
export
javax.servlet
version=2.3.0
export
org.foo.h<p
HTTP$
client
B
export
javax.servlet
version=2.4.0
"uses"
We need to declare such
internal dependencies!
Metadata
Export-Package: org.foo.http; version=“1.0.0"; uses:="javax.servlet"
Import-Package: javax.servlet; version="2.3.0"
- 25. Example Manifest
Bundle-ManifestVersion: 2
Bundle-Name: Example Bundle
Bundle-SymbolicName: net.luminis.example.bundle
Bundle-Version: 1.0.0
Import-Package:
org.osgi.framework;version=“1.3“,
org.osgi.service.event;version=“[1.1,2.0)“,
net.luminis.foo;resolution:=“optional“
Export-Package:
org.osgi.service.event;uses:=org.osgi.framework;version=“1.1”
X-MyBundleHeader:
custom-attribute=“my-value”
- 26. Lifecycle Layer
• Managed life cycle:
- states for each bundle
• Allows updating existing
bundles
- dynamically install, start,
update, and uninstall
Life%cycle
start
end
install
start
stopuninstall
installed
star2ng
stopping
ac2veresolved
uninstalled
- 30. Lifecycle Layer
• The framework instantiates a class implementing
BundleActivator
• declared in the manifest
• bootstraps your code by invoking start()
• provides you a BundleContext for framework
interaction
- 31. Lifecycle Layer
public interface BundleContext {
// …
public Bundle[] getBundles();
public Bundle installBundle(String location, InputStream input)
throws BundleException;
public void addServiceListener(ServiceListener listener);
public void addBundleListener(BundleListener listener);
public void addFrameworkListener(FrameworkListener listener);
public ServiceRegistration registerService(String clazz,
Object service, Dictionary properties);
public ServiceReference[] getServiceReferences(String clazz,
String filter) throws InvalidSyntaxException;
public Object getService(ServiceReference reference);
// …
}
- 32. Service Layer
• OSGi framework
promotes service
oriented interaction
pattern among
bundles
Service
Log Store
publish use
use
publish
Prefs
publish
use
Bundle Bundle Bundle Bundle
Service'
Provider
Service'
Requester
Service'
Registry
publish
interact
find
- 37. Registering a service
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
Properties props = new Properties();
props.put("author", "Jan Willem");
context.registerService(
MyService.class.getName(), new MyServiceImpl(), props);
}
public void stop(BundleContext context) throws Exception {
// framework unregisters our services on our behalf…
}
}
- 38. Looking up and using a service
1. lookup a ServiceReference
2. get a reference to the service
3. invoke the method
4. (optional: unget the service)
- 39. Looking up and using a service
ServiceReference reference =
context.getServiceReference(MyFirstService.class.getName());
if (reference != null) {
MyFirstService srv =
(MyFirstService) context.getService(reference);
if (srv != null) {
// use service
// …
context.ungetService(reference);
} else {
System.out.println("No service found");
}
} else {
System.out.println("No service reference found!");
}
- 40. Looking up using a query
• You can both query on the service name and a filter
condition
• The filter condition allows you to query for properties
• The filter syntax is similar to LDAP:
• (key=value) or (&(name=john)(age>=18))
context.getServiceReferences(
MyFirstService.class.getName(),
"(author=Jan Willem)");
- 41. Listening to the service registry
• Using the bundle context, register as a ServiceListener
• serviceChanged() will be invoked when a service is:
• registered;
• modified;
• unregistering.
public interface ServiceListener extends EventListener {
public void serviceChanged(ServiceEvent event);
}
- 42. Introducing the ServiceTracker
• Makes the task of tracking services easier
• You can just ask the ServiceTracker for a (list of)
service(s) that match the conditions you specified
• A ServiceTrackerCustomizer can be used to
monitor changes or customise the service reference
that is returned by the tracker
• Found in org.osgi.util.tracker package
- 43. ServiceTracker example
private ServiceTracker m_tracker;
// initialise:
m_tracker = new ServiceTracker(context, MyService.class.getName(), null);
m_tracker.open();
// usage:
SomeService service = (SomeService) m_tracker.getService();
if (service != null) {
service.greet("John");
}
// cleanup:
m_tracker.close();
- 44. Version Format
• OSGi uses a 4-part version numbering scheme
• <major>.<minor>.<micro>.<qualifier>
• Major, minor, and micro are numeric values
• Qualifier is a string value
• Comparison (not always intuitive)
• 1.0.0 < 1.9.9 < 1.10
• 1.0.0.beta > 1.0.0.alpha > 1.0.0
- 46. Version Range Format
• Interval notation is used for version ranges
• use '[' or ']' for inclusive values
• use '(' or ')' for exclusive values
- 47. Version Range Format
• Examples (quotes needed)
• "[1.0.0,2.0.0)" == (1.0.0 <= v < 2.0.0)
• "[1.1.2,1.2.3]" == (1.2.3 <= v <= 1.2.3)
• "[1.1,2)" == (1.1.0 <= v < 2.0.0)
• When a version range is expected, a single value
represents an infinite range:
• "1.0.0" == (1.0.0 <= v < ∞)
- 48. Semantic versioning
• Major number change – signifies a backward
incompatible update.
• Minor number change – signifies a backward
compatible update.
• Micro number change – signifies an internal update
(e.g., a bug fix or performance improvement).
• Qualifier change – signifies a trivial internal change with
“outward” noticeable difference, but nonetheless is a
new artifact (e.g., line number refactoring).