OSGI Modularity Layer

Download Report

Transcript OSGI Modularity Layer

Review:
OSGi – a component framework for Java
“Dynamic Modules for Java”
Bundle
Bundle
Bundle
Bundle
OSGi Framework
Java Runtime Environment (JRE)
Operating System (OS)
Hardware
Bundle
Review:
OSGi Layered Architecture
Service
Bundles
Lifecycle
Modularity
Execution Environment
HW / OS
• Each layer depends on the layers beneath it (It is possible to use
lower OSGi layers without using upper ones, but not vice versa)
• Bundles are the unit of modularity. They further have an associated
life cycle and are the providers of services.
OSGi: The Modularity Layer
Reading
• Ch.1: OSGi revealed
• Ch 2: Mastering modularity
• Ch 3: Learning lifecycle
• Ch 4: Studying services
• Ch 11: Component models and
frameworks
Logical vs Physical Modularity
• Logical modularity refers to a form of code visibility. A
module defines a logical boundary in your application,
which impacts code visibility in a fashion similar to
access modifiers
• Physical modularity refers to how code is packaged
and/or made available for deployment. Physical
modules are sometimes also referred to as deployment
modules or deployment units.
• In general, a physical module is not necessary equal to
a logical module: it’s possible to have logical modularity
without physical modularity or to package multiple logical
modules into a single physical module
Limitations of Java Modularity
1. Low-level control of code visibility
2. Limited deployment and management support
– The classpath problem
Limitations of Java Modularity (1)
Low-level code visibility control
• What are Java modules ? Packages, jars ?
• Packages are in general too finegrained to be
considered modules
• A module would be of a size of a group of packages
(maybe in a jar – or not)
• Problem with this:
– No relationships are defined between packages
– jar files by themselves provide no visibility scoping. All the public
classes in implementation packages are visible to everyone, not
only to the other packages forming the module
Limitations of Java Modularity (2)
The classpath problem
Limitations of Java Modularity (2)
The classpath problem
• The “class path hell” arises when more than one JAR file provides
a given set of classes
• Example scenario:
– The jar file A.jar has a class pack.a.Test that needs
pack.lib.Util. During testing it was compiled against this class in
Lib.jar at version 1.2.0.
– However, during deployment the class is provided by the first jar found
on the classpath that contains pack/lib/Util.class.
– The class carries no version information, so there is no way to diagnose
problems around using that class !
– The jar file also contains no version information, so even if the class
came from Lib.jar it might be the wrong one (version 1.1.0) !
– This problem can be especially hard to diagnose when an OtherLib
only accidentally contains pack.lib.Util where its primary classes
it is meant to provide are in another package such as pack.other.
OSGi Modularity
• In OSGi, logical modularity is synonymous with
physical modularity: both the logical module
and the physical module is referred to as a
bundle
OSGi Bundles
• A Bundle is:
• “ A physical unit of
modularity in the form of
a JAR file containing
code, resources, and
metadata, where the
boundary of the JAR file
also serves as the
encapsulation boundary
for logical modularity at
execution time”.
Bundle’s role in logical modularity
• Packages (and therefore the classes in them) contained
in a bundle are private to that bundle unless explicitly
exported
• Only explicitly exported packages can be imported
(used) by other bundles
• Bundles extend standard Java access modifiers with
module private visibility (only visible in the module)
OSGi Bundle Metadata
• Metadata are contained in the Manifest file
• The OSGI manifest extends the classical jar file manifest
• The OSGI-related metadata contains the following
categories of information about the bundle:
– Human-readable information—Optional information intended
purely as an aid to humans who are using the bundle
– Bundle identification—Required information to identify a bundle
– Code visibility—Required information for defining which code is
internally visible and which internal code is externally visible
Bundle Manifest Example
Humanreadable
info
Bundle
identificat
ion
Code
visibility
Bundle-ManifestVersion: 2
Bundle-Name: Hello
Bundle-Description: A Greeting Bundle
Bundle-Vendor: FooProducer
Bundle-SymbolicName: org.foo.hello
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: org.foo.hello
Import-Package: org.osgi.framework;version="1.5.0"
Bundle-Activator: org.foo.hello.Activator
Bundle Metadata:
(1) Human-readable information
• the OSGi framework ignores this part, it is just for
humans.
• Examples:
– Bundle-Name
– Bundle-Description
– Bundle-Vendor
– Bundle-Copyright
Bundle Metadata:
(2) Bundle Identification
• Examples:
– Bundle-SymbolicName: helps the OSGi framework to uniquely
identify a bundle
– Bundle-Version: an OSGI version-number, is taken together with
the symbolic name for bundle identification
Bundle Metadata:
(3) Code Visibility
• Internal bundle class path— bundle class path is a list of
locations to search for classes. The difference from java
class path is that the bundle class path refers to
locations inside the bundle JAR file.
– Bundle-ClassPath has a default value of . meaning that
classes are searched in the root of the bundle jar file
• Exported internal code—Explicitly exposed code from
the bundle class path for sharing with other bundles
• Imported external code—External code on which the
bundle class path code depends
Bundle Metadata:
Code Visibility – Exported code
•
Export: Bundles may export packages
•
Exported packages form the bundle's API
•
Packages that not exported are private
•
Packages are exported with their name and an optional version number
(packages are versioned independently)
•
Examples:
– Export-Package: org.foo.hello
– Export-Package: org.foo.hello, org.foo.other
– Export-Package: org.foo.hello, org.foo.other; version=“2.0.0”
•
You can also attach attributes to exported packages. Because it’s possible
for different bundles to export the same packages, a given bundle can use
custom attributes to differentiate its exports from other bundles. For
example:
– Export-Package: org.foo.hello, org.foo.other; vendor=“Manning”
Bundle Metadata:
Code Visibility – Imported code
• Code is imported in form of:
– Imported packages
• Bundles may use packages exported packages only if they explicitly
import them using the package name
• Each import may be qualified with a version or a version range
– Import-Package: org.osgi.framework; version="1.3.0“
– Import-Package: org.osgi.framework; version="[1.3.0,2.0.0)“
– Import-Package: org.foo.hello; vendor=“Manning”
– Required bundles
• Bundles may specify a dependency on entire bundles
• Simplifies imports, but it is highly NOT recommended !
•
Better: “Depend on packages, not on bundles”
OSGi Class Search Order
•
When a bundle needs a class at execution time, the
framework searches for the class in the following order:
1. If the class is from a package starting with java., the parent
class loader is asked for the class. If the class is found, it’s
used. If there is no such class, the search ends with an
exception. => ensures all bundles use the same core Java
2. If the class is from a package imported by the bundle, the
framework asks the exporting bundle for the class. If the class is
found, it’s used. If there is no such class, the search ends with
an exception. => ensures that imported packages are not split
3. The bundle class path is searched for the class. If it’s found, it’s
used. If there is no such class, the search ends with an
exception.
OSGi Import-Package vs. Java import
• They serve different purposes:
– The import keyword in Java is for namespace management:
• it allows you to use the short name of the imported classes instead
of using its fully qualified class name
• the import statement itself doesn’t grant any visibility.
• you do not need to use import, because you can always use the
fully qualified class name instead.
– For OSGi, the metadata for importing external code is important,
because it’s how the framework knows what your bundle needs.
Resolving dependencies
automatically
• One of the most important tasks performed by the OSGi
framework is automating dependency management,
which is called bundle dependency resolution.
• A bundle’s dependencies must be resolved by the
framework before the bundle can be used
• The OSGi framework uses a sophisticated dependency
resolution algorithm
Resolving a Bundle
• RESOLVING = The process of matching a bundle’s
imported packages to exported packages from other
bundles and doing so in a consistent way so any given
bundle only has access to a single version of any type.
• Resolving a bundle may cause the framework to resolve
other bundles transitively, if exporting bundles
themselves haven’t yet been resolved.
• The resulting set of resolved bundles are conceptually
wired together
• If any dependency can’t be satisfied, then the resolve
fails, and the instigating bundle can’t be used until its
dependencies are satisfied.
Resolving dependencies
• The priority of dependency resolution candidate
selection:
– Highest priority is given to already-resolved candidates, where
multiple matches of resolved candidates are sorted according to
version and then installation order.
– Next priority is given to unresolved candidates, where multiple
matches of unresolved candidates are sorted according to
version and then installation order.
• The resolve process is incremental !
– Dependencies are resolved taking into account the bundles that
are installed at the moment
– Bundles may be installed at any later moment – this may reset
the resolve algorithm !
Consistency
• The dependencies are resolved in a consistent way if
any given bundle only has access to a single version of
any package.
• The bundle’s class space = its imported packages plus
the packages accesible from its bundle classpath
• In order to be able to ensure consistency, sometimes
uses contraints are necessary to be specified
– The following example scenario illustrates this
Example
1. Initial situation: two bundles installed and resolved
package org.osgi.service.http;
import javax.servlet.Servlet;
public interface HttpService {
void registerServlet(Sting alias,
Servlet servlet, HttpContext ctx);
}
Example contd.
2. Follow up: two more bundles are installed:
The incremental dependency resolution leads to a situation that is
NOT CONSISTENT !
The class spaces of the HTTP Client and HTTP service bundles are not consistent,
since two different versions of javax.servlet.Servlet are reachable !
Example contd.
3. Solution: specifying intra-bundle dependencies
The Uses Directive = A directive attached to exported packages whose value is a
comma-delimited list of packages exposed by the associated exported package.
It constrains the choices of the framework when resolving dependencies !
Export-Package: org.osgi.service.http;
uses:="javax.servlet"; version="1.0.0"
Import-Package: javax.servlet; version="2.3.0"
Example contd.
4. Resolution with Uses contraints:
For the incremental case, the framework can now detect inconsistencies in the class
spaces, and resolution fails when you try to use the client bundle. Early detection is
better than errors at execution time, because it alerts you to inconsistencies in the
deployed set of bundles.
The framework can be requested to re-resolve the bundle dependencies
to remedy this situation
Example contd.
5. Consistent resolution:
Summary
• Modularity is a form of separation of concerns that provides both
logical and physical encapsulation of classes.
• Bundle is the name for a module in OSGi. It’s a JAR file containing
code, resources, and modularity metadata.
• Modularity metadata details human-readable information, bundle
identification, and code visibility.
• Bundle code visibility is composed of an internal class path,
exported packages, and imported packages.
• The OSGi framework uses the metadata about imported and
exported packages to automatically resolve bundle
dependencies and ensure type consistency before a bundle can
be used.
• Imported and exported packages capture inter-bundle package
dependencies, but uses constraints are necessary to capture intrabundle package dependencies to ensure complete type
consistency.