<?xml version="1.0" encoding="UTF-8"?>
<section version="5.0" xml:id="classloader" xml:lang="en"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:svg="http://www.w3.org/2000/svg"
         xmlns:mml="http://www.w3.org/1998/Math/MathML"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:db="http://docbook.org/ns/docbook">
  <info>
    <title>JOnAS classloading architecture</title>
  </info>

  <para>This section introduces the classloading architecture of JOnAS.</para>

  <section xml:id="classloader.nderstanding">
    <info>
      <title>Understanding class loaders hierarchies</title>
    </info>

    <para>Obviously, a <classname>ClassLoader</classname> is used to load
    classes (and resources) that will then be usable from the application.
    Most of the ClassLoaders are <classname>URLClassLoaders</classname>, that
    means that they are based on a set of URLs. Theses URLs will be the place
    where the ClassLoader, when asked for a resource (using its fully
    qualified name, ie including full package name), will try to find the
    resource.</para>

    <para>An <classname>URLClassLoader</classname> always have a parent
    ClassLoader. When loading a class, the first thing a ClassLoader do is to
    ask its parent to load the class (this is recursive). If the parent return
    the Class, it's returned to the caller. Otherwise, the URLs will be search
    for the given class. this is the default Java delegation model (parent
    first).</para>

    <para>Let's roll with an example: you have a ClassLoader (let's call it A)
    that can load the class <classname>Test</classname>, A is the parent of B,
    but B do not contains the <classname>Test</classname> class, and B is the
    parent of C, with C that contains also the <classname>Test</classname>
    class. Clearly, there is a ClassLoader hierarchy here (C-&gt;B-&gt;A, with
    "-&gt;" meaning "is child of"). If you ask C to load
    <classname>Test</classname>, the following steps will be performed:</para>

    <orderedlist>
      <listitem>
        <para>C have B as parent, so asks B to try to load
        <classname>Test</classname></para>
      </listitem>

      <listitem>
        <para>B have A as parent, so asks A to try to load
        <classname>Test</classname></para>
      </listitem>

      <listitem>
        <para>A is the top level ClassLoader, no parent, it will try to load
        test by itself</para>
      </listitem>

      <listitem>
        <para>As A contains the <classname>Test</classname> class, it can be
        loaded and returned</para>
      </listitem>

      <listitem>
        <para>B see that A (its parent) have loaded the class, so it return it
        as is</para>
      </listitem>

      <listitem>
        <para>C see that B (its parent) have loaded the class, so it return it
        as is</para>
      </listitem>
    </orderedlist>

    <para><note>
        <para>Using the Java delegation model, the loaded class is always
        coming from the parent ClassLoader that is closer to the System class
        loader (the well known <envar>CLASSPATH</envar>), even if the class
        exists in a lower level ClassLoader (aka child ClassLoaders).</para>
      </note>Java EE makes an heavy use of ClassLoaders: the application
    server in itself may be composed of multiple ClassLoaders and the Java EE
    applications (EAR, Rar, War, EjbJar) themselves are using
    ClassLoaders.</para>

    <para>An application is deployed by its own class loader. This means, for
    example, that if a Web Application and an EjbJar are deployed separately,
    the classes contained in the two archives are loaded with two separate
    classloaders with no hierarchy between them. Thus, the EJBs from within
    the JAR will not be visible to the Web components in the WAR. This is not
    acceptable in cases where the Web components of an application need to
    reference and use some of the EJBs (this concerns local references in the
    same <acronym>JVM</acronym>).</para>

    <para><note>
        <para>Class loaders are used to ensure <emphasis>class space
        isolation</emphasis>.</para>
      </note></para>

    <para>For this reason, prior to EAR files, when a Web application had to
    be deployed using EJBs, the EjbJar had to be located in the <filename
    class="directory">WEB-INF/lib</filename> directory of the Web
    application.</para>

    <para>Currently, with the Java EE integration and the use of the EAR
    packaging, that kind of class visibility problems no longer exist and the
    EjbJar is no longer required in the <filename
    class="directory">WEB-INF/lib</filename> directory.</para>

    <para>The following sections describe the JOnAS class loaders and explain
    the mechanism used to locate the referenced classes.</para>
  </section>

  <section xml:id="classloader.tools">
    <info>
      <title>Application Server's class loaders</title>
    </info>

    <para>JOnAS is basically an assembly of modules providing the features
    that makes JOnAS an application server. Each of the modules have an
    associated class loader. All theses loaders have visibility constraints,
    meaning that some of the internal classes or libraries used by JOnAS are
    hidden from the application class space. In clear, even if JOnAS may use a
    library also used by a deployed application, there will be no
    conflicts.<note>
        <para>Having visibility constraints on class loaders reduce the risks
        of conflicting libraries.</para>
      </note></para>

    <para>The loaders of JOnAS are not in a tree hierarchy. They all share the
    same parent class loader (the System classloader), so it's a flat
    hierarchy. Nevertheless, there are links (aka wires) between theses class
    loaders. A module can export some of its packages (and thus, all the
    classes from that package) to the system. Theses exported packages can
    then be imported by other modules. That creates a wire. As a module can be
    wired to multiple others modules, the class loaders of the application
    server forms an oriented graph of loaders.<note>
        <para>The class loading rules are described in much more details in
        the <trademark>OSGi</trademark> specification.</para>
      </note><note>
        <para>Only exported packages are available to the applications</para>
      </note></para>

    <para></para>

    <mediaobject>
      <imageobject>
        <imagedata fileref="../../../resources/images/jonas-classloaders.png"></imagedata>
      </imageobject>
    </mediaobject>

    <section xml:id="classloader.extending">
      <title>Extending JOnAS class loaders</title>

      <para>As JOnAS is build on a modular system
      (<trademark>OSGi</trademark>), it's very natural to "extends" the
      application server's class space.</para>

      <para>There are 2 way that can be used to augment the class
      space:</para>

      <para><orderedlist>
          <listitem>
            <para>Place an <trademark>OSGi</trademark> bundle containing your
            classes in the <filename
            class="directory">${jonas.base}/deploy/</filename>
            directory</para>

            <para>It will be deployed as any normal bundle, and if it's
            resolved (ie all imported packages are found), all the packages
            exported by this bundle will be made available to the server (and
            applications).<note>
                <para>This is the preferred way to augment the class
                space.</para>
              </note></para>
          </listitem>

          <listitem>
            <para>Place a classic jar file in the <filename
            class="directory">${jonas.base}/lib/ext/</filename> (or <filename
            class="directory">${jonas.root}/lib/ext/</filename>). During JOnAS
            startup, theses jar files will automatically be transformed into
            bundle (using default creation rules) and installed like all other
            bundles.</para>

            <para><note>
                <para>The default rule is: every required packages that is not
                in the jar file will be imported, and every packages of the
                jar will be exported.</para>
              </note><warning>
                <para>This option, even if it is seducing, should be used with
                caution: it can break application server modularity (if they
                export a package required by some of the JOnAS modules, maybe
                that can cause weird classes exceptions), and, because of the
                default transformation rule (all is exported), it's highly
                possible that a jar file will export some internal packages
                that should not have been exposed to the world.</para>

                <para>So the right method to augment the class space is to
                provide a well constructed bundle (with imports and exports
                constrained with versions).</para>
              </warning></para>
          </listitem>
        </orderedlist></para>
    </section>

    <section>
      <title>Using JDBC driver jars</title>

      <para>In order to connect the applications to an external database (not
      <database>HSQL</database> which is embedded in JOnAS), the user must
      provide the jar file that contains the <acronym>JDBC</acronym> Driver's
      classes.</para>

      <para>Providing theses jar files are just like extending JOnAS class
      loaders:</para>

      <para><itemizedlist>
          <listitem>
            <para>The driver's jar file is already an
            <trademark>OSGi</trademark> bundle, so it can be placed in
            <filename class="directory">${jonas.base}/deploy</filename> and it
            will be deployed automatically</para>
          </listitem>

          <listitem>
            <para>The jar file is not a bundle, it could be placed in
            <filename class="directory">${jonas.base}/lib/ext</filename> and
            will be (<emphasis>at startup only</emphasis>) transformed into a
            bundle (see previous section for detailed information), or the
            user takes the responsability of transformation (more fine control
            on the bundle).</para>
          </listitem>
        </itemizedlist></para>
    </section>
  </section>

  <section xml:id="classloader.jonas">
    <info>
      <title>Java EE module's class loaders</title>
    </info>

    <para>Java EE modules are following the classic, hierarchical, parent
    oriented graph of class loaders.</para>

    <para>The class loader hierarchy for Java EE modules that allows the
    deployment of EAR applications without placing the EJB JAR in the
    <filename class="directory">WEB-INF/lib</filename> directory consists of
    the following:<caution>
        <para>Work in progress</para>
      </caution></para>

    <section>
      <title xml:id="standalone.resource-adapter.loader">Standalone resource
      adapters loader</title>

      <para>This class loader, child of the <trademark>OSGi</trademark> class
      loader, contains only the libraries provided by the system level
      resource adapters (i.e. resource adapters not part of an EAR
      application).</para>

      <para>This class loader is the parent of all the deployed Java EE
      modules:</para>

      <itemizedlist>
        <listitem>
          <para>Standalone Web Applications (<filename
          class="extension">.war</filename> files)</para>
        </listitem>

        <listitem>
          <para>Standalone EjbJars (<filename
          class="extension">.jar</filename> files)</para>
        </listitem>

        <listitem>
          <para>Java EE Applications (<filename
          class="extension">.ear</filename> files)</para>
        </listitem>
      </itemizedlist>

      <para>This means that all the classes available from this loader are
      also made available for the child loaders.</para>
    </section>

    <section>
      <title>Standalone EjbJar loader</title>

      <para>A standalone EjbJar classloader contains the classes packaged
      inside of the ejbjar. The parent of this classloader is the <xref
      linkend="standalone.resource-adapter.loader" />. It can therefore see
      all the classes available from the system level resource adapters and
      its ancestors.</para>

      <para>The classloading policy of this loader is to ask its parent first,
      and then (if the class was not found) try to search in itself.
      <emphasis>There is no way to invert the classloading policy of an EjbJar
      classloader.</emphasis></para>
    </section>

    <section>
      <title>Standalone WebApp loader</title>

      <para>The classloader for standalone web applications modules contains
      the classes and libraries packaged inside of the war.</para>

      <para>It contains the <filename
      class="directory">WEB-INF/classes/</filename> directory (that usually
      matches the classes of the application) and all the jar files located
      under the <filename class="directory">WEB-INF/lib/</filename> directory.
      Notice that only jars directly under the <filename
      class="directory">lib/</filename> directory are available, jars in
      <filename class="directory">WEB-INF/lib/subdirectory/</filename> will
      not be accessible from the classloader.</para>

      <para>The parent of the standalone webapp classloader is the <xref
      linkend="standalone.resource-adapter.loader" />, meaning that all
      standalone web applications will be able to use system level resource
      adapters classes/libraries and the classes available from its
      ancestors.</para>

      <para>A webapp loader also have a direct link with the system
      classloader (classes of the JVM + what's available from the
      <envar>CLASSPATH</envar> environment variable). <emphasis>All class
      loading actions are first directed to the system classloader</emphasis>
      to avoid JVM class overloading from the web application (in short,
      guards the developer from overloading primordial classes).</para>

      <para>Then, if the system classlaoder did not find the required class,
      the loader will ask either the parent, or itself. Asking the parent or
      itself is configured by the delegation model choosed by the
      developer.</para>

      <note>
        <para>By default, java2 delegation model is turned on.</para>
      </note>

      <section>
        <title xml:id="java2.delegation.model">Java 2 delegation model</title>

        <para>The default classloading policy of a web application in an
        application server (in opposition of a webapp hosted in a standalone
        servlet container) is to ask the parent loader first, and then look
        inside itself (if the parent did not find the required class), this is
        the default java2 delegation model.</para>

        <para>Nevertheless, a web application developer can configure the web
        classloader to use first itself, then ask the parent loader. That
        means that the web application classes will have more priority than
        classes from the parent loader, in other words it can be used to
        overload some classes provided by the application server.</para>

        <para>The delegation model can be configured using the
        <filename>WEB-INF/jonas-web.xml</filename> specific deployment
        descriptor, as shown below.</para>

        <programlisting language="xml">&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;jonas-web-app xmlns="http://www.objectweb.org/jonas/ns"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.objectweb.org/jonas/ns
                                   http://jonas.ow2.org/ns/jonas-web-app_4_0.xsd"&gt;
    &lt;!--
    true  : the context uses a classloader using the Java 2 delegation model (default)
    false : the class loader looks inside the web application first, before asking parent class loader
    --&gt;
    &lt;java2-delegation-model&gt;false&lt;/java2-delegation-model&gt;
&lt;/jonas-web-app&gt;</programlisting>
      </section>
    </section>

    <section>
      <info>
        <title>EAR class loader</title>
      </info>

      <para>The EAR class loader is the common parent (directly or indirectly)
      of all the class loaders of the inner modules (ejbjars, rar, webapps).
      There is only one EAR class loader per EAR application. This class
      loader is the child class loader, thus making JOnAS classes visible to
      it. The parent of all the EAR class loaders is a JOnAS special class
      loader that is able to seek for classes/resources exported by all the
      other module's class loaders of JOnAS.</para>

      <section>
        <title>Class-Path: entries and lib/folder</title>

        <para>In Java EE 5, if libraries are required to any module packaged
        into the EAR file, these libraries could be added in the lib/ folder
        of the EAR.</para>

        <para>By using this mechanism, the use of "Class-Path" entries in the
        MANIFEST file of each application (WAR / EJB-JAR) is no longer
        required.</para>
      </section>
    </section>

    <section>
      <info>
        <title>EJB class loader</title>
      </info>

      <para>The EJB class loader is responsible for loading all the EJB JARs
      of the EAR application, thus all the EJBs of the same EAR application
      are loaded with the same EJB classloader. This class loader is the child
      of the EAR class loader.</para>
    </section>

    <section>
      <info>
        <title>WEB class loader</title>
      </info>

      <para>The WEB class loader is responsible for loading the Web
      components. There is one WEB class loader per WAR file, and this class
      loader is the child of the EJB class loader. Using this class loader
      hierarchy (the EJB class loader is the parent of the WEB class loader)
      eliminates the problem of visibility between classes when a WEB
      component tries to reference EJBs; the classes loaded with the EJB class
      loader are definitely visible to the classes loaded by its child class
      loader (WEB class loader).</para>

      <para>The compliance of the class loader of the web application to the
      java 2 delegation model can be changed by using the
      <filename>WEB-INF/jonas-web.xml</filename> file. This is described in
      the section <link
      xlink:href="j2eeprogrammerguide.html#j2ee.pg.classloader"> Defining the
      Web Deployment Descriptor</link>.</para>

      <para>If the <markup>java2-delegation-model</markup> element is set to
      false, the class loader of the web application looks for the class in
      its own repository before asking its parent class loader. See <xref
      linkend="java2.delegation.model" /> for more detailed
      explanations.</para>
    </section>
  </section>

  <section>
    <title>Filtering class loaders</title>

    <section>
      <title>The problem</title>

      <para>By default, all classes exported by the application server can be
      accessed within an application. Sometimes this may cause problems if
      there are different versions of the library (in the AS and in the
      application).</para>

      <para>For example, JOnAS is using Apache Commons Digester. If an
      application wants to use an older version of this library, there is a
      problem as the default loading mechanism of classes is searching first
      in the parent classloaders. Then the library provided by JOnAS and not
      by the application will be used.</para>

      <para>For web applications, this mechanism could be changed by using
      <literal>java2-delegation-model</literal> but this may raise problems
      for EAR case, etc.</para>
    </section>

    <section>
      <title>The solution</title>

      <para>JOnAS is providing the concept of filtering classloader. A
      filtered classloader will hide to applications some packages/resources
      exported by the Application Server.</para>

      <para>A <classname>FilteringClassLoader</classname> is simply placed
      between a child <classname>ClassLoader</classname> and its parent and
      filter any requests coming from the child to the parent.</para>

      <figure>
        <title>Filtering ClassLoader Principle</title>

        <mediaobject>
          <imageobject>
            <imagedata fileref="../../../resources/images/filtering-loader.png"></imagedata>
          </imageobject>
        </mediaobject>
      </figure>

      <para>This approach allows a fine grain control over what is visible or
      not from a given ClassLoader.</para>

      <para>Any loading request for a resource will trigger a matching against
      a list of excluded patterns. If any of the pattern match, the resource
      will not be loaded and the flow will return to the caller.</para>

      <para>Loading of a filtered resource (image, static content, ...) will
      result in <literal>null</literal> (the usual return for a resource not
      found) being returned. If the loading request a filtered class, a
      <classname>ClassNotFoundException</classname> will be thrown back to the
      caller (the usual return when a class is not found).</para>
    </section>

    <section>
      <title>Filtering system resources</title>

      <para>Some filters are configured by default in JOnAS. They will be
      applied to the "standalone rars" ClassLoader, effectively filtering
      resource/class request from all the deployed applications (among just
      the standalone resource adapters). This is a <emphasis>system
      wide</emphasis> configuration.</para>

      <para>These default filters are located in the
      <filename>JONAS_BASE/conf/classloader-default-filtering.xml</filename>
      file.</para>

      <programlisting>&lt;class-loader-filtering xmlns="http://org.ow2.jonas.lib.loader.mapping"&gt;

   &lt;!-- List of filters used to exclude packages/resources that are used internally by
        the Application Server but that will not be available to applications.
        An empty list will not hide any packages to the applications
        This list is used both to hide resources and classes to applications. --&gt;
    &lt;default-filters&gt;
        &lt;filter-name&gt;org.apache.commons.digester.*&lt;/filter-name&gt;
    &lt;/default-filters&gt;
&lt;/class-loader-filtering&gt;</programlisting>

      <para>By modifying the set of filters, some packages will be hidden to
      the applications. Note that resources name can be specified. For
      example, when putting a resource in <filename
      class="directory">JONAS_BASE/conf</filename> folder, this resource can
      be obtained by using <methodname>ClassLoader.getResource()</methodname>
      method. By adding a filter on this resource, the resource won't be
      available to applications (This includes EAR, WAR and EJB-JAR
      modules).</para>
    </section>

    <section>
      <title>Filtering deployed modules</title>

      <para>In addition of the system wide filters configuration, JOnAS allows
      Java EE modules to provide themselves the filters they requires.</para>

      <para>It can be done by providing a
      <filename>classloader-filtering.xml</filename> file in the info
      directory of the deployed module (<filename
      class="directory">META-INF/</filename> or <filename
      class="directory">WEB-INF/</filename>).</para>

      <section>
        <title>Supported module types</title>

        <para>Not all modules supports the classloader filtering
        feature.</para>

        <para>Supported modules includes:</para>

        <itemizedlist>
          <listitem>
            <para>EAR applications (<filename
            class="extension">.ear</filename>)</para>
          </listitem>

          <listitem>
            <para>Web Applications (<filename
            class="extension">.war</filename>), inside or outside an
            application</para>
          </listitem>

          <listitem>
            <para>EjbJars (<filename class="extension">.jar</filename>), only
            the ones outside of an application</para>
          </listitem>
        </itemizedlist>

        <tip>
          <para>Web Applications filtering rules also apply when they are in
          an application (EAR).</para>
        </tip>
      </section>

      <section>
        <title>Declaring the filters</title>

        <para>A Java EE module declares the filters it requires with an XML
        file named <filename>META-INF/classloader-filtering.xml</filename>
        (<filename>WEB-INF/classloader-filtering.xml</filename> for a web
        application). its format is very similar to the system wide
        configuration file (<literal>&lt;default-filters&gt;</literal> simply
        become <literal>&lt;filters&gt;</literal>):</para>

        <para><programlisting>&lt;class-loader-filtering xmlns="http://org.ow2.jonas.lib.loader.mapping"&gt;

    &lt;filters&gt;
        &lt;!-- Excludes all CXF resources as another version is embed in the web application --&gt;
        &lt;filter-name&gt;org.apache.cxf.*&lt;/filter-name&gt;
        &lt;!-- plus some other dependencies of CXF ... --&gt;
        &lt;filter-name&gt;org.springframework.*&lt;/filter-name&gt;
        &lt;filter-name&gt;net.sf.cglib.*&lt;/filter-name&gt;
        &lt;filter-name&gt;org.objectweb.asm.*&lt;/filter-name&gt;
    &lt;/filters&gt;

&lt;/class-loader-filtering&gt;</programlisting></para>
      </section>

      <section>
        <title>What about Rars and Ejbjars ?</title>

        <para>Standalone Resource Adapters are all sharing the same
        <classname>ClassLoader</classname>. This loader is the parent of all
        the applications and is the one that is filtered by the system wide
        configuration file. That means that standalone Rars cannot have their
        own filtering configuration. They have to use (or modify) the
        <filename>classloader-default-filtering.xml</filename> file to fit
        their needs.</para>

        <para>EjbJars in Ear do not have support for the filtering. First, an
        EjbJar should not contains any library, so what could you filter ?
        Then EjbJars are all placed (along with Ear libraries) inside a unique
        <filename>ClassLoader</filename>, direct child of the application
        loader (containing Rars embed in the Ear), so they can indirectly
        benefit from the filters declared inside the application.</para>
      </section>
    </section>
  </section>
</section>
