| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
| "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
| <chapter id="bnd-app-ctx"> |
| <title>Bundles and Application Contexts</title> |
| |
| <para>The unit of deployment (and modularity) in OSGi is the <emphasis>bundle</emphasis> (see |
| section 3.2 of the OSGi Service Platform Core Specification). A bundle |
| known to the OSGi runtime is in one of three steady states: installed, |
| resolved, or active. Bundles may export services (objects) to the OSGi |
| service registry, and by so doing make these services available for other |
| bundles to discover and to use. Bundles may also export Java packages, |
| enabling other bundles to import the exported types.</para> |
| |
| <para>In Spring the primary unit of modularity is an <emphasis>application context</emphasis>, |
| which contains some number of beans (objects managed by the Spring |
| application context). Application contexts can be configured in a |
| hierarchy such that a child application context can see beans defined in a |
| parent, but not vice-versa. The Spring concepts of exporters and factory |
| beans are used to export references to beans to clients outside of the |
| application context, and to inject references to services that are defined |
| outside of the application context.</para> |
| |
| <para>There is a natural affinity between an OSGi bundle and a Spring |
| application context. Using Gemini Blueprint, an active bundle may |
| contain a Spring application context, responsible for the instantiation, |
| configuration, assembly, and decoration of the objects (beans) within the |
| bundle. Some of these beans may optionally be exported as OSGi services |
| and thus made available to other bundles; beans within the bundle may also |
| be transparently injected with references to OSGi services.</para> |
| |
| <para>This chapter describes the lifecycle relationship between bundles and their |
| application contexts, as imposed by Gemini Blueprint based on the events occurring at runtime, |
| inside an OSGi environment.</para> |
| |
| <section id="bnd-app-ctx:extender"> |
| <title>The Gemini Blueprint Extender Bundle</title> |
| |
| <sidebar id="extender-pattern"> |
| <title>Extender Pattern</title> |
| <para>A common pattern in OSGi applications is the <emphasis>extender</emphasis>, that |
| (quoting <ulink url="http://www.aqute.biz/Blog/HomePage">Peter Kriens</ulink>, |
| OSGi Technical Director), <quote>allows other bundles to extend the functionality in a specific domain</quote>. |
| See <ulink url="http://www.osgi.org/blog/2007/02/osgi-extender-model.html">this</ulink> OSGi Alliance blog |
| entry for an in-depth explanation. |
| </para> |
| </sidebar> |
| |
| <para>The component responsible for detecting the <emphasis>Spring-powered bundles</emphasis> and instantiating |
| their application context is the Gemini Blueprint <emphasis>extender</emphasis>. It serves the same purpose as the <ulink |
| url="http://static.springframework.org/spring/docs/2.5.x/reference/webintegration.html">ContextLoaderListener</ulink> |
| does for Spring web applications. Once the extender bundle is installed |
| and started it looks for any existing Spring-powered bundles that are |
| already in the <emphasis>ACTIVE</emphasis> state and creates application contexts on their |
| behalf. In addition, it listens for bundle starting events and |
| automatically creates an application context for any Spring-powered |
| bundle that is subsequently started. <xref linkend="app-deploy:headers"/> |
| describes what the extender recognizes as a "Spring-powered bundle" while |
| <xref linkend="app-deploy:extender-configuration"/> how the extender can be configured. |
| The extender monitors the lifecycle of the bundle it manages and will destroy automatically the contexts for bundles |
| that are stopped. When the extender bundle itself is stopped, it will automatically close all the contexts that it manages, |
| based on the service dependency between them. |
| The extender bundle symbolic name is <literal>org.eclipse.gemini.blueprint.extender</literal>. </para> |
| |
| </section> |
| |
| <section id="bnd-app-ctx:app-creation"> |
| <title>Application Context Creation</title> |
| |
| <para>Once started, the extender analyses the existing started bundles and monitors any new bundle that will start. Once a |
| Blueprint or Gemini Blueprint configuration is detected, the extender will create an application context for it in an asynchronous manner, |
| on a different thread then the one starting the bundle (or delivering the STARTED event). |
| This behaviour follows the OSGi specification recommendation and ensures that starting an OSGi Service Platform is fast and that |
| bundles with service inter-dependencies do not cause deadlock (waiting for each other) on startup, as pictured below: </para> |
| |
| |
| <para><mediaobject> |
| <imageobject role="fo"> |
| <imagedata fileref="../src/docbkx/resources/images/start-diagram.png" format="PNG" align="center"/> |
| </imageobject> |
| <imageobject role="html"> |
| <imagedata fileref="images/start-diagram.png" format="PNG" align="center"/> |
| </imageobject> |
| |
| <textobject> |
| <phrase>Application Context Sequence Diagram</phrase> |
| </textobject> |
| |
| </mediaobject></para> |
| |
| <para>The extender considers only bundles successfully started, that is, bundles in |
| <emphasis>ACTIVE</emphasis> state; bundles in other states are ignored. |
| Therefore a Spring-powered/Blueprint bundle will have its application context created <emphasis>after</emphasis> |
| it has been fully started. It is possible to force synchronous/serialized creation of application contexts |
| for started bundles, on a bundle-by-bundle basis. See <xref linkend="app-deploy:headers"/> for information |
| on how to specify this behaviour.</para> |
| |
| <para>If application context creation fails for any reason then the |
| failure cause is logged. The bundle remains in the ACTIVE state; the application context lifecycle will not influence |
| the bundle lifecycle in anyway. Naturally, since the context has failed, so will the functionality associated with it; |
| for example there will be no services exported to the registry from the application context in this scenario.</para> |
| |
| <section id="bnd-app-ctx:app-creation:mandatory-deps"> |
| <title>Mandatory Service Dependencies</title> |
| |
| <para>If an application context declares mandatory availability for certain |
| imported OSGi services, the creation of the application context is blocked |
| until all the mandatory dependencies can be satisfied through matching services |
| available in the OSGi service registry. In practice, for most enterprise applications |
| built using Gemini Blueprint services, the set of available |
| services and bundles will reach a steady state once the platform and |
| its installed bundles are all started. In such a world, the behaviour of |
| waiting for mandatory dependencies simply ensures that bundles A and |
| B, where bundle A depends on services exported by bundle B, may be |
| started in any order.</para> |
| |
| <para>A timeout applies to the wait for mandatory dependencies to be |
| satisfied. By default the timeout is set to 5 minutes, but this value |
| can be configured using the <literal>timeout</literal> directive. See |
| <xref linkend="app-deploy:headers"/> for details.</para> |
| |
| <para>Blueprint users could achieve the same result through the <literal>blueprint.timeout</literal> |
| attribute declared on the <literal>Bundle-SymbolicName</literal></para> |
| |
| <para>It is possible to change the application context creation |
| semantics so that application context creation fails if all mandatory |
| services are not immediately available upon startup (see the aforementioned |
| section for more information). |
| Again, note that regardless of the configuration chosen, the failure of the |
| application context will not change the bundle state.</para> |
| |
| <para>For more information on the <emphasis>availability</emphasis> of imported services, |
| see <xref linkend="service-registry:refs:availability"/></para> |
| </section> |
| |
| <section id="bnd-app-ctx:app-creation:app-ctx-publication"> |
| <title>Application Context Service Publication</title> |
| |
| <para>Once the application context creation for a bundle has |
| completed, the application context object is automatically exported as |
| a service available through the OSGi Service Registry. The context is |
| published under the interface |
| <interfacename>org.springframework.context.ApplicationContext</interfacename> (and |
| also all of the visible super-interfaces and types implemented by the |
| context). The published service has a service property named |
| <literal>org.springframework.context.service.name</literal> whose |
| value is set to the bundle symbolic name of the bundle hosting the |
| application context. In case of a Blueprint bundle, the container will be published |
| under <interfacename>org.osgi.service.blueprint.container.BlueprintContainer</interfacename> |
| while the bundle symbolic name will be published under <literal>osgi.blueprint.container.symbolicname</literal> |
| property. |
| </para> |
| <para>It is possible to prevent publication of the |
| application context as a service using a directive in the bundle's |
| manifest. See <xref linkend="app-deploy:headers"/> for details.</para> |
| |
| <para>Note: the application context is published as a service |
| primarily to facilitate testing, administration, and management. |
| Accessing this context object at runtime and invoking |
| <literal>getBean()</literal> or similar operations is discouraged. The |
| preferred way to access a bean defined in another application context |
| is to export that bean as an OSGi service from the defining context, |
| and then to import a reference to that service in the context that |
| needs access to the service. Going via the service registry in this |
| way ensures that a bean only sees services with compatible versions of |
| service types, and that OSGi platform dynamics are respected.</para> |
| </section> |
| </section> |
| |
| |
| <section id="bnd-app-ctx:bnd-lifecycle"> |
| <title>Bundle Lifecycle</title> |
| |
| <para>OSGi is a dynamic platform: bundles may be installed, started, |
| updated, stopped, and uninstalled at any time during the running of the |
| framework.</para> |
| |
| <para>When an active bundle is stopped, any services it exported during |
| its lifetime are automatically unregistered and the bundle returns to |
| the resolved state. A stopped bundle should release any resources it has |
| acquired and terminate any threads. Packages exported by a stopped |
| bundle continue to be available to other bundles.</para> |
| |
| <para>A bundle in the resolved state may be uninstalled: packages that |
| were exported by an uninstalled bundle continue to be available to |
| bundles that imported them (but not to newly installed bundles).A bundle |
| in the resolved state may also be updated. The update |
| process migrates from one version of a bundle to another version of the |
| same bundle.</para> |
| |
| <para>Finally of course, a resolved bundle can be started, which |
| transitions it to the active state.</para> |
| |
| <para>The diagram below represents the bundle states and its transitions:</para> |
| |
| <para><mediaobject> |
| <imageobject role="fo"> |
| <imagedata fileref="../src/docbkx/resources/images/bundle-states.png" format="PNG" align="center"/> |
| </imageobject> |
| <imageobject role="html"> |
| <imagedata fileref="images/bundle-states.png" format="PNG" align="center"/> |
| </imageobject> |
| |
| <textobject> |
| <phrase>Bundle States</phrase> |
| </textobject> |
| |
| </mediaobject></para> |
| |
| |
| <para>The OSGi <literal>PackageAdmin</literal> |
| <literal>refreshPackages</literal> operation refreshes packages across |
| the whole OSGi framework or a given subset of installed bundles. During |
| the refresh, an application context in an affected bundle will be |
| stopped and restarted. After a <literal>refreshPackages</literal> |
| operation, packages exported by older versions of updated bundles, or |
| packages exported by uninstalled bundles, are no longer available. |
| Consult the OSGi specifications for full details.</para> |
| |
| <para>When a Spring-powered or Blueprint bundle is stopped, the application context |
| created for it is automatically destroyed. All services exported by the |
| bundle will be unregistered (removed from the service registry) and the |
| normal application context tear-down life-cycle is observed |
| (<interfacename>org.springframework.beans.factory.DisposableBean</interfacename> implementors |
| and <literal>destroy-method</literal> |
| callbacks are invoked on beans in the context).</para> |
| |
| <para>If a Spring-powered bundle that has been stopped is subsequently |
| re-started, a new application context will be created for it.</para> |
| </section> |
| |
| <section id="bnd-app-ctx:osgi-resource"> |
| <title>The Resource Abstraction</title> |
| |
| <para>The Spring Framework defines a resource abstraction for loading |
| resources within an application context (see <ulink |
| url="http://static.springframework.org/spring/docs/2.5.x/reference/resources.html">Spring's |
| resource abstraction</ulink>). All resource loading is done through the |
| <interfacename>org.springframework.core.io.ResourceLoader</interfacename> associated with the application |
| context. The <interfacename>org.springframework.core.io.ResourceLoader</interfacename> is also |
| available to beans wishing to load resources programmatically. Resource paths with |
| explicit prefixes - such as <literal>classpath:</literal> - are treated uniformly |
| across all application context types (for example, web application |
| contexts and classpath-based application contexts). Relative resource |
| paths are interpreted differently based on the type of application |
| context being created. This enables easy integration testing outside |
| the ultimate deployment environment.</para> |
| |
| <para>OSGi 4.0.x specification defines three different spaces from which a |
| resource can be loaded. Gemini Blueprint supports all of them through its dedicated OSGi-specific |
| application context and dedicated prefixes:</para> |
| |
| <table id="osgi-search-strategies" pgwide="1"> |
| <title>OSGi resource search strategies</title> |
| <tgroup cols="3"> |
| <thead> |
| <row> |
| <entry>OSGi Search Strategy</entry> |
| <entry>Prefix</entry> |
| <entry>Explanation</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>Class Space</entry> |
| <entry><literal>classpath:</literal></entry> |
| <entry>Searches the bundle classloader (the bundle, all imported packages and required bundles). Forces the bundle to be resolved. |
| This method has similar semantics to |
| <ulink url="http://www2.osgi.org/javadoc/r4/org/osgi/framework/Bundle.html#getResource(java.lang.String)"><literal>Bundle#getResource(String)</literal></ulink></entry> |
| </row> |
| |
| <row> |
| <entry>Class Space</entry> |
| <entry><literal>classpath*:</literal></entry> |
| <entry>Searches the bundle classloader (the bundle and all imported packages and required bundles). Forces the bundle to be resolved. |
| This method has similar semantics to |
| <ulink url="http://www2.osgi.org/javadoc/r4/org/osgi/framework/Bundle.html#getResources(java.lang.String)"><literal>Bundle#getResources(String)</literal></ulink> |
| </entry> |
| </row> |
| |
| <row> |
| <entry>JAR File (or JarSpace)</entry> |
| <entry><literal>osgibundlejar:</literal></entry> |
| <entry>Searches only the bundle jar. Provides low-level access without requiring the bundle to be resolved.</entry> |
| </row> |
| <row> |
| <entry>Bundle Space</entry> |
| <entry><literal>osgibundle:</literal></entry> |
| <entry>Searches the bundle jar and its attached fragments (if there are any). Does not create a class loader or force the bundle to be resolved.</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <para>Please consult section 4.3.12 of the OSGi specification for an in depth explanation of the differences between them. |
| </para> |
| |
| <note>If no prefix is specified, the bundle space (<literal>osgibundle:</literal>) will be used.</note> |
| |
| <note>Due to the OSGi dynamic nature, a bundle classpath can change during its life time (for example when dynamic imports are used). This might cause different |
| classpath <interfacename>Resource</interfacename>s to be returned when doing pattern matching based on the running environment or target platform.</note> |
| |
| <para>All of the regular Spring resource prefixes such as <literal>file:</literal> and |
| <literal>http:</literal> are also supported, as are the pattern matching wildcards. |
| Resources loaded using such prefixes may come from any location, they |
| are not restricted to being defined within the resource-loading bundle |
| or its attached fragments.</para> |
| |
| <para>OSGi platforms may define their own unique prefixes for accessing |
| bundle contents. For example, Equinox defines the <literal>bundleresource:</literal> and |
| <literal>bundlentry:</literal> prefixes. These platform specific prefixes may also be |
| used with Gemini Blueprint, at the cost, of course, of tying yourself to a |
| particular OSGi implementation.</para> |
| </section> |
| |
| <section id="bnd-app-ctx:bundle-scope"> |
| <title>Bundle Scope</title> |
| |
| <para>Gemini Blueprint introduces a new bean scope named <literal>bundle</literal>. This scope is relevant for |
| beans exported as an OSGi service and can be described as <emphasis>one instance per bundle</emphasis>. |
| Beans exported as OSGi service, that have <literal>bundle</literal> scope, will result in a different instance created for |
| each unique bundle that imports the service through the OSGi service registry. Consumers of the same bundle (whether defined |
| through Gemini Blueprint or not) will see the same bean instance. When a bundle has stopped importing the bundle (for whatever reason), |
| the bean instance is disposed. |
| To the declaring bundle, a <literal>bundle</literal>-scoped bean behaves just like a singleton (i.e. there is only |
| one instance per bundle, including the declaring one).This contract lifecycle is similar to that of the |
| <interfacename>org.osgi.framework.ServiceFactory</interfacename> interface.</para> |
| <para>For more information regarding service publication and consumption, see <xref linkend="service-registry"/>.</para> |
| |
| <important>The bundle scope is relevant, only if the declaring bean is consumed through the OSGi service registry. That is, |
| instances are created and destroyed (tracked) only when the bean exported as a service, is requested or released as an OSGi service |
| by other bundles.</important> |
| </section> |
| |
| <section id="bnd-app-ctx:access-bnd-ctx"> |
| <title>Accessing the BundleContext</title> |
| |
| <para>In general there is no need to depend on any OSGi APIs when using |
| the Gemini Blueprint support. If you <emphasis>do</emphasis> need |
| access to the OSGi <interfacename>BundleContext</interfacename> object for your |
| bundle, then Spring makes this easy to do.</para> |
| |
| <para>The OSGi application context created by the Spring extender will |
| automatically contain a bean of type <interfacename>BundleContext</interfacename> |
| and with name <literal>bundleContext</literal>. You can inject a |
| reference to this bean into any bean in the application context either |
| by-name or by-type. In addition, Gemini Blueprint defines the |
| interface |
| <interfacename>org.eclipse.gemini.blueprint.context.BundleContextAware</interfacename>:</para> |
| |
| <programlisting language="java">public interface BundleContextAware { |
| public void setBundleContext(BundleContext context); |
| }</programlisting> |
| |
| <para>Any bean implementing this interface will be injected with a |
| reference to the bundle context when it is configured by Spring. If you |
| wish to use this facility within a bundle, remember to import the |
| package <literal>org.eclipse.gemini.blueprint.context</literal> in your |
| bundle manifest since otherwise the interface will not be visible to your bundle.</para> |
| </section> |
| |
| <section id="bnd-app-ctx:app-destruction"> |
| <title>Application Context Destruction</title> |
| |
| <para>The application context is bound to the bundle in which it lives. Thus, if the declaring |
| bundle is being shutdown (for whatever reasons), the application context will be destroyed as well, |
| all exported services being unregistered and all service imported dispose of. |
| </para> |
| |
| <para>As opposed to the application creation, the application context is destroyed in a synchronized manner, |
| on the same thread that stops the bundle. This is required since once stopped, a bundle can not longer be used |
| (even for class loading) preventing the application context shutdown from executing correctly. |
| </para> |
| |
| <para><mediaobject> |
| <imageobject role="fo"> |
| <imagedata fileref="../src/docbkx/resources/images/stop-diagram.png" format="PNG" align="center"/> |
| </imageobject> |
| <imageobject role="html"> |
| <imagedata fileref="images/stop-diagram.png" format="PNG" align="center"/> |
| </imageobject> |
| |
| <textobject> |
| <phrase>Application Context Sequence Diagram</phrase> |
| </textobject> |
| |
| </mediaobject></para> |
| |
| |
| <para>Note that a bundle can be closed individually or as part of a bigger |
| event such as shutting down the entire OSGi platform. In this case or when the extender |
| bundle is being closed down, the application contexts will be closed in a managed |
| manner, based on the service dependencies between them. Please see the next section for more |
| details.</para> |
| </section> |
| |
| <section id="bnd-app-ctx:access-bnd-ctx:stop-extender"> |
| <title>Stopping the Extender Bundle</title> |
| |
| <sidebar id="shutdown-2.x"> |
| <title>Shutdown algorithm change in 2.x</title> |
| <para>The shutdown algorithm implementation in Gemini Blueprint 1.0 has been revised to be better |
| aligned with the Blueprint Container spec. Namely, the previous implementation performed ordering |
| in only one pass while the latter performs multiple steps to accommodate the service changes in |
| the OSGi space. Users should not discover any differences at runtime however, if that's not the case, |
| please let us know. |
| </para> |
| </sidebar> |
| |
| <para>If the extender bundle is stopped, then all the application |
| contexts created by the extender will be destroyed. The algorithm described here is identical |
| to that used by the Blueprint specification (section 121.3.11). Application contexts |
| are shutdown in the following order:</para> |
| |
| <orderedlist> |
| <listitem id="bnd-app-ctx:access-bnd-ctx:stop-extender:shutdown.step.1"> |
| <para>Application contexts that do not export any services, or that |
| export services that are not currently referenced, are shutdown in |
| reverse order of bundle id. (Most recently installed bundles have |
| their application contexts shutdown first).</para> |
| </listitem> |
| |
| <listitem> |
| <para>Shutting down the application contexts in step 1 may have |
| released references these contexts were holding such that there are |
| now additional application contexts that can be shutdown. If so, |
| repeat <link linkend="bnd-app-ctx:access-bnd-ctx:stop-extender:shutdown.step.1">step 1</link> again.</para> |
| </listitem> |
| |
| <listitem> |
| <para>If there are no more active application contexts, we have |
| finished. If there <emphasis>are</emphasis> active application |
| contexts then there must be a cyclic dependency of references. The |
| circle is broken by determining the highest ranking service exported |
| by each context: the bundle with the lowest ranking service in this |
| set (or in the event of a tie, the highest service id), is shut |
| down. Repeat from <link linkend="bnd-app-ctx:access-bnd-ctx:stop-extender:shutdown.step.1">step 1</link>.</para> |
| </listitem> |
| </orderedlist> |
| </section> |
| </chapter> |