ws-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From veit...@apache.org
Subject svn commit: r1601686 [2/2] - /webservices/axiom/trunk/devguide/src/docbkx/devguide.xml
Date Tue, 10 Jun 2014 16:55:48 GMT

Modified: webservices/axiom/trunk/devguide/src/docbkx/devguide.xml
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/devguide/src/docbkx/devguide.xml?rev=1601686&r1=1601685&r2=1601686&view=diff
==============================================================================
--- webservices/axiom/trunk/devguide/src/docbkx/devguide.xml (original)
+++ webservices/axiom/trunk/devguide/src/docbkx/devguide.xml Tue Jun 10 16:55:47 2014
@@ -170,760 +170,763 @@ javax.xml.stream.XMLOutputFactory=com.be
     </chapter>
     
     <chapter>
-        <title>OSGi integration and separation between API and implementation</title>
+        <title>Design</title>
         <section>
-            <title>Introduction</title>
-            <para>
-                This chapter addresses two related architectural questions:
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        OSGi support was originally introduced in Axiom 1.2.9, but the implementation had
-                        a couple of flaws. This chapter discusses the rationale behind the new OSGi
-                        support introduced in Axiom 1.2.13.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Axiom is designed as a set of abstract APIs for which two implementations are
-                        provided: LLOM and DOOM. It is important to make a clear distinction between what
-                        is part of the public API and what should be considered implementation classes that
-                        must not be used by application code directly. This also implies that Axiom must
-                        provide the necessary APIs to allow application code to access all features without
-                        the need to access implementation classes directly. This chapter in particular
-                        discusses the question how application code can request factories that support DOM
-                        without the need to refer directly to DOOM.
-                    </para>
-                </listitem>
-            </itemizedlist>
-            <para>
-                These two questions are closely related because OSGi allows to enforce the distinction
-                between public API and implementation classes by carefully selecting the packages
-                exported by the different bundles: only classes belonging to the public API
-                should be exported, while implementation classes should be private to the bundles
-                containing them. This in turn has implications for the packaging of these artifacts.
-            </para>
-        </section>
-        <section>
-            <title>Requirements</title>
-            <formalpara xml:id="osgi-req-no-separate-bundles">
-                <title>Requirement 1</title>
-                <para>
-                    The Axiom artifacts SHOULD be usable both as normal JAR files and as OSGi bundles.
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    The alternative would be to produce two sets of artifacts during the build. This
-                    should be avoided in order to keep the build process as simple as possible.
-                    It should also be noted that the Geronimo Spec artifacts also meet this requirement.
-                </para>
-            </note>
-            <formalpara xml:id="osgi-req-same-api">
-                <title>Requirement 2</title>
-                <para>
-                    All APIs defined by the <literal>axiom-api</literal> module, and in particular the
-                    <classname>OMAbstractFactory</classname> API MUST continue to work
-                    as expected in an OSGi environment, so that code in downstream projects
-                    doesn't need to be rewritten.
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    This requirement was already satisfied by the OSGi support introduced in Axiom 1.2.9.
-                    It therefore also ensures that the transition to the new OSGi support in Axiom 1.2.13
-                    is transparent for applications that already use Axiom in an OSGi container.
-                </para>
-            </note>
-            <formalpara xml:id="osgi-req-same-impl-selection">
-                <title>Requirement 3</title>
-                <para>
-                    <classname>OMAbstractFactory</classname> MUST select the same implementation
-                    regardless of the type of container (OSGi or non OSGi). The only exception is
-                    related to the usage of system properties to specify the default <classname>OMMetaFactory</classname>
-                    implementation: in an OSGi environment, selecting an implementation class using
-                    a system property is not meaningful.
-                </para>
-            </formalpara>
-            <formalpara xml:id="osgi-ref-impl-not-exported">
-                <title>Requirement 4</title>
-                <para>
-                    Only classes belonging to the public API should be exported by the OSGi bundles.
-                    Implementation classes should not be exported. In particular,
-                    the bundles for the LLOM and DOOM implementations MUST NOT export any packages.
-                    This is required to keep a clean separation between the public API and implementation
-                    specific classes and to make sure that the implementations can be modified without the
-                    risk of breaking existing code.
-                    An exception MAY be made for factory classes related to foreign APIs, such as the
-                    <classname>DocumentBuilderFactory</classname> implementation for an Axiom implementation
-                    supporting DOM.
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    When the Axiom artifacts are used as normal JAR files in a Maven build, this requirement implies that
-                    they should be used in scope <literal>runtime</literal>.
-                </para>
+            <title>OSGi integration and separation between API and implementation</title>
+            <section>
+                <title>Introduction</title>
                 <para>
-                    Although this requirement is easy to implement for the Axiom project, it requires
-                    changes to downstreams project to make this actually work:
+                    This section addresses two related architectural questions:
                 </para>
                 <itemizedlist>
                     <listitem>
                         <para>
-                            As explained in <link xlink:href="https://issues.apache.org/jira/browse/AXIS2-4902">AXIS2-4902</link>,
-                            there used to be many places in Axis2 that still referred directly to Axiom implementation classes.
-                            The same was true for Rampart and Sandesha2. This has now been fixed and all three projects
-                            use <literal>axiom-impl</literal> and <literal>axiom-dom</literal> as dependencies in scope
-                            <literal>runtime</literal>.
+                            OSGi support was originally introduced in Axiom 1.2.9, but the implementation had
+                            a couple of flaws. This section discusses the rationale behind the new OSGi
+                            support introduced in Axiom 1.2.13.
                         </para>
                     </listitem>
                     <listitem>
                         <para>
-                            Abdera extends the LLOM implementation. Probably, some <literal>maven-shade-plugin</literal>
-                            magic will be required here to create Abdera OSGi bundles that work properly with
-                            the Axiom bundles.
-                        </para>
-                    </listitem>
-                    <listitem>
-                        <para>
-                            For Spring Web Services this issue is addressed by
-                            <link xlink:href="https://jira.springsource.org/browse/SWS-822">SWS-822</link>.
+                            Axiom is designed as a set of abstract APIs for which two implementations are
+                            provided: LLOM and DOOM. It is important to make a clear distinction between what
+                            is part of the public API and what should be considered implementation classes that
+                            must not be used by application code directly. This also implies that Axiom must
+                            provide the necessary APIs to allow application code to access all features without
+                            the need to access implementation classes directly. This section in particular
+                            discusses the question how application code can request factories that support DOM
+                            without the need to refer directly to DOOM.
                         </para>
                     </listitem>
                 </itemizedlist>
-            </note>
-            <formalpara xml:id="osgi-req-dropin">
-                <title>Requirement 5</title>
-                <para>
-                    It MUST be possible to use a non standard (third party) Axiom implementation as a drop-in replacement
-                    for the standard LLOM and DOOM implementation, i.e. the <literal>axiom-impl</literal>
-                    and <literal>axiom-dom</literal> bundles. It MUST be possible to replace <literal>axiom-impl</literal>
-                    (resp. <literal>axiom-dom</literal>) by any Axiom implementation that supports the full Axiom API
-                    (resp. that supports DOM in addition to the Axiom API), without the need to change any application code.
-                </para>
-            </formalpara>
-            <note>
                 <para>
-                    This requirement has several important implications:
-                </para>
-                <itemizedlist>
-                    <listitem>
-                        <para>
-                            It restricts the allowable exceptions to <xref linkend="osgi-ref-impl-not-exported"/>.
-                        </para>
-                    </listitem>
-                    <listitem>
-                        <para>
-                            It implies that there must be an API that allows application code to select an Axiom
-                            implementation based on its capabilities (e.g. DOM support) without introducing a
-                            hard dependency on a particular Axiom implementation.
-                        </para>
-                    </listitem>
-                    <listitem>
-                        <para>
-                            In accordance with <xref linkend="osgi-req-same-api"/> and <xref linkend="osgi-req-same-impl-selection"/>
-                            this requirement not only applies to an OSGi environment, but extends to non OSGi environments as well.
-                        </para>
-                    </listitem>
-                </itemizedlist>
-            </note>
-            <formalpara>
-                <title>Requirement 6</title>
-                <para>
-                    The OSGi integration SHOULD remove the necessity for downstreams projects
-                    to produce their own custom OSGi bundles for Axiom. There SHOULD be one
-                    and only one set of OSGi bundles for Axiom, namely the ones released by the Axiom project.
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    Currently there are at least two projects that create their own modified Axiom bundles:
-                </para>
-                <itemizedlist>
-                    <listitem>
-                        <para>
-                            Apache Geronimo has a custom Axiom bundle to support the Axis2 integration.
-                        </para>
-                    </listitem>
-                    <listitem>
-                        <para>
-                            ServiceMix also has a custom bundles for Axiom. However, this bundle only seem to exist to
-                            support their own custom Abdera bundle, which is basically an incorrect repackaging of the
-                            original Abdera code. See
-                            <link xlink:href="https://issues.apache.org/jira/browse/SMX4-877">SMX4-877</link> for more details.
-                        </para>
-                    </listitem>
-                </itemizedlist>
-                <para>
-                    Note that this requirement can't be satisfied directly by Axiom. It requires that
-                    the above mentioned projects (Geronimo, Axis2 and Abdera) use Axiom in a way that is
-                    compatible with its design, and in particular with <xref linkend="osgi-ref-impl-not-exported"/>.
-                    Nevertheless, Axiom must provide the necessary APIs and features to meet the needs
-                    of these projects.
-                </para>
-            </note>
-            <formalpara xml:id="osgi-reg-no-framework">
-                <title>Requirement 7</title>
-                <para>
-                    The Axiom OSGi integration SHOULD NOT rely on any particular OSGi framework such
-                    as Felix SCR (Declarative Services). When deployed in an OSGi environment, Axiom should have the same
-                    runtime dependencies as in a non OSGi environment (i.e. StAX, Activation and JavaMail).
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    Axiom 1.2.12 relies on Felix SCR. Although there is no real issue with that, getting rid
-                    of this extra dependency is seen as a nice to have. One of the reasons for using Felix SCR
-                    was to avoid introducing OSGi specific code into Axiom. However, there is no issue with
-                    having such code, provided that <xref linkend="osgi-req-no-osgi-dep"/> is satisfied.
-                </para>
-            </note>
-            <formalpara xml:id="osgi-req-no-osgi-dep">
-                <title>Requirement 8</title>
-                <para>
-                    In a non OSGi environment, Axiom MUST NOT have any OSGi related dependencies. That means
-                    that the OSGi integration must be written in such a way that no OSGi specific classes are
-                    ever loaded in a non OSGi environment.
-                </para>
-            </formalpara>
-            <formalpara xml:id="osgi-req-best-practices">
-                <title>Requirement 9</title>
-                <para>
-                    The OSGi integration MUST follow established best practices. It SHOULD be inspired by
-                    what has been done to add OSGi integration to APIs that have a similar structure as Axiom.
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    Axiom is designed around an abstract API and allows for the existence of multiple
-                    independent implementations. A factory (<classname>OMAbstractFactory</classname>) is used to
-                    locate and instantiate the desired implementation. This is similar to APIs such as
-                    JAXP (<classname>DocumentBuilderFactory</classname>, etc.) and JAXB (<classname>JAXBContext</classname>).
-                    These APIs have been successfully "OSGi-fied" e.g. by the Apache Geronimo project.
-                    Instead of reinventing the wheel, we should leverage that work and adapt it to
-                    Axiom's specific requirements.
-                </para>
-                <para>
-                    It should be noted that because of the way the Axiom API is designed and taking into account
-                    <xref linkend="osgi-req-same-api"/>, it is not possible to make Axiom entirely compatible
-                    with OSGi paradigms (the same is true for JAXB). In an OSGi-only world, each Axiom
-                    implementation would simply expose itself as an OSGi service (of type <classname>OMMetaFactory</classname> e.g.)
-                    and code depending on Axiom would bind to one (or more) of these services depending on its needs.
-                    That is not possible because it would conflict with <xref linkend="osgi-req-same-api"/>.
-                </para>
-            </note>
-            <formalpara>
-                <title>Non-Requirement 1</title>
-                <para>
-                    APIs such as JAXP and JAXB have been designed from the start for inclusion into the JRE.
-                    They need to support scenarios where an application bundles its own implementation
-                    (e.g. an application may package a version of Apache Xerces, which would then be
-                    instantiated by the <methodname>newInstance</methodname> method in
-                    <classname>DocumentBuilderFactory</classname>). That implies that the selected implementation
-                    depends on the thread context class loader. It is assumed that there is no such requirement
-                    for Axiom, which means that in a non OSGi environment, the Axiom implementations are always loaded from the same
-                    class loader as the <literal>axiom-api</literal> JAR.
-                </para>
-            </formalpara>
-            <note>
-                <para>
-                    This (non-)requirement is actually not directly relevant for the OSGi support, but it
-                    nevertheless has some importance because of <xref linkend="osgi-req-same-impl-selection"/>
-                    (which implies that the OSGi support needs to be designed in parallel with the implementation
-                    discovery strategy applicable in a non OSGi environment).
-                </para>
-            </note>
-        </section>
-        <section>
-            <title>Analysis of the Geronimo JAXB bundles</title>
-            <para>
-                As noted in <xref linkend="osgi-req-best-practices"/> the Apache Geronimo has successfully
-                added OSGi support to the JAXB API which has a structure similar to the Axiom API. This section briefly describes
-                how this works. The analysis refers to the following Geronimo artifacts: 
-                <literal>org.apache.geronimo.specs:geronimo-jaxb_2.2_spec:1.0.1</literal> (called the "API bundle" hereafter),
-                <literal>org.apache.geronimo.bundles:jaxb-impl:2.2.3-1_1</literal> (the "implementation bundle"),
-                <literal>org.apache.geronimo.specs:geronimo-osgi-locator:1.0</literal> (the "locator bundle") and
-                <literal>org.apache.geronimo.specs:geronimo-osgi-registry:1.0</literal> (the "registry bundle"):
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        The implementation bundle retains the <filename>META-INF/services/javax.xml.bind.JAXBContext</filename>
-                        resource from the original artifact (<literal>com.sun.xml.bind:jaxb-impl</literal>).
-                        In a non OSGi environment, that resource will be used to discover the implementation, following
-                        the standard JDK 1.3 service discovery algorithm will (as required by the JAXB specification).
-                        This is the equivalent of our <xref linkend="osgi-req-no-separate-bundles"/>.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        The manifest of the implementation bundle has an attribute <literal>SPI-Provider: true</literal> that indicates
-                        that it contains provider implementations that are discovered using the JDK 1.3 service discovery.
-                    </para>
-                </listitem>
-                <listitem>
+                    These two questions are closely related because OSGi allows to enforce the distinction
+                    between public API and implementation classes by carefully selecting the packages
+                    exported by the different bundles: only classes belonging to the public API
+                    should be exported, while implementation classes should be private to the bundles
+                    containing them. This in turn has implications for the packaging of these artifacts.
+                </para>
+            </section>
+            <section>
+                <title>Requirements</title>
+                <formalpara xml:id="osgi-req-no-separate-bundles">
+                    <title>Requirement 1</title>
+                    <para>
+                        The Axiom artifacts SHOULD be usable both as normal JAR files and as OSGi bundles.
+                    </para>
+                </formalpara>
+                <note>
+                    <para>
+                        The alternative would be to produce two sets of artifacts during the build. This
+                        should be avoided in order to keep the build process as simple as possible.
+                        It should also be noted that the Geronimo Spec artifacts also meet this requirement.
+                    </para>
+                </note>
+                <formalpara xml:id="osgi-req-same-api">
+                    <title>Requirement 2</title>
+                    <para>
+                        All APIs defined by the <literal>axiom-api</literal> module, and in particular the
+                        <classname>OMAbstractFactory</classname> API MUST continue to work
+                        as expected in an OSGi environment, so that code in downstream projects
+                        doesn't need to be rewritten.
+                    </para>
+                </formalpara>
+                <note>
+                    <para>
+                        This requirement was already satisfied by the OSGi support introduced in Axiom 1.2.9.
+                        It therefore also ensures that the transition to the new OSGi support in Axiom 1.2.13
+                        is transparent for applications that already use Axiom in an OSGi container.
+                    </para>
+                </note>
+                <formalpara xml:id="osgi-req-same-impl-selection">
+                    <title>Requirement 3</title>
+                    <para>
+                        <classname>OMAbstractFactory</classname> MUST select the same implementation
+                        regardless of the type of container (OSGi or non OSGi). The only exception is
+                        related to the usage of system properties to specify the default <classname>OMMetaFactory</classname>
+                        implementation: in an OSGi environment, selecting an implementation class using
+                        a system property is not meaningful.
+                    </para>
+                </formalpara>
+                <formalpara xml:id="osgi-ref-impl-not-exported">
+                    <title>Requirement 4</title>
+                    <para>
+                        Only classes belonging to the public API should be exported by the OSGi bundles.
+                        Implementation classes should not be exported. In particular,
+                        the bundles for the LLOM and DOOM implementations MUST NOT export any packages.
+                        This is required to keep a clean separation between the public API and implementation
+                        specific classes and to make sure that the implementations can be modified without the
+                        risk of breaking existing code.
+                        An exception MAY be made for factory classes related to foreign APIs, such as the
+                        <classname>DocumentBuilderFactory</classname> implementation for an Axiom implementation
+                        supporting DOM.
+                    </para>
+                </formalpara>
+                <note>
                     <para>
-                        The registry bundle creates a <classname>BundleTracker</classname> that looks for
-                        the <literal>SPI-Provider</literal> attribute in active bundles. For each bundle
-                        that has this attribute set to <literal>true</literal>, it will scan the content of
-                        <filename>META-INF/services</filename> and add the discovered services to a registry
-                        (Note that the registry bundle supports other ways to declare SPI providers,
-                        but this is not really relevant for the present discussion).
+                        When the Axiom artifacts are used as normal JAR files in a Maven build, this requirement implies that
+                        they should be used in scope <literal>runtime</literal>.
                     </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        The <classname>ContextFinder</classname> class (the interface of which is defined by
-                        the JAXB specification and that is used by the <methodname>newInstance</methodname>
-                        method in <classname>JAXBContext</classname>) in the API bundle delegates the discovery
-                        of the SPI implementation to a static method of the <classname>ProviderLocator</classname>
-                        class defined by the locator bundle (which is not specific to JAXB and is used by other
-                        API bundles as well). This is true both in an OSGi environment and in a non OSGi environment.
-                    </para>
-                    <para>
-                        The build is configured (using a <literal>Private-Package</literal> instruction)
-                        such that the classes of the locator bundle are actually included into the API bundle, thus
-                        avoiding an additional dependency.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        The <classname>ProviderLocator</classname> class and related code provided by the locator bundle is designed
-                        such that in a non OSGi environment, it will simply use JDK 1.3 service discovery to locate
-                        the SPI implementation, without ever loading any OSGi specific class. On the other hand,
-                        in an OSGi environment, it will query the registry maintained by the registry bundle to locate
-                        the provider. The reference to the registry is injected into the <classname>ProviderLocator</classname>
-                        class using a bundle activator.
-                    </para>
-                </listitem>
-                <listitem>
                     <para>
-                        Finally, it should also be noted that the API bundle is configured with <literal>singleton=true</literal>.
-                        There is indeed no meaningful way how providers could be matched with different versions of the same API
-                        bundle.
-                    </para>
-                </listitem>
-            </itemizedlist>
-            <para>
-                This is an example of a particularly elegant way to satisfy <xref linkend="osgi-req-no-separate-bundles"/>,
-                <xref linkend="osgi-req-same-api"/> and <xref linkend="osgi-req-same-impl-selection"/>, especially because
-                it relies on the same metadata (the <filename>META-INF/services/javax.xml.bind.JAXBContext</filename> resources)
-                in OSGi and non OSGi environments.
-            </para>
-            <para>
-                Obviously, Axiom could reuse the registry and locator bundles developed by Geronimo. This however would
-                contradict <xref linkend="osgi-reg-no-framework"/>. In addition, for Axiom there is no requirement to
-                strictly follow the JDK 1.3 service discovery algorithm. Therefore Axiom should reuse the pattern
-                developed by Geronimo, but not the actual implementation.
-            </para>
-        </section>
-        <section>
-            <title>New abstract APIs</title>
-            <para>
-                Application code rarely uses DOOM as the default Axiom implementation. Several downstream projects
-                (e.g. the Axis2/Rampart combination) use both the default (LLOM) implementation and DOOM. They select
-                the implementation based on the particular context. As of Axiom 1.2.12, the only way to create an object
-                model instance with the DOOM implementation is to use the <classname>DOOMAbstractFactory</classname> API
-                or to instantiate one of the factory classes (<classname>OMDOMMetaFactory</classname>, <classname>OMDOMFactory</classname>
-                or one of the subclasses of <classname>DOMSOAPFactory</classname>). All these classes are part of
-                the <literal>axiom-dom</literal> artifact. This is clearly in contradiction with <xref linkend="osgi-ref-impl-not-exported"/>
-                and <xref linkend="osgi-req-dropin"/>.
-            </para>
-            <para>
-                To overcome this problem the Axiom API must be enhanced to make it possible to select an Axiom
-                implementation based on capabilities/features requested by the application code. E.g. in the case
-                of DOOM, the application code would request a factory that implements the DOM API. It is then up
-                to the Axiom API classes to locate an appropriate implementation, which may be DOOM or another
-                drop-in replacement, as per <xref linkend="osgi-req-dropin"/>.
-            </para>
-            <para>
-                If multiple Axiom implementations are available (on the class path in non OSGi environment or
-                deployed as bundles in an OSGi environment), then the Axiom API must also be able to select an
-                appropriate default implementation if no specific feature is requested by the application code.
-                This can be easily implemented by defining a special feature called "default" that would be
-                declared by any Axiom implementation that is suitable as a default implementation.
-            </para>
-            <note>
-                <para>
-                    DOOM is generally not considered suitable as a default implementation because it doesn't
-                    implement the complete Axiom API (e.g. it doesn't support <classname>OMSourcedElement</classname>).
-                    In addition, in earlier versions of Axiom, the factory classes for DOOM were not stateless
-                    (see <link xlink:href="https://issues.apache.org/jira/browse/AXIOM-412">AXIOM-412</link>).
-                </para>
-            </note>
-            <para>
-                Finally, to make the selection algorithm deterministic, there should also be a concept
-                of priority: if multiple Axiom implementations are found for the same feature, then the Axiom API
-                would select the one with the highest priority.
-            </para>
-            <para>
-                This leads to the following design:
-            </para>
-            <orderedlist>
-                <listitem>
-                    <para>
-                        Every Axiom implementation declares a set of features that it supports. A feature is
-                        simply identified by a string. Two features are predefined by the Axiom API:
+                        Although this requirement is easy to implement for the Axiom project, it requires
+                        changes to downstreams project to make this actually work:
                     </para>
                     <itemizedlist>
                         <listitem>
                             <para>
-                                <literal>default</literal>: indicates that the implementation is a complete
-                                implementation of the Axiom API and may be used as a default implementation.
+                                As explained in <link xlink:href="https://issues.apache.org/jira/browse/AXIS2-4902">AXIS2-4902</link>,
+                                there used to be many places in Axis2 that still referred directly to Axiom implementation classes.
+                                The same was true for Rampart and Sandesha2. This has now been fixed and all three projects
+                                use <literal>axiom-impl</literal> and <literal>axiom-dom</literal> as dependencies in scope
+                                <literal>runtime</literal>.
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                                Abdera extends the LLOM implementation. Probably, some <literal>maven-shade-plugin</literal>
+                                magic will be required here to create Abdera OSGi bundles that work properly with
+                                the Axiom bundles.
                             </para>
                         </listitem>
                         <listitem>
                             <para>
-                                <literal>dom</literal>: indicates that the implementation supports DOM
-                                in addition to the Axiom API.
+                                For Spring Web Services this issue is addressed by
+                                <link xlink:href="https://jira.springsource.org/browse/SWS-822">SWS-822</link>.
                             </para>
                         </listitem>
                     </itemizedlist>
-                    <para>
-                        For every feature it declares, the Axiom implementation specifies a priority,
-                        which is a positive integer.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        The relevant Axiom APIs are enhanced so that they take an optional argument
-                        specifying the feature requested by the application code. If no explicit feature
-                        is requested, then Axiom will use the <literal>default</literal> feature.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        To determine the <classname>OMMetaFactory</classname> to be used, Axiom locates
-                        the implementations declaring the requested feature and selects the one that
-                        has the highest priority for that feature.
-                    </para>
-                </listitem>
-            </orderedlist>
-            <para>
-                A remaining question is how the implementation declares the feature/priority information.
-                There are two options:
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        Add a method to <classname>OMMetaFactory</classname> that allows the Axiom API
-                        to query the feature/priority information from the implementation (i.e. the
-                        features and priorities are hardcoded in the implementation).
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Let the implementation provide this information declaratively in its metadata
-                        (either in the manifest or in a separate resource with a well defined name).
-                        Note that in a non OSGi environment, such a metadata resource must be used anyway
-                        to enable the Axiom API to locate the <classname>OMMetaFactory</classname> implementations.
-                        Therefore this would be a natural place to declare the features as well.
-                    </para>
-                </listitem>
-            </itemizedlist>
-            <para>
-                The second option has the advantage to make it easier for users to debug and tweak
-                the implementation discovery process (e.g. there may be a need to
-                customize the features and priorities declared by the different implementations to ensure
-                that the right implementation is chosen in a particular use case).
-            </para>
-            <para>
-                This leads to the following design decision:
-                the features and priorities (together with the class name of the <classname>OMMetaFactory</classname>
-                implementation) will be defined in an XML descriptor with resource name <filename>META-INF/axiom.xml</filename>.
-                The format of that descriptor must take into account that a single JAR may contain several
-                Axiom implementations (e.g. if the JAR is an uber-JAR repackaged from the standard Axiom JARs).
-            </para>
-        </section>
-        <section>
-            <title>Common implementation classes</title>
-            <para>
-                Obviously the LLOM and DOOM implementations share some amount of common code. Historically,
-                implementation classes reusable between LLOM and DOOM were placed in <literal>axiom-api</literal>.
-                This however tends to blur the distinction between the public API and implementation classes.
-                Starting with Axiom 1.2.13 such classes are placed into a separate module called
-                <literal>axiom-common-impl</literal>. However, <literal>axiom-common-impl</literal> cannot simply
-                be a dependency of <literal>axiom-impl</literal> and <literal>axiom-dom</literal>.
-                The reason is that in an OSGi environment, the <literal>axiom-common-impl</literal> bundle
-                would have to export these shared classes, which is in contradiction with <xref linkend="osgi-ref-impl-not-exported"/>.
-                Therefore the code from <literal>axiom-common-impl</literal> needs to be packaged into
-                <literal>axiom-impl</literal> and <literal>axiom-dom</literal> by the build process so that
-                the <literal>axiom-common-impl</literal> artifact is not required at runtime.
-                <xref linkend="osgi-req-no-separate-bundles"/> forbids using embedded JARs to achieve this.
-                Instead <literal>maven-shade-plugin</literal> is used to include the classes
-                from <literal>axiom-common-impl</literal> into <literal>axiom-impl</literal> and <literal>axiom-dom</literal>
-                (and to modify the POMs to remove the dependencies on <literal>axiom-common-impl</literal>).
-            </para>
-            <para>
-                This raises the question whether <literal>maven-shade-plugin</literal> should be configured to
-                simply copy the classes or to relocate them (i.e. to change their package names). There are a couple
-                of arguments in favor of relocating them:
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        According to <xref linkend="osgi-req-no-separate-bundles"/>, the Axiom artifacts should be
-                        usable both as normal JARs and as OSGi bundles. Obviously the expectation is that from the
-                        point of view of application code, they should work in the same in OSGi and non OSGi environments.
-                        Relocation is required if one wants to strictly satisfy this requirement even if different versions
-                        of <literal>axiom-impl</literal> and <literal>axiom-dom</literal> are mixed.
-                        Since the container creates separate class loaders for the <literal>axiom-impl</literal> and <literal>axiom-dom</literal> bundles,
-                        it is always possible to do that in an OSGi environment: even if the shared classes
-                        included in <literal>axiom-impl</literal> and <literal>axiom-dom</literal> are
-                        not relocated, but have the same names, this will not result in conflicts.
-                        The situation is different in a non OSGi environment where the classes in <literal>axiom-impl</literal>
-                        and <literal>axiom-dom</literal> are loaded by the same class loader. If the shared classes
-                        are not relocated, then there may be a conflict if the versions don't match.
-                    </para>
-                    <para>
-                        However, in practice it is unlikely that there are valid use case where one would use
-                        <literal>axiom-impl</literal> and <literal>axiom-dom</literal> artifacts from different Axiom versions.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Relocation allows to preserve compatibility when duplicate code from
-                        <literal>axiom-impl</literal> and <literal>axiom-dom</literal> is merged and moved
-                        to <literal>axiom-common-impl</literal>. The <classname>OMNamespaceImpl</classname>,
-                        <classname>OMNavigator</classname> and <classname>OMStAXWrapper</classname> classes
-                        from <literal>axiom-impl</literal> and the <classname>NamespaceImpl</classname>,
-                        <classname>DOMNavigator</classname> and <classname>DOMStAXWrapper</classname>
-                        classes from <literal>axiom-dom</literal> that existed in earlier versions of Axiom
-                        are examples of this. The classes in <literal>axiom-dom</literal> were almost identical
-                        to the corresponding classes in <literal>axiom-impl</literal>. These classes have been
-                        merged and moved to <literal>axiom-common-impl</literal>. Relocation then allows them
-                        to retain their original name (including the original package name) in the
-                        <literal>axiom-impl</literal> and <literal>axiom-dom</literal> artifacts.
-                    </para>
-                    <para>
-                        However, this is only a concern if one wants to preserve compatibility with existing
-                        code that directly uses these implementation specific classes (which is something that is
-                        strongly discouraged). One example where this was relevant was the SAAJ implementation
-                        in Axis2 which used to be very strongly coupled to the DOOM implementation. This however
-                        has been fixed now.
+                </note>
+                <formalpara xml:id="osgi-req-dropin">
+                    <title>Requirement 5</title>
+                    <para>
+                        It MUST be possible to use a non standard (third party) Axiom implementation as a drop-in replacement
+                        for the standard LLOM and DOOM implementation, i.e. the <literal>axiom-impl</literal>
+                        and <literal>axiom-dom</literal> bundles. It MUST be possible to replace <literal>axiom-impl</literal>
+                        (resp. <literal>axiom-dom</literal>) by any Axiom implementation that supports the full Axiom API
+                        (resp. that supports DOM in addition to the Axiom API), without the need to change any application code.
                     </para>
-                </listitem>
-            </itemizedlist>
-            <para>
-                Using relocation also has some serious disadvantages:
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        Stack traces may contain class names that don't match class names in the Axiom source
-                        code, making debugging harder.
-                    </para>
-                </listitem>
-                <listitem>
+                </formalpara>
+                <note>
                     <para>
-                        Axiom now uses JaCoCo to produce code coverage reports. However these reports are
-                        incomplete if relocation is used. This doesn't affect test cases executed in
-                        the <literal>axiom-impl</literal> and <literal>axiom-dom</literal> modules
-                        (because they are executed with the original classes), but tests in separate modules
-                        (such as integration tests). There are actually two issues:
+                        This requirement has several important implications:
                     </para>
                     <itemizedlist>
                         <listitem>
                             <para>
-                                For the relocated classes, JaCoCo is unable to find the corresponding source code.
-                                This means that the reported code coverage is inaccurate for classes in
-                                <literal>axiom-common-impl</literal>.
+                                It restricts the allowable exceptions to <xref linkend="osgi-ref-impl-not-exported"/>.
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                                It implies that there must be an API that allows application code to select an Axiom
+                                implementation based on its capabilities (e.g. DOM support) without introducing a
+                                hard dependency on a particular Axiom implementation.
                             </para>
                         </listitem>
                         <listitem>
                             <para>
-                                Relocation not only modifies the classes in <literal>axiom-common-impl</literal>, but
-                                also the classes in <literal>axiom-impl</literal> and <literal>axiom-dom</literal>
-                                that use them. JaCoCo <link xlink:href="https://github.com/jacoco/jacoco/issues/51">detects this</link>
-                                and excludes the data from the coverage analysis. This means that the
-                                reported code coverage will also be inaccurate for classes in
-                                <literal>axiom-impl</literal> and <literal>axiom-dom</literal>.
+                                In accordance with <xref linkend="osgi-req-same-api"/> and <xref linkend="osgi-req-same-impl-selection"/>
+                                this requirement not only applies to an OSGi environment, but extends to non OSGi environments as well.
                             </para>
                         </listitem>
                     </itemizedlist>
-                </listitem>
-            </itemizedlist>
-            <para>
-                In Axiom 1.2.14 relocation was used, but this has been changed in Axiom 1.2.15 because the disadvantages
-                outweigh the advantages.
-            </para>
-        </section>
-    </chapter>
-    
-    <chapter>
-        <title><classname>LifecycleManager</classname> design (Axiom 1.3)</title>
-        <para>
-            The <classname>LifecycleManager</classname> API is used by the MIME handling code in Axiom
-            to manage the temporary files that are used to buffer the content of attachment parts.
-            The <classname>LifecycleManager</classname> implementation is responsible to track the temorary
-            files that have been created and to ensure that they are deleted when they are no longer used.
-            In Axiom 1.2.x, this API has multiple issues and a redesign is required for Axiom 1.3.
-        </para>
-        <section>
-            <title>Issues with the <classname>LifecycleManager</classname> API in Axiom 1.2.x</title>
-            <orderedlist>
-                <listitem>
-                    <para>
-                        Temporary files that are not cleaned up explicitly by application code will only be removed
-                        when the JVM stops (<classname>LifecycleManagerImpl</classname> registers a shutdown hook
-                        and maintains a list of files that need to be deleted when the JVM exits). This means that
-                        temporary files may pile up, causing the file system to fill.
+                </note>
+                <formalpara>
+                    <title>Requirement 6</title>
+                    <para>
+                        The OSGi integration SHOULD remove the necessity for downstreams projects
+                        to produce their own custom OSGi bundles for Axiom. There SHOULD be one
+                        and only one set of OSGi bundles for Axiom, namely the ones released by the Axiom project.
                     </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        <classname>LifecycleManager</classname> also has a method <methodname>deleteOnTimeInterval</methodname>
-                        that deletes a file after some specified time interval. However, the implementation creates a new
-                        thread for each invocation of that method, which is generally not acceptable in high performance
-                        use cases.
-                    </para>
-                </listitem>
-                <listitem>
+                </formalpara>
+                <note>
                     <para>
-                        One of the stated design goals (see <link xlink:href="https://issues.apache.org/jira/browse/AXIOM-192">AXIOM-192</link>)
-                        of the <classname>LifecycleManager</classname> API was to wrap the files in <classname>FileAccessor</classname> objects to
-                        <quote>keep track of activity that occurs on the files</quote>. However, as pointed out in
-                        <link xlink:href="https://issues.apache.org/jira/browse/AXIOM-185">AXIOM-185</link>, since
-                        <classname>FileAccessor</classname> has a method that returns the corresponding <classname>File</classname>
-                        object, this goal has not been reached.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        As noted in <link xlink:href="https://issues.apache.org/jira/browse/AXIOM-382">AXIOM-382</link>, the fact
-                        that <classname>LifecycleManagerImpl</classname> registers a shutdown hook which is never unregistered
-                        causes a class loader leak in J2EE environments.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        In an attempt to work around the issues related to <classname>LifecycleManager</classname> (in particular
-                        the first item above), <link xlink:href="https://issues.apache.org/jira/browse/AXIOM-185">AXIOM-185</link>
-                        introduced another class called <classname>AttachmentCacheMonitor</classname> that implements a timer
-                        based mechanism to clean up temporary files. However, this change causes other issues:
+                        Currently there are at least two projects that create their own modified Axiom bundles:
                     </para>
                     <itemizedlist>
                         <listitem>
                             <para>
-                                The existence of this API has a negative impact on Axiom's architectural integrity because it
-                                has functionality that overlaps with <classname>LifecycleManager</classname>. This means that
-                                we now have two completely separate APIs that are expected to serve the same purpose, but
-                                none of them addresses the problem properly.
+                                Apache Geronimo has a custom Axiom bundle to support the Axis2 integration.
                             </para>
                         </listitem>
                         <listitem>
                             <para>
-                                <classname>AttachmentCacheMonitor</classname> automatically creates a timer, but there is no
-                                way to stop that timer. This means that this API can only be used if Axiom is integrated
-                                into the container, but not when it is deployed with an application.
+                                ServiceMix also has a custom bundles for Axiom. However, this bundle only seem to exist to
+                                support their own custom Abdera bundle, which is basically an incorrect repackaging of the
+                                original Abdera code. See
+                                <link xlink:href="https://issues.apache.org/jira/browse/SMX4-877">SMX4-877</link> for more details.
                             </para>
                         </listitem>
                     </itemizedlist>
                     <para>
-                        Fortunately, that change was only meant as a workaround to solve a particular issue in WebSphere
-                        (see APAR <link xlink:href="http://www-01.ibm.com/support/docview.wss?rs=180&amp;uid=swg1PK91497">PK91497</link>),
-                        and once the <classname>LifecycleManager</classname> API is redesigned to solve that issue,
-                        <classname>AttachmentCacheMonitor</classname> no longer has a reason to exist.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        <classname>LifecycleManager</classname> is an abstract API (interface), but refers to
-                        <classname>FileAccessor</classname> which is placed in an <literal>impl</literal> package.
-                    </para>
-                </listitem>
-                <listitem>
+                        Note that this requirement can't be satisfied directly by Axiom. It requires that
+                        the above mentioned projects (Geronimo, Axis2 and Abdera) use Axiom in a way that is
+                        compatible with its design, and in particular with <xref linkend="osgi-ref-impl-not-exported"/>.
+                        Nevertheless, Axiom must provide the necessary APIs and features to meet the needs
+                        of these projects.
+                    </para>
+                </note>
+                <formalpara xml:id="osgi-reg-no-framework">
+                    <title>Requirement 7</title>
+                    <para>
+                        The Axiom OSGi integration SHOULD NOT rely on any particular OSGi framework such
+                        as Felix SCR (Declarative Services). When deployed in an OSGi environment, Axiom should have the same
+                        runtime dependencies as in a non OSGi environment (i.e. StAX, Activation and JavaMail).
+                    </para>
+                </formalpara>
+                <note>
+                    <para>
+                        Axiom 1.2.12 relies on Felix SCR. Although there is no real issue with that, getting rid
+                        of this extra dependency is seen as a nice to have. One of the reasons for using Felix SCR
+                        was to avoid introducing OSGi specific code into Axiom. However, there is no issue with
+                        having such code, provided that <xref linkend="osgi-req-no-osgi-dep"/> is satisfied.
+                    </para>
+                </note>
+                <formalpara xml:id="osgi-req-no-osgi-dep">
+                    <title>Requirement 8</title>
+                    <para>
+                        In a non OSGi environment, Axiom MUST NOT have any OSGi related dependencies. That means
+                        that the OSGi integration must be written in such a way that no OSGi specific classes are
+                        ever loaded in a non OSGi environment.
+                    </para>
+                </formalpara>
+                <formalpara xml:id="osgi-req-best-practices">
+                    <title>Requirement 9</title>
+                    <para>
+                        The OSGi integration MUST follow established best practices. It SHOULD be inspired by
+                        what has been done to add OSGi integration to APIs that have a similar structure as Axiom.
+                    </para>
+                </formalpara>
+                <note>
+                    <para>
+                        Axiom is designed around an abstract API and allows for the existence of multiple
+                        independent implementations. A factory (<classname>OMAbstractFactory</classname>) is used to
+                        locate and instantiate the desired implementation. This is similar to APIs such as
+                        JAXP (<classname>DocumentBuilderFactory</classname>, etc.) and JAXB (<classname>JAXBContext</classname>).
+                        These APIs have been successfully "OSGi-fied" e.g. by the Apache Geronimo project.
+                        Instead of reinventing the wheel, we should leverage that work and adapt it to
+                        Axiom's specific requirements.
+                    </para>
+                    <para>
+                        It should be noted that because of the way the Axiom API is designed and taking into account
+                        <xref linkend="osgi-req-same-api"/>, it is not possible to make Axiom entirely compatible
+                        with OSGi paradigms (the same is true for JAXB). In an OSGi-only world, each Axiom
+                        implementation would simply expose itself as an OSGi service (of type <classname>OMMetaFactory</classname> e.g.)
+                        and code depending on Axiom would bind to one (or more) of these services depending on its needs.
+                        That is not possible because it would conflict with <xref linkend="osgi-req-same-api"/>.
+                    </para>
+                </note>
+                <formalpara>
+                    <title>Non-Requirement 1</title>
+                    <para>
+                        APIs such as JAXP and JAXB have been designed from the start for inclusion into the JRE.
+                        They need to support scenarios where an application bundles its own implementation
+                        (e.g. an application may package a version of Apache Xerces, which would then be
+                        instantiated by the <methodname>newInstance</methodname> method in
+                        <classname>DocumentBuilderFactory</classname>). That implies that the selected implementation
+                        depends on the thread context class loader. It is assumed that there is no such requirement
+                        for Axiom, which means that in a non OSGi environment, the Axiom implementations are always loaded from the same
+                        class loader as the <literal>axiom-api</literal> JAR.
+                    </para>
+                </formalpara>
+                <note>
+                    <para>
+                        This (non-)requirement is actually not directly relevant for the OSGi support, but it
+                        nevertheless has some importance because of <xref linkend="osgi-req-same-impl-selection"/>
+                        (which implies that the OSGi support needs to be designed in parallel with the implementation
+                        discovery strategy applicable in a non OSGi environment).
+                    </para>
+                </note>
+            </section>
+            <section>
+                <title>Analysis of the Geronimo JAXB bundles</title>
+                <para>
+                    As noted in <xref linkend="osgi-req-best-practices"/> the Apache Geronimo has successfully
+                    added OSGi support to the JAXB API which has a structure similar to the Axiom API. This section briefly describes
+                    how this works. The analysis refers to the following Geronimo artifacts: 
+                    <literal>org.apache.geronimo.specs:geronimo-jaxb_2.2_spec:1.0.1</literal> (called the "API bundle" hereafter),
+                    <literal>org.apache.geronimo.bundles:jaxb-impl:2.2.3-1_1</literal> (the "implementation bundle"),
+                    <literal>org.apache.geronimo.specs:geronimo-osgi-locator:1.0</literal> (the "locator bundle") and
+                    <literal>org.apache.geronimo.specs:geronimo-osgi-registry:1.0</literal> (the "registry bundle"):
+                </para>
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            The implementation bundle retains the <filename>META-INF/services/javax.xml.bind.JAXBContext</filename>
+                            resource from the original artifact (<literal>com.sun.xml.bind:jaxb-impl</literal>).
+                            In a non OSGi environment, that resource will be used to discover the implementation, following
+                            the standard JDK 1.3 service discovery algorithm will (as required by the JAXB specification).
+                            This is the equivalent of our <xref linkend="osgi-req-no-separate-bundles"/>.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            The manifest of the implementation bundle has an attribute <literal>SPI-Provider: true</literal> that indicates
+                            that it contains provider implementations that are discovered using the JDK 1.3 service discovery.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            The registry bundle creates a <classname>BundleTracker</classname> that looks for
+                            the <literal>SPI-Provider</literal> attribute in active bundles. For each bundle
+                            that has this attribute set to <literal>true</literal>, it will scan the content of
+                            <filename>META-INF/services</filename> and add the discovered services to a registry
+                            (Note that the registry bundle supports other ways to declare SPI providers,
+                            but this is not really relevant for the present discussion).
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            The <classname>ContextFinder</classname> class (the interface of which is defined by
+                            the JAXB specification and that is used by the <methodname>newInstance</methodname>
+                            method in <classname>JAXBContext</classname>) in the API bundle delegates the discovery
+                            of the SPI implementation to a static method of the <classname>ProviderLocator</classname>
+                            class defined by the locator bundle (which is not specific to JAXB and is used by other
+                            API bundles as well). This is true both in an OSGi environment and in a non OSGi environment.
+                        </para>
+                        <para>
+                            The build is configured (using a <literal>Private-Package</literal> instruction)
+                            such that the classes of the locator bundle are actually included into the API bundle, thus
+                            avoiding an additional dependency.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            The <classname>ProviderLocator</classname> class and related code provided by the locator bundle is designed
+                            such that in a non OSGi environment, it will simply use JDK 1.3 service discovery to locate
+                            the SPI implementation, without ever loading any OSGi specific class. On the other hand,
+                            in an OSGi environment, it will query the registry maintained by the registry bundle to locate
+                            the provider. The reference to the registry is injected into the <classname>ProviderLocator</classname>
+                            class using a bundle activator.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            Finally, it should also be noted that the API bundle is configured with <literal>singleton=true</literal>.
+                            There is indeed no meaningful way how providers could be matched with different versions of the same API
+                            bundle.
+                        </para>
+                    </listitem>
+                </itemizedlist>
+                <para>
+                    This is an example of a particularly elegant way to satisfy <xref linkend="osgi-req-no-separate-bundles"/>,
+                    <xref linkend="osgi-req-same-api"/> and <xref linkend="osgi-req-same-impl-selection"/>, especially because
+                    it relies on the same metadata (the <filename>META-INF/services/javax.xml.bind.JAXBContext</filename> resources)
+                    in OSGi and non OSGi environments.
+                </para>
+                <para>
+                    Obviously, Axiom could reuse the registry and locator bundles developed by Geronimo. This however would
+                    contradict <xref linkend="osgi-reg-no-framework"/>. In addition, for Axiom there is no requirement to
+                    strictly follow the JDK 1.3 service discovery algorithm. Therefore Axiom should reuse the pattern
+                    developed by Geronimo, but not the actual implementation.
+                </para>
+            </section>
+            <section>
+                <title>New abstract APIs</title>
+                <para>
+                    Application code rarely uses DOOM as the default Axiom implementation. Several downstream projects
+                    (e.g. the Axis2/Rampart combination) use both the default (LLOM) implementation and DOOM. They select
+                    the implementation based on the particular context. As of Axiom 1.2.12, the only way to create an object
+                    model instance with the DOOM implementation is to use the <classname>DOOMAbstractFactory</classname> API
+                    or to instantiate one of the factory classes (<classname>OMDOMMetaFactory</classname>, <classname>OMDOMFactory</classname>
+                    or one of the subclasses of <classname>DOMSOAPFactory</classname>). All these classes are part of
+                    the <literal>axiom-dom</literal> artifact. This is clearly in contradiction with <xref linkend="osgi-ref-impl-not-exported"/>
+                    and <xref linkend="osgi-req-dropin"/>.
+                </para>
+                <para>
+                    To overcome this problem the Axiom API must be enhanced to make it possible to select an Axiom
+                    implementation based on capabilities/features requested by the application code. E.g. in the case
+                    of DOOM, the application code would request a factory that implements the DOM API. It is then up
+                    to the Axiom API classes to locate an appropriate implementation, which may be DOOM or another
+                    drop-in replacement, as per <xref linkend="osgi-req-dropin"/>.
+                </para>
+                <para>
+                    If multiple Axiom implementations are available (on the class path in non OSGi environment or
+                    deployed as bundles in an OSGi environment), then the Axiom API must also be able to select an
+                    appropriate default implementation if no specific feature is requested by the application code.
+                    This can be easily implemented by defining a special feature called "default" that would be
+                    declared by any Axiom implementation that is suitable as a default implementation.
+                </para>
+                <note>
                     <para>
-                        <classname>FileAccessor</classname> uses the <classname>MessagingException</classname> class
-                        from JavaMail, although Axiom no longer relies on this API to parse or create MIME messages.
+                        DOOM is generally not considered suitable as a default implementation because it doesn't
+                        implement the complete Axiom API (e.g. it doesn't support <classname>OMSourcedElement</classname>).
+                        In addition, in earlier versions of Axiom, the factory classes for DOOM were not stateless
+                        (see <link xlink:href="https://issues.apache.org/jira/browse/AXIOM-412">AXIOM-412</link>).
                     </para>
-                </listitem>
-            </orderedlist>
+                </note>
+                <para>
+                    Finally, to make the selection algorithm deterministic, there should also be a concept
+                    of priority: if multiple Axiom implementations are found for the same feature, then the Axiom API
+                    would select the one with the highest priority.
+                </para>
+                <para>
+                    This leads to the following design:
+                </para>
+                <orderedlist>
+                    <listitem>
+                        <para>
+                            Every Axiom implementation declares a set of features that it supports. A feature is
+                            simply identified by a string. Two features are predefined by the Axiom API:
+                        </para>
+                        <itemizedlist>
+                            <listitem>
+                                <para>
+                                    <literal>default</literal>: indicates that the implementation is a complete
+                                    implementation of the Axiom API and may be used as a default implementation.
+                                </para>
+                            </listitem>
+                            <listitem>
+                                <para>
+                                    <literal>dom</literal>: indicates that the implementation supports DOM
+                                    in addition to the Axiom API.
+                                </para>
+                            </listitem>
+                        </itemizedlist>
+                        <para>
+                            For every feature it declares, the Axiom implementation specifies a priority,
+                            which is a positive integer.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            The relevant Axiom APIs are enhanced so that they take an optional argument
+                            specifying the feature requested by the application code. If no explicit feature
+                            is requested, then Axiom will use the <literal>default</literal> feature.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            To determine the <classname>OMMetaFactory</classname> to be used, Axiom locates
+                            the implementations declaring the requested feature and selects the one that
+                            has the highest priority for that feature.
+                        </para>
+                    </listitem>
+                </orderedlist>
+                <para>
+                    A remaining question is how the implementation declares the feature/priority information.
+                    There are two options:
+                </para>
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            Add a method to <classname>OMMetaFactory</classname> that allows the Axiom API
+                            to query the feature/priority information from the implementation (i.e. the
+                            features and priorities are hardcoded in the implementation).
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            Let the implementation provide this information declaratively in its metadata
+                            (either in the manifest or in a separate resource with a well defined name).
+                            Note that in a non OSGi environment, such a metadata resource must be used anyway
+                            to enable the Axiom API to locate the <classname>OMMetaFactory</classname> implementations.
+                            Therefore this would be a natural place to declare the features as well.
+                        </para>
+                    </listitem>
+                </itemizedlist>
+                <para>
+                    The second option has the advantage to make it easier for users to debug and tweak
+                    the implementation discovery process (e.g. there may be a need to
+                    customize the features and priorities declared by the different implementations to ensure
+                    that the right implementation is chosen in a particular use case).
+                </para>
+                <para>
+                    This leads to the following design decision:
+                    the features and priorities (together with the class name of the <classname>OMMetaFactory</classname>
+                    implementation) will be defined in an XML descriptor with resource name <filename>META-INF/axiom.xml</filename>.
+                    The format of that descriptor must take into account that a single JAR may contain several
+                    Axiom implementations (e.g. if the JAR is an uber-JAR repackaged from the standard Axiom JARs).
+                </para>
+            </section>
+            <section>
+                <title>Common implementation classes</title>
+                <para>
+                    Obviously the LLOM and DOOM implementations share some amount of common code. Historically,
+                    implementation classes reusable between LLOM and DOOM were placed in <literal>axiom-api</literal>.
+                    This however tends to blur the distinction between the public API and implementation classes.
+                    Starting with Axiom 1.2.13 such classes are placed into a separate module called
+                    <literal>axiom-common-impl</literal>. However, <literal>axiom-common-impl</literal> cannot simply
+                    be a dependency of <literal>axiom-impl</literal> and <literal>axiom-dom</literal>.
+                    The reason is that in an OSGi environment, the <literal>axiom-common-impl</literal> bundle
+                    would have to export these shared classes, which is in contradiction with <xref linkend="osgi-ref-impl-not-exported"/>.
+                    Therefore the code from <literal>axiom-common-impl</literal> needs to be packaged into
+                    <literal>axiom-impl</literal> and <literal>axiom-dom</literal> by the build process so that
+                    the <literal>axiom-common-impl</literal> artifact is not required at runtime.
+                    <xref linkend="osgi-req-no-separate-bundles"/> forbids using embedded JARs to achieve this.
+                    Instead <literal>maven-shade-plugin</literal> is used to include the classes
+                    from <literal>axiom-common-impl</literal> into <literal>axiom-impl</literal> and <literal>axiom-dom</literal>
+                    (and to modify the POMs to remove the dependencies on <literal>axiom-common-impl</literal>).
+                </para>
+                <para>
+                    This raises the question whether <literal>maven-shade-plugin</literal> should be configured to
+                    simply copy the classes or to relocate them (i.e. to change their package names). There are a couple
+                    of arguments in favor of relocating them:
+                </para>
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            According to <xref linkend="osgi-req-no-separate-bundles"/>, the Axiom artifacts should be
+                            usable both as normal JARs and as OSGi bundles. Obviously the expectation is that from the
+                            point of view of application code, they should work in the same in OSGi and non OSGi environments.
+                            Relocation is required if one wants to strictly satisfy this requirement even if different versions
+                            of <literal>axiom-impl</literal> and <literal>axiom-dom</literal> are mixed.
+                            Since the container creates separate class loaders for the <literal>axiom-impl</literal> and <literal>axiom-dom</literal> bundles,
+                            it is always possible to do that in an OSGi environment: even if the shared classes
+                            included in <literal>axiom-impl</literal> and <literal>axiom-dom</literal> are
+                            not relocated, but have the same names, this will not result in conflicts.
+                            The situation is different in a non OSGi environment where the classes in <literal>axiom-impl</literal>
+                            and <literal>axiom-dom</literal> are loaded by the same class loader. If the shared classes
+                            are not relocated, then there may be a conflict if the versions don't match.
+                        </para>
+                        <para>
+                            However, in practice it is unlikely that there are valid use case where one would use
+                            <literal>axiom-impl</literal> and <literal>axiom-dom</literal> artifacts from different Axiom versions.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            Relocation allows to preserve compatibility when duplicate code from
+                            <literal>axiom-impl</literal> and <literal>axiom-dom</literal> is merged and moved
+                            to <literal>axiom-common-impl</literal>. The <classname>OMNamespaceImpl</classname>,
+                            <classname>OMNavigator</classname> and <classname>OMStAXWrapper</classname> classes
+                            from <literal>axiom-impl</literal> and the <classname>NamespaceImpl</classname>,
+                            <classname>DOMNavigator</classname> and <classname>DOMStAXWrapper</classname>
+                            classes from <literal>axiom-dom</literal> that existed in earlier versions of Axiom
+                            are examples of this. The classes in <literal>axiom-dom</literal> were almost identical
+                            to the corresponding classes in <literal>axiom-impl</literal>. These classes have been
+                            merged and moved to <literal>axiom-common-impl</literal>. Relocation then allows them
+                            to retain their original name (including the original package name) in the
+                            <literal>axiom-impl</literal> and <literal>axiom-dom</literal> artifacts.
+                        </para>
+                        <para>
+                            However, this is only a concern if one wants to preserve compatibility with existing
+                            code that directly uses these implementation specific classes (which is something that is
+                            strongly discouraged). One example where this was relevant was the SAAJ implementation
+                            in Axis2 which used to be very strongly coupled to the DOOM implementation. This however
+                            has been fixed now.
+                        </para>
+                    </listitem>
+                </itemizedlist>
+                <para>
+                    Using relocation also has some serious disadvantages:
+                </para>
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            Stack traces may contain class names that don't match class names in the Axiom source
+                            code, making debugging harder.
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+                            Axiom now uses JaCoCo to produce code coverage reports. However these reports are
+                            incomplete if relocation is used. This doesn't affect test cases executed in
+                            the <literal>axiom-impl</literal> and <literal>axiom-dom</literal> modules
+                            (because they are executed with the original classes), but tests in separate modules
+                            (such as integration tests). There are actually two issues:
+                        </para>
+                        <itemizedlist>
+                            <listitem>
+                                <para>
+                                    For the relocated classes, JaCoCo is unable to find the corresponding source code.
+                                    This means that the reported code coverage is inaccurate for classes in
+                                    <literal>axiom-common-impl</literal>.
+                                </para>
+                            </listitem>
+                            <listitem>
+                                <para>
+                                    Relocation not only modifies the classes in <literal>axiom-common-impl</literal>, but
+                                    also the classes in <literal>axiom-impl</literal> and <literal>axiom-dom</literal>
+                                    that use them. JaCoCo <link xlink:href="https://github.com/jacoco/jacoco/issues/51">detects this</link>
+                                    and excludes the data from the coverage analysis. This means that the
+                                    reported code coverage will also be inaccurate for classes in
+                                    <literal>axiom-impl</literal> and <literal>axiom-dom</literal>.
+                                </para>
+                            </listitem>
+                        </itemizedlist>
+                    </listitem>
+                </itemizedlist>
+                <para>
+                    In Axiom 1.2.14 relocation was used, but this has been changed in Axiom 1.2.15 because the disadvantages
+                    outweigh the advantages.
+                </para>
+            </section>
         </section>
+    
         <section>
-            <title>Cleanup strategy for temporary files</title>
-            <para>
-                As pointed out in the previous section, one of the primary problems with the
-                <classname>LifecycleManager</classname> API in Axiom 1.2.x is that temporary files that are
-                not cleaned up explicitly by application code (e.g. using the <methodname>purgeDataSource</methodname> method
-                defined by <classname>DataHandlerExt</classname>) are only removed when the JVM exits.
-                A timer based strategy that deletes temporary file after a given time interval (as proposed
-                by <classname>AttachmentCacheMonitor</classname>) is not reliable
-                because in some use cases, application code may keep a reference to the attachment part for
-                a long time before accessing it again.
-            </para>
-            <para>
-                The only reliable strategy is to take advantage of finalization, i.e. to rely on the garbage
-                collector to trigger the deletion of temporary files that are no longer used. For this to work
-                the design of the API (and its default implementation) must satisfy the following two conditions:
-            </para>
-            <orderedlist>
-                <listitem>
-                    <para>
-                        All access to the underlying file must be strictly encapsulated, so that the file
-                        is only accessible as long as there is a strong reference to the object that
-                        encapsulates the file access. This is necessary to ensure that the file can
-                        be safely deleted once there is no longer a strong reference and the
-                        object is garbage collected.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Java guarantees that the finalizer is invoked before the instance is garbage
-                        collected. However, instances are not necessarily garbage collected before the
-                        JVM exits, and in that case the finalizer is never invoked. Therefore, the
-                        implementation must delete all existing temporary files when the JVM exits.
-                        The API design should also take into account that some implementations of
-                        the <classname>LifecycleManager</classname> API may want to trigger this
-                        cleanup before the JVM exits, e.g. when the J2EE application in which
-                        Axiom is deployed is stopped.
-                    </para>
-                </listitem>
-            </orderedlist>
-            <para>
-                The first condition can be satisfied by redesigning the <classname>FileAccessor</classname>
-                such that it never leaks the name of the file it represents (neither as a <classname>String</classname>
-                nor a <classname>File</classname> object). This in turn means that the
-                <classname>CachedFileDataSource</classname> class must be removed from the Axiom API.
-                In addition, the <methodname>getInputStream</methodname> method defined by
-                <classname>FileAccessor</classname> must no longer return a simple <classname>FileInputStream</classname>
-                instance, but must use a wrapper that keeps a strong reference to the <classname>FileAccessor</classname>,
-                so that the <classname>FileAccessor</classname> can't be garbage collected while the
-                input stream is still in use.
-            </para>
-            <para>
-                To satisfy the second condition, one may want to use <methodname>File#deleteOnExit</methodname>.
-                However, this method causes a native memory leak, especially when used with temporary files,
-                which are expected to have unique names (see
-                <link xlink:href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4513817">bug 4513817</link>).
-                Therefore this can only be implemented using a shutdown hook. However, a shutdown hook will
-                cause a class loader leak if it is used improperly, e.g. if it is registered by an application deployed
-                into a J2EE container and not unregistered when that application is stopped. For this
-                particular case, it is possible to create a special <classname>LifecycleManager</classname>
-                implementation, but for this to work, the lifecycle of this type of <classname>LifecycleManager</classname>
-                must be bound to the lifecycle of the application, e.g. using a
-                <classname>ServletContextListener</classname>. This is not always possible and this approach
-                is therefore not suitable for the default <classname>LifecycleManager</classname> implementation.
-            </para>
+            <title><classname>LifecycleManager</classname> design (Axiom 1.3)</title>

[... 191 lines stripped ...]


Mime
View raw message