| <?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="app-deploy"> |
| <title>Packaging and Deploying Spring-based OSGi applications</title> |
| |
| <para>A traditional Spring application uses either a single application |
| context, or a parent context containing service layer, data layer, and |
| domain objects with a child context containing web layer components. The |
| application context may well be formed by aggregating the contents of |
| multiple configuration files.</para> |
| |
| <para>When deploying an application to OSGi the more natural structure is |
| to package the application as a set of peer bundles (application contexts) |
| interacting via the OSGi service registry. Independent subsystems should |
| be packaged as independent bundles or sets of bundles (vertical |
| partitioning). A subsystem may be package in a single bundle, or divided |
| into several bundles partitioned by layer (horizontal partitioning). A |
| straightforward web application may for example be divided into four |
| modules (bundles): a web bundle, service layer bundle, data layer bundle, |
| and domain model bundle. Such an application would look like this:</para> |
| |
| <para><mediaobject> |
| <imageobject role="fo"> |
| <imagedata fileref="../src/docbkx/resources/images/spring-osgi-model.png" format="PNG" align="center"/> |
| </imageobject> |
| <imageobject role="html"> |
| <imagedata fileref="images/spring-osgi-model.png" format="PNG" align="center"/> |
| </imageobject> |
| |
| <textobject> |
| <phrase>Bundles and Application Contexts</phrase> |
| </textobject> |
| |
| </mediaobject></para> |
| |
| <para>In this example the data layer bundle yields a data layer |
| application context that contains a number of internal components (beans). |
| Two of those beans are made publicly available outside of the application |
| context by publishing them as services in the OSGi service |
| registry.</para> |
| |
| <para>The service layer bundle yields a service layer application context |
| that contains a number of internal components (beans). Some of those |
| components depend on data layer services, and import those services from |
| the OSGi service registry. Two of the service layer components are made |
| externally available as services in the OSGi service registry.</para> |
| |
| <para>The web component bundle yields a web application context that |
| contains a number of internal components (beans). Some of those components |
| depend on application services, and import those services from the OSGi |
| service registry. Since the domain model bundle contributes only domain |
| model types, but does not need to create any components of its own, it has |
| no associated application context.</para> |
| |
| <section id="app-deploy:headers"> |
| <title>Bundle Format And Manifest Headers</title> |
| |
| <para>Each application module should be packaged as an OSGi bundle. A |
| bundle is essentially a jar file with a |
| <literal>META-INF/MANIFEST.MF</literal> file containing a series of |
| headers recognized by the OSGi Service Platform. See the OSGi Service |
| Platform Core Specification section 3.2 for details. Some OSGi |
| implementations may support exploded jar files, but the format remains |
| the same.</para> |
| |
| <para>The Spring extender recognizes a bundle as "Spring-powered" and |
| will create an associated application context when the bundle is started |
| and one or both of the following conditions is true:</para> |
| |
| <itemizedlist> |
| <listitem> |
| <para>The bundle path contains a folder |
| <literal>META-INF/spring</literal> with one or more files in that |
| folder with a '.xml' extension.</para> |
| </listitem> |
| |
| <listitem> |
| <para><literal>META-INF/MANIFEST.MF</literal> contains a manifest |
| header <literal>Spring-Context</literal>.</para> |
| </listitem> |
| </itemizedlist> |
| |
| <para>In addition, if the optional |
| <literal>SpringExtender-Version</literal> header is declared in the |
| bundle manifest, then the extender will only recognize bundles where the |
| specified version constraints are satisfied by the version of the |
| extender bundle (<literal>Bundle-Version</literal>). The value of the |
| <literal>SpringExtender-Version</literal> header must follow the syntax |
| for a version range as specified in section 3.2.5 of the OSGi Service |
| Platform Core Specification.</para> |
| |
| <para>In the absence of the <literal>Spring-Context</literal> header the |
| extender expects every ".xml" file in the |
| <literal>META-INF/spring</literal> folder to be a valid Spring |
| configuration file, and all directives (see below) take on their default |
| values.</para> |
| |
| <tip id="app-deploy:headers:xml:tip"><para>An application context is constructed from this set of files. A |
| suggested practice is to split the application context configuration |
| into at least two files, named by convention |
| <emphasis>modulename</emphasis>-context.xml and |
| <emphasis>modulename</emphasis>-osgi-context.xml. The |
| <emphasis>modulename</emphasis>-context.xml file contains regular bean |
| definitions independent of any knowledge of OSGi. The |
| <emphasis>modulename</emphasis>-osgi-context.xml file contains the bean |
| definitions for importing and exporting OSGi services. It may (but is |
| not required to) use the Gemini Blueprint OSGi schema as the |
| top-level namespace instead of the Spring 'beans' namespace.</para> |
| </tip> |
| |
| <para>The <literal>Spring-Context</literal> manifest header may be used |
| to specify an alternate set of configuration files. The resource paths |
| are treated as relative resource paths and resolve to entries defined in |
| the bundle and the set of attached <link linkend="appendix-tips:fragments">fragments</link>. |
| When the |
| <literal>Spring-Context</literal> header defines at least one |
| configuration file location, any files in |
| <literal>META-INF/spring</literal> are ignored unless directly |
| referenced from the <literal>Spring-Context</literal> header.</para> |
| |
| <para>The syntax for the <literal>Spring-Context</literal> header value |
| is:</para> |
| |
| <programlisting><![CDATA[Spring-Context-Value ::= context ( ',' context ) * |
| context ::= path ( ';' path ) * (';' directive) * |
| ]]></programlisting> |
| |
| <para>This syntax is consistent with the OSGi Service Platform common |
| header syntax defined in section 3.2.3 of the OSGi Service Platform Core |
| Specification.</para> |
| |
| <para>For example, the manifest entry:</para> |
| |
| <programlisting><![CDATA[Spring-Context: config/account-data-context.xml, config/account-security-context.xml |
| ]]></programlisting> |
| |
| <para>will cause an application context to be instantiated using the |
| configuration found in the files |
| <literal>account-data-context.xml</literal> and |
| <literal>account-security-context.xml</literal> in the bundle jar |
| file.</para> |
| |
| <para>A number of directives are available for use with the |
| <literal>Spring-Context</literal> header. These directives are:</para> |
| |
| <itemizedlist> |
| <listitem> |
| <para><emphasis>create-asynchronously</emphasis> (false|true): |
| controls whether the application context is created asynchronously |
| (the default), or synchronously.</para> |
| |
| <para>For example:</para> |
| |
| <programlisting><![CDATA[Spring-Context: *;create-asynchronously:=false |
| ]]></programlisting> |
| |
| <para>Creates an application context synchronously, using all of the |
| "*.xml" files contained in the <literal>META-INF/spring</literal> |
| folder.</para> |
| |
| <programlisting><![CDATA[Spring-Context: config/account-data-context.xml;create-asynchrously:=false |
| ]]></programlisting> |
| |
| <para>Creates an application context synchronously using the |
| <literal>config/account-data-context.xml</literal> configuration file. |
| Care must be taken when specifying synchronous context creation as the |
| application context will be created on the OSGi event thread, blocking |
| further event delivery until the context is fully initialized. If an |
| error occurs during the synchronous creation of the application context |
| then a <literal>FrameworkEvent.ERROR</literal> event is raised. The bundle will still |
| proceed to the <literal>ACTIVE</literal> state.</para> |
| </listitem> |
| |
| <listitem> |
| <para><emphasis>wait-for-dependencies</emphasis> (true|false): |
| controls whether or not application context creation should wait for |
| any mandatory service dependencies to be satisfied before proceeding |
| (the default), or proceed immediately without waiting if |
| dependencies are not satisfied upon startup.</para> |
| |
| <para>For example:</para> |
| |
| <programlisting><![CDATA[Spring-Context: config/osgi-*.xml;wait-for-dependencies:=false |
| ]]></programlisting> |
| |
| <para>Creates an application context using all the files matching |
| "osgi-*.xml" in the config directory. Context creation will begin |
| immediately even if dependencies are not satisfied. This essentially |
| means that mandatory service references are treated as though they were |
| optional - clients will be injected with a service object that may not |
| be backed by an actual service in the registry initially. See |
| <xref linkend="service-registry:refs:singular:dynamics"/> for more details.</para> |
| </listitem> |
| |
| <listitem> |
| <para><emphasis>timeout</emphasis> (300): the time to wait (in |
| seconds) for mandatory dependencies to be satisfied before giving up |
| and failing application context creation. This setting is ignored if |
| <literal>wait-for-dependencies:=false</literal> is specified. The |
| default is 5 minutes (300 seconds).</para> |
| |
| <para>For example:</para> |
| |
| <programlisting><![CDATA[Spring-Context: *;timeout:=60 |
| ]]></programlisting> |
| <para>Creates an application context that waits up to 1 minute (60 seconds) |
| for its mandatory dependencies to appear. |
| </para> |
| </listitem> |
| <listitem> |
| <para><emphasis>publish-context</emphasis> (true|false): controls |
| whether or not the application context object itself should be |
| published in the OSGi service registry. The default is to publish |
| the context.</para> |
| |
| <para>For example:</para> |
| |
| <programlisting><![CDATA[Spring-Context: *;publish-context:=false |
| ]]></programlisting> |
| |
| <para>If there is no <literal>Spring-Context</literal> manifest entry, or no value is |
| specified for a given directive in that entry, then the directive takes |
| on its default value.</para> |
| </listitem> |
| </itemizedlist> |
| |
| </section> |
| |
| <section id="app-deploy:headers:blueprint"> |
| <title>Blueprint Manifest Configuration Comparison</title> |
| |
| <para>The table below summarizes the differences between the manifest configuration options in Eclipse Gemini Blueprint/Spring DM and Blueprint Container:</para> |
| |
| <table id="sdm-vs-blueprint-config-attr" pgwide="1"> |
| <title>Configuration Setting Differences</title> |
| <tgroup cols="3"> |
| <thead> |
| <row> |
| <entry>Option</entry> |
| <entry>Gemini Blueprint/Spring DM</entry> |
| <entry>Blueprint</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>Default Configuration Location</entry> |
| <entry><literal>META-INF/spring</literal></entry> |
| <entry><literal>OSGI-INF/blueprint</literal></entry> |
| </row> |
| <row> |
| <entry>Custom Locations Header</entry> |
| <entry><literal>Spring-Context</literal></entry> |
| <entry><literal>Bundle-Blueprint</literal></entry> |
| </row> |
| <row> |
| <entry>Attribute Header</entry> |
| <entry><literal>Spring-Context</literal></entry> |
| <entry><literal>Bundle-SymbolicName</literal></entry> |
| </row> |
| <row> |
| <entry>Asynchronous Creation Attribute</entry> |
| <entry><literal>create-asynchronously</literal></entry> |
| <entry><literal>-</literal></entry> |
| </row> |
| <row> |
| <entry>Startup Mandatory Dependencies Attribute</entry> |
| <entry><literal>wait-for-dependencies</literal></entry> |
| <entry><literal>blueprint.graceperiod</literal></entry> |
| </row> |
| <row> |
| <entry>Startup Mandatory Timeout Attribute</entry> |
| <entry><literal>timeout</literal> (in s)</entry> |
| <entry><literal>blueprint.timeout</literal> (in ms)</entry> |
| </row> |
| <row> |
| <entry>Container API Service Publication Attribute</entry> |
| <entry><literal>publish-context</literal></entry> |
| <entry><literal>-</literal></entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <para>The manifests below are equivalent in terms of settings:</para> |
| |
| <programlistingco> |
| <areaspec> |
| <area id="blueprint:vs:mf:attr:sdm" coords="2 72"/> |
| <area id="blueprint:vs:mf:timeout:s" coords="4 72"/> |
| </areaspec> |
| <programlisting><![CDATA[Bundle-SymbolicName: org.example.account.bundle |
| Spring-Context: config/account-data-context.xml, config/osgi-*.xml; |
| wait-for-dependencies:=true; |
| timeout:=10 |
| ]]></programlisting> |
| <calloutlist> |
| <callout arearefs="blueprint:vs:mf:attr:sdm"> |
| <para>All Gemini Blueprint/Spring DM specific attributes are grouped under <literal>Spring-Context</literal> header.</para> |
| </callout> |
| <callout arearefs="blueprint:vs:mf:timeout:s"> |
| <para>Timeout specified in <emphasis>seconds</emphasis>.</para> |
| </callout> |
| </calloutlist> |
| </programlistingco> |
| |
| <programlistingco> |
| <areaspec> |
| <areaset id="blueprint:vs:mf:attr:bp" coords=""> |
| <area id="blueprint:vs:mf:attr:bp.1" coords="1 72"/> |
| <area id="blueprint:vs:mf:attr:bp.2" coords="4 72"/> |
| </areaset> |
| <area id="blueprint:vs:mf:timeout:ms" coords="3 72"/> |
| </areaspec> |
| <programlisting><![CDATA[Bundle-SymbolicName: org.example.account.bundle; |
| blueprint.graceperiod:=true; |
| blueprint.timeout:=10000 |
| Blueprint-Bundle: config/account-data-context.xml, config/osgi-*.xml |
| ]]></programlisting> |
| <calloutlist> |
| <callout arearefs="blueprint:vs:mf:attr:bp"> |
| <para>Blueprint settings are spread between <literal>Bundle-SymbolicName</literal> and <literal>Blueprint-Bundle</literal>.</para> |
| </callout> |
| <callout arearefs="blueprint:vs:mf:timeout:ms"> |
| <para>Timeout specified in <emphasis>milliseconds</emphasis>.</para> |
| </callout> |
| </calloutlist> |
| </programlistingco> |
| |
| </section> |
| |
| <section id="app-deploy:extender-configuration"> |
| <title>Extender Configuration Options</title> |
| |
| <para>Aside from bundle-specific configurations, Gemini Blueprint/Spring DM allows the core extender generic behaviour be configured. This is useful when |
| embedding Spring DM inside a managed environment or when a bundles-wide functionality is desired. To allow for extensible configuration, |
| the extender relies on OSGi <link linkend="appendix-tips:fragments">fragments</link> to override its defaults. The extender looks for all XML files |
| under <literal>META-INF/spring/extender</literal> folder in its bundle space and assembled them into an application context |
| (of type <classname>OsgiBundleXmlApplicationContext</classname>) |
| that is used internally as its configuration. To override a default setting of the extender, look up the appropriate bean |
| name from the table below, define it in a suitable manner and then attach it as a <link linkend="appendix-tips:fragments">fragment</link> to the |
| <literal>spring-osgi-extender.jar</literal>, using:</para> |
| <programlisting><![CDATA[Fragment-Host: org.eclipse.gemini.blueprint.extender]]></programlisting> |
| |
| <para>The following beans are currently recognized by the extender:</para> |
| |
| <table id="extender-configuration-options" pgwide="1"> |
| <title>Extender Configuration Options</title> |
| <tgroup cols="4"> |
| <thead> |
| <row> |
| <entry>Bean Name</entry> |
| <entry>Type</entry> |
| <entry>Role</entry> |
| <entry>Default Behaviour/Value</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry><literal>taskExecutor</literal></entry> |
| <entry><interfacename>TaskExecutor</interfacename> |
| <footnote>Part of <literal>org.springframework.core.task</literal> package</footnote></entry> |
| <entry>Creates and runs the Spring application contexts associated with each bundle. The task executor is responsible for managing its own pool |
| of threads used by the application contexts</entry> |
| <entry><classname>ThreadPoolTaskExecutor</classname> with a maximum number of threads equal to the number of available processors is used by default.</entry> |
| </row> |
| |
| <row> |
| <entry><literal>shutdownTaskExecutor</literal></entry> |
| <entry><interfacename>TaskExecutor</interfacename> |
| <footnote>Part of <literal>org.springframework.core.task</literal> package</footnote></entry> |
| <entry>Destroys managed Spring application contexts associated with each bundle. The task executor is responsible for managing its own pool |
| of threads used by the application contexts</entry> |
| <entry><classname>ThreadPoolTaskExecutor</classname> with a single thread is used by default which means all application context will be destroyed in a serialized manner (which is |
| desired). Since the shutdown order normally matters, it is recommended to keep the default implementation or, for managed environments, to use a thread-pool |
| that executes only one task at a time (so that contexts are stopped in the given order).</entry> |
| </row> |
| |
| <row> |
| <entry><literal>extenderProperties</literal></entry> |
| <entry><classname>java.util.Properties</classname></entry> |
| <entry>Defines simple properties such as the maximum time for contexts to gracefully close</entry> |
| <entry>See the <link linkend="extender-configuration-options-properties">defaults</link> below</entry> |
| </row> |
| |
| <row> |
| <entry><literal>osgiApplicationEventMulticaster</literal></entry> |
| <entry><interfacename>ApplicationEventMulticaster</interfacename> |
| <footnote>Part of <literal>org.springframework.context.event</literal> package</footnote> |
| </entry> |
| <entry><literal><ulink url="https://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/context/event/ApplicationEventMulticaster.html"> |
| ApplicationEventMultiCaster</ulink></literal> used for propagating Gemini Blueprint/Spring DM <link linkend="app-deploy:extender-configuration:events">events</link> |
| to third parties. |
| </entry> |
| <entry>An instance of <classname><ulink url="https://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/context/event/SimpleApplicationEventMulticaster.html"> |
| SimpleApplicationEventMulticaster</ulink></classname> is used. |
| See <classname>AbstractApplicationContext</classname> |
| <ulink url="https://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/context/support/AbstractApplicationContext.html">javadoc</ulink> |
| for more information regarding available beans in an application context.</entry> |
| </row> |
| |
| <row id="extender-configuration-options:acc"> |
| <entry><literal>applicationContextCreator</literal></entry> |
| <entry><interfacename>OsgiApplicationContextCreator</interfacename> |
| <footnote id="extender-configuration-options:extender.pkg"><literal>org.eclipse.gemini.blueprint.extender package</literal></footnote> |
| </entry> |
| <entry>Allows customization of the application context created by the extender. This includes changing the application context class type or additional |
| processing (see <link linkend="extender-configuration-options:obfpp">below</link>).</entry> |
| <entry>The Extender default behaviour applies.</entry> |
| </row> |
| |
| <row id="extender-configuration-options:obfpp"> |
| <entry><emphasis>(irrelevant)</emphasis></entry> |
| <entry><interfacename>OsgiBeanFactoryPostProcessor</interfacename> |
| <footnoteref linkend="extender-configuration-options:extender.pkg"/> |
| </entry> |
| <entry>Similar to Spring's <interfacename>BeanFactoryPostProcessor</interfacename> interface, beans of type |
| <interfacename>OsgiBeanFactoryPostProcessor</interfacename> are automatically detected and applied to all contexts created by the |
| extender (whether <link linkend="extender-configuration-options:acc">user-defined</link> or not). This type of post processor |
| is useful as it allows customization of the bean factory such as adding/removing/changing existing bean definitions or adding new bean |
| instances.</entry> |
| <entry>The Extender default behaviour applies.</entry> |
| </row> |
| |
| <row id="extender-configuration-options:contextListener"> |
| <entry><literal>osgiApplicationContextListener</literal></entry> |
| <entry><interfacename>OsgiBundleApplicationContextListener</interfacename> |
| <footnote id="extender-configuration-options:event.pkg"><literal>org.eclipse.gemini.blueprint.context.event package</literal></footnote> |
| </entry> |
| <entry>Application context event listener registered automatically by the extender.</entry> |
| <entry>Default implementation provides logging of the managed application contexts lifecycle.</entry> |
| </row> |
| |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <para>From the <literal>extenderProperties</literal> bean, the following properties are recognized:</para> |
| |
| <para>In addition, in Eclipse Gemini Blueprint a new system property has been introduced to control whether bundles providing namespace extensions should be considered in RESOLVED (default) |
| or STARTED state. The former allows namespaces to be picked up as soon as a bundle installed into the OSGi framework has its dependencies resolved - the advantage is that the namespaces become |
| available as soon as possible but on the downside, one needs to remove the source bundle in order to remove the namespace. |
| The latter forces namespaces to be considered only when the source bundles are actually started - to remove a namespace simply stop the owning bundle. However the order in which the bundles |
| are started influences the available namespace - the bundles providing the namespaces need to start before the bundles that require them - depending on the app such a dependency graph can create |
| some subtle problems (at runtime). |
| |
| Thus, if the system property <literal>org.eclipse.gemini.blueprint.ns.bundles.started</literal> is defined and set to <literal>true</literal> then only namespace bundles <emphasis>started</emphasis> |
| will be considered, if not the ones <emphasis>resolved</emphasis> will be used. |
| </para> |
| |
| <table id="extender-configuration-options-properties" pgwide="1"> |
| <title>Available <literal>extenderProperties</literal></title> |
| <tgroup cols="4"> |
| <thead> |
| <row> |
| <entry>Name</entry> |
| <entry>Type</entry> |
| <entry>Description</entry> |
| <entry>Default Value</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry><literal>shutdown.wait.time</literal></entry> |
| <entry><classname>java.lang.Long</classname></entry> |
| <entry>The amount of time the extender will wait for each application context to shutdown gracefully. Expressed in milliseconds.</entry> |
| <entry>10000 ms (10 s)</entry> |
| </row> |
| |
| <row> |
| <entry><literal>shutdown.asynchronously</literal></entry> |
| <entry><classname>boolean</classname></entry> |
| <entry> |
| Whether the extender shall shutdown each application context asynchronously. If <literal>false</literal>, |
| the <literal>shutdown.wait.time</literal> is ignored. Accordingly, application contexts blocking during close will block the bundle shutdown. |
| </entry> |
| <entry><literal>true</literal></entry> |
| </row> |
| |
| <row> |
| <entry><literal>dependencies.wait.time</literal></entry> |
| <entry><classname>java.lang.Long</classname></entry> |
| <entry>The amount of time the newly created application contexts will wait for their mandatory service dependencies during startup. Expressed |
| in milliseconds. This settings is used only if the context owning bundle manifest does <emphasis>not</emphasis> define a value. </entry> |
| <entry>300000 ms (300 s or 5 min)</entry> |
| </row> |
| |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <note>Since an application context is used, the full power of the Spring IoC container can be used for creating the extender configuration beans.</note> |
| |
| <section id="app-deploy:extender-configuration:events"> |
| <title>Listening To Extender Events</title> |
| |
| <para>There are cases when the failure or succesful startup of an application context needs to be acknowledged for logging purposes (for example). |
| For these cases, Gemini Blueprint/Spring DM offers a dedicated package <literal>org.eclipse.gemini.blueprint.context.event</literal> which defines the events that |
| OSGi application contexts can send during their lifecycle. At the moment, the following events are available:</para> |
| |
| <table id="app-deploy:extender-configuration:events-table" pgwide="1"> |
| <title>Gemini Blueprint/Spring DM build-in events</title> |
| <tgroup cols="2"> |
| <thead> |
| <row> |
| <entry>Event</entry> |
| <entry>Explanation</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry><classname>OsgiBundleContextRefreshedEvent</classname></entry> |
| <entry>Published when an OSGi application context has been succesfully initialized or refreshed (e.g. using the |
| <methodname>refresh()</methodname> method on the <interfacename>ConfigurableApplicationContext</interfacename> interface). |
| There are no guarantees on how many times this event might be received during the lifecycle of an application context - this is |
| left up to the used implementation.</entry> |
| </row> |
| |
| <row> |
| <entry><classname>OsgiBundleContextFailedEvent</classname></entry> |
| <entry>Published when an OSGi application context is closed due to a failure. This event can appear any time during the lifecycle |
| of an application context - before, during or after refresh. Usually the cause indicates an error in the configuration - syntax typo, |
| incorrect wiring, missing bean and so forth.</entry> |
| </row> |
| |
| <row> |
| <entry><classname>OsgiBundleContextClosedEvent</classname></entry> |
| <entry>Published when an OSGi application context is closed after a successful refresh (normally issued a Spring bundle is being stopped). |
| </entry> |
| </row> |
| |
| |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <para>Parties interested in receiving these events should implement <interfacename>OsgiBundleApplicationContextListener</interfacename> and |
| then publish it as an OSGi service. The Gemini Blueprint/Spring DM extender will automatically detect the listener and will send the events to it. By taking advantage |
| of the OSGi service registry, the extender decouples the received from the event publisher and moreover, makes the registration/unregistration process |
| easier. For example, there is nothing special a client should do to unregister the listener - simply stopping the bundle will automatically |
| unregister all its published services (including the listener), an event which will detected by the extender which will remove the listener. |
| Of course, it is also possible for the client to unregister the listener manually during a bundle lifecycle. |
| |
| <note>The Gemini Blueprint/Spring DM events semantics are slightly different then |
| <ulink url="http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/beans.html#context-functionality-events">Spring's</ulink>. The OSGi events are |
| not sent to beans inside the <emphasis>causing</emphasis> application context but to other parties (possible beans in other application contexts) |
| interested in monitoring its behaviour.</note> |
| </para> |
| </section> |
| </section> |
| |
| |
| <section id="app-deploy:required-libraries"> |
| <title>Required Spring Framework And Gemini Blueprint |
| Bundles</title> |
| |
| <para>The Gemini Blueprint project provides a number of bundle |
| artifacts that must be installed in your OSGi platform in order for the |
| Spring extender to function correctly:</para> |
| |
| <itemizedlist> |
| <listitem> |
| <para>The extender bundle itself, |
| <literal>org.eclipse.gemini.blueprint.extender</literal></para> |
| </listitem> |
| |
| <listitem> |
| <para>The core implementation bundle for the Gemini Blueprint |
| support, <literal>org.eclipse.gemini.blueprint.core</literal></para> |
| </listitem> |
| |
| <listitem> |
| <para>The Gemini Blueprint I/O support library bundle, |
| <literal>org.eclipse.gemini.blueprint.io</literal></para> |
| </listitem> |
| </itemizedlist> |
| |
| <para>In addition, the Spring Framework provides a number of bundles that |
| are required to be installed as dependencies. As of release 4.2.4 of the |
| Spring Framework, OSGi bundle versions are maintained by the Apache ServiceMix team and published using their group id, see for example |
| <ulink url="http://search.maven.org/#search|ga|1|g%3Aorg.apache.servicemix.bundles%20spring-">all Spring OSGi artifacts published in maven central</ulink>. |
| </para> |
| </section> |
| |
| <section id="app-deploy:optional-libraries"> |
| <title>Optional Gemini Blueprint Bundles</title> |
| |
| <para>Optionally, the following bundles may be installed to augment the Gemini Blueprint core functionality:</para> |
| |
| <itemizedlist> |
| <listitem> |
| <para>The Gemini Blueprint propriertary extensions bundle, |
| <literal>org.eclipse.gemini.blueprint.extensions</literal></para> |
| </listitem> |
| </itemizedlist> |
| </section> |
| |
| <section id="app-deploy:spring-namespaces"> |
| <title>Spring XML Authoring Support</title> |
| |
| <para>Spring 2.0 introduced (among other things) <ulink url="https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/oxm.html#oxm-schema-based-config"> |
| easier</ulink> XML configuration and <ulink url="https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/xml-custom.html"> |
| extensible</ulink> XML authoring. The latter gives the ability of creating custom schemas that are discovered automatically (in non-OSGi environment) |
| by the Spring XML infrastructure by including them in the classpath. Gemini Blueprint/Spring DM is aware of this process and supports it in OSGi environments so |
| that custom schemas are available to bundles that use them without any extra code or manifest declaration.</para> |
| <para>All bundles deployed in the OSGi space (whether they are <literal>Spring-powered</literal> or not) are scanned by Gemini Blueprint/Spring DM for |
| custom Spring namespace declaration (by checking the bundle space for<literal>META-INF/spring.handlers</literal> and |
| <literal>META-INF/spring.schemas</literal>). If these are found, Gemini Blueprint/Spring DM will make the schemas and the namespaces available through an OSGi |
| service that will be automatically used by Spring-powered bundles. This mean that if you deploy a bundle that uses a custom schema, all you have to do |
| is deploy the library that provides the namespace parser and the schema. |
| Bundles that embedded inside their classpath libraries that provide custom schemas will use these over those available in the OSGi space. However, |
| the namespaces of the embedded libraries will not shared with other bundles, that is, they will not be seen by any other bundle.</para> |
| <para> |
| In short, when using Gemini Blueprint/Spring DM, custom Spring namespaces are supported transparently without any additional work. Embedded namespace providers will |
| have priority but will not be shared, as opposed to providers deployed as bundles which will be seen (and used) by others.</para> |
| </section> |
| |
| <section id="app-deploy:imports-exports"> |
| <title>Importing and Exporting Packages</title> |
| |
| <para>Refer to the OSGi Service Platform for details of the |
| <literal>Import-Package</literal> and <literal>Export-Package</literal> |
| manifest headers. Your bundle will need an |
| <literal>Import-Package</literal> entry for every external package that |
| the bundle depends on. If your bundle provides types that other bundles |
| need access to, you will need <literal>Export-Package</literal> entries |
| for every package that should be available from outside of the |
| bundle.</para> |
| |
| <important>Both <literal>Export</literal> and <literal>Import-Package</literal> have a crucial role in defining a bundle class space. If used incorrectly, |
| the bundle might not be able to load certain classes or resources, load incorrect versions or even load multiple versions at the same time which usually |
| result in <literal>ClassCastException</literal>, <literal>NoClassDefFoundError</literal> or <literal>LinkageError</literal>. We strongly |
| recommend that you get familiar with the basics and, at least for starters, use tools |
| (such as <ulink url="https://docs.spring.io/s2-bundlor/1.0.x/user-guide/html/">Bundlor</ulink> or <ulink url="http://www.aqute.biz/Bnd/Bnd">BND</ulink>) for creating proper |
| OSGi manifests.</important> |
| </section> |
| |
| <section id="app-deploy:ext-libs"> |
| <title>Considerations When Using External Libraries</title> |
| |
| <sidebar> |
| <title>What is the context class loader?</title> |
| |
| <para> |
| The thread context class loader was introduced in J2SE without much fanfare. |
| Below is a short definition for it, quoted from <ulink url="http://java.sun.com/products/jndi/tutorial/beyond/misc/classloader.html">one |
| </ulink> of the tutorials available on <ulink url="http://java.sun.com/">Java</ulink> site: |
| </para> |
| <para> |
| The Java 2 platform also introduced the notion of <emphasis>context class loader</emphasis>. A thread's context class loader is, by default, |
| set to the context class loader of the thread's parent. The hierarchy of threads is rooted at the primordial thread (the one that runs the program). |
| The context class loader of the primordial thread is set to the class loader that loaded the application. So unless you explicitly change |
| the thread's context class loader, its context class loader will be the application's class loader. That is, the context class loader can |
| load the classes that the application can load. This loader is used by the Java runtime such as the RMI (Java Remote Method Invocation) to |
| load classes and resources on behalf of the user application. The context class loader, like any Java 2 platform class loader, has a parent |
| class loader and supports the same delegation model for class loading described previously. |
| </para> |
| </sidebar> |
| |
| <para>Many enterprise application libraries assume that all of the types |
| and resources that comprise the application are accessible through the |
| context class loader. While most developers do not use the context class |
| loader, the loader is used heavily by application servers, containers or |
| applications that are multi-threaded.</para> |
| |
| <para> |
| In OSGi R4, the set of types and resources |
| available through the context class loader is undefined. |
| This means that the OSGi platform does not make a guarantee of the thread context |
| class loader value or in other words, it does not manage it. |
| </para> |
| <para> |
| Thus code (for example libraries) that performs manual class loading or that generates |
| new classes dynamically can cause problems when executed inside an OSGi environment. |
| </para> |
| |
| <para>Gemini Blueprint guarantees that during the creation of an |
| application context on behalf of a given bundle, all of the types and |
| resources on the bundle's classpath are accessible via the context class |
| loader. Gemini Blueprint also allows you to control what is |
| accessible through the context class loader when invoking external |
| services and when servicing requests on exported services. See <xref linkend="service-registry"/> |
| for details on this.</para> |
| |
| <para>Work is underway in the OSGi R5 timeframe to provide standardized |
| support for dealing with generated classes and implicit class path |
| dependencies introduced by third-party libraries. In the interim you may |
| need to rely on workarounds such as the |
| <literal>DynamicImport-Package</literal> manifest header, or the |
| facilities provided by specific OSGi implementations such as Equinox's |
| buddy mechanism. The Gemini Blueprint documentation contains more |
| details on known issues with common enterprise libraries and the |
| workarounds.</para> |
| </section> |
| |
| <section id="app-deploy:troubleshooting"> |
| <title>Diagnosing Problems</title> |
| |
| <para>Your chosen OSGi platform implementation should be able to provide |
| you with a good deal of information about the current status of the OSGi |
| environment. For example, starting Equinox with the |
| <literal>-console</literal> argument provides a command-line console |
| through which you can determine which bundles are installed and their |
| states, the packages and services exported by bundles, find out why a |
| bundle has failed to resolve, and drive bundles through the |
| lifecycle. All the OSGi platform tested, provide their own logging, which |
| can be enabled and customized through dedicated settings. For more information, |
| please refer to OSGi platforms documentation.</para> |
| |
| <para>In addition, Spring itself and the Gemini Blueprint bundles |
| contain extensive logging instrumentation that can help you diagnose |
| problems. The recommended approach is to deploy the Simple Logging |
| Facade for Java (<ulink url="http://www.slf4j.org/">slf4j</ulink>) |
| slf4j-api.jar and slf4j-log4j13.jar bundles (the jar files distributed |
| by the project are valid OSGi bundles). Then you simply need to create a |
| <literal>log4j.properties</literal> file in the root of your bundle |
| classpath.</para> |
| |
| <para>Managed, OSGi-aware runtime environments such as |
| <ulink url="http://docs.spring.io/s2-dmserver/2.0.x/user-guide/html/">dmServer</ulink> |
| provide additional logging and insight not just for the bundle at hand, but also |
| regarding the application context and the VM among other things.</para> |
| |
| <para>Note that Gemini Blueprint uses commons-logging API internally |
| which means that its logging implementation is fully pluggable. Please see |
| the FAQ and Resources pages for more information on other logging libraries |
| besides log4j. |
| </para> |
| </section> |
| |
| </chapter> |