osgi bootcamp - part 1
TRANSCRIPT
OSGi Bootcamp Day 1
Jan Willem Janssen
Agenda
• Introduction to OSGi
• The core framework
• creating bundles, working with services, dealing with the dynamics and version resolution
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
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 ?
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.
OSGi Alliance• Expert Groups:
• core platform (CPEG)
• enterprise (EEG)
• residential (REG)
• IoT (IEG)
• Working Groups:
• marketing
• requirements
• technical steering committee
OSGi specification
• Core
• semantics
• framework
• core/mandatory services
• Companion
• optional services
Service
Life%cycle
Module
OSGi Framework
Java$Virtual$Machine
Security
Bundle Bundle Bundle
OSGi%framework
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
Module Layer (1/3)• A bundle is:
• a JAR file
• unit of deployment
• own class loader
• isolation
• bundle classpath
storeStore.class
Key.class
store.fsStoreImpl.class
FileSystem.class
StreamU4l.class
bundle
store.fs.osgiAc4vator.class
META%INF/MANIFEST.MF
Bundle%SymbolicName::store.fsBundle%Version::1.0.2
Bundle%Classpath::.,:lib/fsuGl.jar
Bundle%AcGvator::store.fs.osgi.AcGvator
Module Layer (2/3)
fs.nio3Input.class
Output.class
storeStore.class
Key.class
store.fsStoreImpl.class
FileSystem.class
StreamU4l.class
bundle
store.fs.osgiAc4vator.class
META%INF/MANIFEST.MF
Bundle%SymbolicName::store.fsBundle%Version::1.0.2
Bundle%Classpath::.,:lib/fsuGl.jar
Bundle%AcGvator::store.fs.osgi.AcGvator
Export%Package::store:2.5.0Import%package::fs.nio3:[1,:3)
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
• Imagine bundle A somehow gets servlet instances from bundle B
Importing & Exporting a Package (1/4)
A
Bimport
javax.servlet
exportjavax.servlet
.class
one3copy3ofjavax.servlet
• What if bundle A also wanted to get servlet instances somehow from bundle C?
Importing & Exporting a Package (1/4)
A
Bimport
javax.servlet
exportjavax.servlet
.class
one3copy3ofjavax.servlet
• Bundle C could import from bundle B, but then it is dependent on it
Importing & Exporting a Package (2/4)
A
Bimport
javax.servlet
exportjavax.servlet
.class
one3copy3ofjavax.servlet
C
importjavax.servlet
• 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
importjavax.servlet
exportjavax.servlet
.class
two3copies3ofjavax.servlet
B
exportjavax.servlet
.class
???
Importing & Exporting a Package (4/4)
• Bundle C could both import and export servlet to solve the dilemma
A
C
importjavax.servlet
export1and1importjavax.servlet
.class
B.class
export1and1importjavax.servlet
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
Interfacepackage org.foo.http;import javax.servlet;public interface HttpService { void registerServlet(Sting alias, Servlet servlet);}
MetadataExport-Package: org.foo.http; version="1.0.0"Import-Package: javax.servlet; version="2.3.0"
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
HTTP$service
A
importjavax.servletversion=2.3.0
exportjavax.servletversion=2.3.0
exportorg.foo.h=p
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
HTTP$service
A
importjavax.servletversion=2.3.0
exportjavax.servletversion=2.3.0
exportorg.foo.h=p
HTTP$client
importorg.foo.h=p
importjavax.servletversion=2.4.0
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
HTTP$service
A
exportjavax.servletversion=2.3.0
exportorg.foo.h<p
HTTP$client
B
exportjavax.servletversion=2.4.0
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
HTTP$service
A
exportjavax.servletversion=2.3.0
exportorg.foo.h<p
HTTP$client
B
exportjavax.servletversion=2.4.0
This would result in a ClassCastException,
why?
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
HTTP$service
A
exportjavax.servletversion=2.3.0
exportorg.foo.h<p
HTTP$client
B
exportjavax.servletversion=2.4.0
Advanced Consistency Checking
• Sometimes more advanced consistency checking is necessary, consider this:
HTTP$service
A
exportjavax.servletversion=2.3.0
exportorg.foo.h<p
HTTP$client
B
exportjavax.servletversion=2.4.0
"uses"
We need to declare such internal dependencies!
MetadataExport-Package: org.foo.http; version=“1.0.0"; uses:="javax.servlet"Import-Package: javax.servlet; version="2.3.0"
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”
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
Lifecycle Example
Bundle
OSGi+Framework
provided package
Bundle
OSGi+Framework
Bundle
Lifecycle Example
install bundle
Lifecycle Example
Bundle
OSGi+Framework
Bundleresolve bundle
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
Lifecycle Layerpublic 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); // … }
Service Layer
• OSGi framework promotes service oriented interaction pattern among bundles
Service
Log Store
publish useuse
publish
Prefs
publishuse
Bundle Bundle Bundle Bundle
Service'Provider
Service'Requester
Service'Registry
publish
interact
find
Service Example
Bundle
OSGi+Framework
provided package
provided service
Service Example
Bundle
OSGi+Framework
Bundle
install bundle
Service Example
Bundle
OSGi+Framework
Bundleresolve bundle
Service Example
Bundle
OSGi+Framework
Bundle
resolve service
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…
} }
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)
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!"); }
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)");
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); }
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
ServiceTracker exampleprivate 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();
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
Version Format• Valid:
• 1
• 1.10
• 1.9.9.alpha
• 0.2.0.SNAPSHOT
• Invalid:
• 0.2.SNAPSHOT
• 1.9.9-alpha
Version Range Format
• Interval notation is used for version ranges
• use '[' or ']' for inclusive values
• use '(' or ')' for exclusive values
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 < ∞)
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).
Semantic versioning
• OSGi whitepaper on semantic versioning
• semver.org semantic versioning manifest
Downsides and Pitfalls
<<"client">> FoogetBar()
FooImpl
<<"client">> FoogetBar()setBar()
FooImpl
uses
implements update implements
uses
Best Practice
<<"client">> Foo
FooImpl
uses
implements
[1.0,/2.0)
[1.0,/1.1)