Red Hat Training

A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform

Chapter 3. Class Loading and Modules

3.1. Introduction

3.1.1. Overview of Class Loading and Modules

JBoss EAP uses a modular class loading system for controlling the class paths of deployed applications. This system provides more flexibility and control than the traditional system of hierarchical class loaders. Developers have fine-grained control of the classes available to their applications, and can configure a deployment to ignore classes provided by the application server in favor of their own.

The modular class loader separates all Java classes into logical groups called modules. Each module can define dependencies on other modules in order to have the classes from that module added to its own class path. Because each deployed JAR and WAR file is treated as a module, developers can control the contents of their application’s class path by adding module configuration to their application.

3.1.2. Modules

A module is a logical grouping of classes used for class loading and dependency management. JBoss EAP identifies two different types of modules: static and dynamic. The main difference between the two is how they are packaged.

Static Modules

Static modules are defined in the EAP_HOME/modules/ directory of the application server. Each module exists as a subdirectory, for example EAP_HOME/modules/com/mysql/. Each module directory then contains a slot subdirectory, which defaults to main and contains the module.xml configuration file and any required JAR files. All the application server-provided APIs are provided as static modules, including the Java EE APIs as well as other APIs.

Example MySQL JDBC Driver module.xml File

<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
  <resources>
    <resource-root path="mysql-connector-java-5.1.36-bin.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
    <module name="javax.transaction.api"/>
  </dependencies>
</module>

The module name (com.mysql) must match the directory structure for the module, excluding the slot name (main).

Creating custom static modules can be useful if many applications are deployed on the same server that use the same third-party libraries. Instead of bundling those libraries with each application, a module containing these libraries can be created and installed by an administrator. The applications can then declare an explicit dependency on the custom static modules.

The modules provided in JBoss EAP distributions are located in the system directory within the EAP_HOME/modules directory. This keeps them separate from any modules provided by third parties. Any Red Hat provided products that layer on top of JBoss EAP also install their modules within the system directory.

Users must ensure that custom modules are installed into the EAP_HOME/modules directory, using one directory per module. This ensures that custom versions of modules that already exist in the system directory are loaded instead of the shipped versions. In this way, user-provided modules will take precedence over system modules.

If you use the JBOSS_MODULEPATH environment variable to change the locations in which JBoss EAP searches for modules, then the product will look for a system subdirectory structure within one of the locations specified. A system structure must exist somewhere in the locations specified with JBOSS_MODULEPATH.

Dynamic Modules

Dynamic modules are created and loaded by the application server for each JAR or WAR deployment (or subdeployment in an EAR). The name of a dynamic module is derived from the name of the deployed archive. Because deployments are loaded as modules, they can configure dependencies and be used as dependencies by other deployments.

Modules are only loaded when required. This usually only occurs when an application is deployed that has explicit or implicit dependencies.

3.1.3. Module Dependencies

A module dependency is a declaration that one module requires the classes of one or more other modules in order to function. When JBoss EAP loads a module, the modular class loader parses the dependencies of that module and adds the classes from each dependency to its class path. If a specified dependency cannot be found, the module will fail to load.

Note

See the Modules section for complete details about modules and the modular class loading system.

Deployed applications (a JAR or WAR, for example) are loaded as dynamic modules and make use of dependencies to access the APIs provided by JBoss EAP.

There are two types of dependencies: explicit and implicit.

Explicit Dependencies
Explicit dependencies are declared by the developer in a configuration file. A static module can declare dependencies in its module.xml file. A dynamic module can declare dependencies in the deployment’s MANIFEST.MF or jboss-deployment-structure.xml deployment descriptor.
Implicit Dependencies

Implicit dependencies are added automatically by JBoss EAP when certain conditions or meta-data are found in a deployment. The Java EE 7 APIs supplied with JBoss EAP are examples of modules that are added by detection of implicit dependencies in deployments.

Deployments can also be configured to exclude specific implicit dependencies by using the jboss-deployment-structure.xml deployment descriptor file. This can be useful when an application bundles a specific version of a library that JBoss EAP will attempt to add as an implicit dependency.

See the Add an Explicit Module Dependency to a Deployment section for details on using the jboss-deployment-structure.xml deployment descriptor.

Optional Dependencies

Explicit dependencies can be specified as optional. Failure to load an optional dependency will not cause a module to fail to load. However, if the dependency becomes available later it will not be added to the module’s class path. Dependencies must be available when the module is loaded.

Export a Dependency

A module’s class path contains only its own classes and that of its immediate dependencies. A module is not able to access the classes of the dependencies of one of its dependencies. However, a module can specify that an explicit dependency is exported. An exported dependency is provided to any module that depends on the module that exports it.

For example, Module A depends on Module B, and Module B depends on Module C. Module A can access the classes of Module B, and Module B can access the classes of Module C. Module A cannot access the classes of Module C unless:

  • Module A declares an explicit dependency on Module C, or
  • Module B exports its dependency on Module C.
Global Modules

A global module is a module that JBoss EAP provides as a dependency to every application. Any module can be made global by adding it to JBoss EAP’s list of global modules. It does not require changes to the module.

See the Define Global Modules section of the JBoss EAP Configuration Guide for details.

3.1.3.1. Display Module Dependencies Using the Management CLI

You can use the following management operation to view information about a particular module and its dependencies:

/core-service=module-loading:module-info(name=$MODULE_NAME)

Example of module-info output

[standalone@localhost:9990 /] /core-service=module-loading:module-info(name=org.jboss.logmanager
{
    "outcome" => "success",
    "result" => {
        "name" => "org.jboss.logmanager:main",
        "main-class" => undefined,
        "fallback-loader" => undefined,
        "dependencies" => [
            {
                "dependency-name" => "ModuleDependency",
                "module-name" => "javax.api:main",
                "export-filter" => "Reject",
                "import-filter" => "multi-path filter {exclude children of \"META-INF/\", exclude equals \"META-INF\", default accept}",
                "optional" => false
            },
            {
                "dependency-name" => "ModuleDependency",
                "module-name" => "org.jboss.modules:main",
                "export-filter" => "Reject",
                "import-filter" => "multi-path filter {exclude children of \"META-INF/\", exclude equals \"META-INF\", default accept}",
                "optional" => false
            }
        ],
        "local-loader-class" => undefined,
        "resource-loaders" => [
            {
                "type" => "org.jboss.modules.JarFileResourceLoader",
                "paths" => [
                    "",
                    "org/jboss/logmanager",
                    "META-INF/services",
                    "org",
                    "META-INF/maven/org.jboss.logmanager/jboss-logmanager",
                    "org/jboss",
                    "org/jboss/logmanager/errormanager",
                    "org/jboss/logmanager/formatters",
                    "META-INF",
                    "org/jboss/logmanager/filters",
                    "org/jboss/logmanager/config",
                    "META-INF/maven",
                    "org/jboss/logmanager/handlers",
                    "META-INF/maven/org.jboss.logmanager"
                ]
            },
            {
                "type" => "org.jboss.modules.NativeLibraryResourceLoader",
                "paths" => undefined
            }
        ]
    }
}

3.1.4. Class Loading in Deployments

For the purposes of class loading, JBoss EAP treats all deployments as modules. These are called dynamic modules. Class loading behavior varies according to the deployment type.

WAR Deployment
A WAR deployment is considered to be a single module. Classes in the WEB-INF/lib directory are treated the same as classes in the WEB-INF/classes directory. All classes packaged in the WAR will be loaded with the same class loader.
EAR Deployment

EAR deployments are made up of more than one module, and are defined by the following rules:

  1. The lib/ directory of the EAR is a single module called the parent module.
  2. Each WAR deployment within the EAR is a single module.
  3. Each EJB JAR deployment within the EAR is a single module.

Subdeployment modules (the WAR and JAR deployments within the EAR) have an automatic dependency on the parent module. However, they do not have automatic dependencies on each other. This is called subdeployment isolation, and can be disabled per deployment, or for the entire application server.

Explicit dependencies between subdeployment modules can be added by the same means as any other module.

3.1.5. Class Loading Precedence

The JBoss EAP modular class loader uses a precedence system to prevent class loading conflicts.

During deployment, a complete list of packages and classes is created for each deployment and each of its dependencies. The list is ordered according to the class loading precedence rules. When loading classes at runtime, the class loader searches this list, and loads the first match. This prevents multiple copies of the same classes and packages within the deployments class path from conflicting with each other.

The class loader loads classes in the following order, from highest to lowest:

  1. Implicit dependencies: These dependencies are automatically added by JBoss EAP, such as the JAVA EE APIs. These dependencies have the highest class loader precedence because they contain common functionality and APIs that are supplied by JBoss EAP.

    Refer to Implicit Module Dependencies for complete details about each implicit dependency.

  2. Explicit dependencies: These dependencies are manually added to the application configuration using the application’s MANIFEST.MF file or the new optional JBoss deployment descriptor jboss-deployment-structure.xml file.

    Refer to Add an Explicit Module Dependency to a Deployment to learn how to add explicit dependencies.

  3. Local resources: These are class files packaged up inside the deployment itself, e.g. from the WEB-INF/classes or WEB-INF/lib directories of a WAR file.
  4. Inter-deployment dependencies: These are dependencies on other deployments in a EAR deployment. This can include classes in the lib directory of the EAR or classes defined in other EJB jars.

3.1.6. Dynamic Module Naming Conventions

JBoss EAP loads all deployments as modules, which are named according to the following conventions.

  • Deployments of WAR and JAR files are named using the following format:

    deployment.DEPLOYMENT_NAME

    For example, inventory.war and store.jar will have the module names of deployment.inventory.war and deployment.store.jar respectively.

  • Subdeployments within an Enterprise Archive (EAR) are named using the following format:

    deployment.EAR_NAME.SUBDEPLOYMENT_NAME

    For example, the subdeployment of reports.war within the enterprise archive accounts.ear will have the module name of deployment.accounts.ear.reports.war.

3.1.7. jboss-deployment-structure.xml

jboss-deployment-structure.xml is an optional deployment descriptor for JBoss EAP. This deployment descriptor provides control over class loading in the deployment.

The XML schema for this deployment descriptor is in /docs/schema/jboss-deployment-structure-1_2.xsd

3.2. Add an Explicit Module Dependency to a Deployment

Explicit module dependencies can be added to applications to add the classes of those modules to the class path of the application at deployment.

Note

JBoss EAP automatically adds some dependencies to deployments. See Implicit Module Dependencies for details.

Prerequisites

  1. A working software project that you want to add a module dependency to.
  2. You must know the name of the module being added as a dependency. See Included Modules for the list of static modules included with JBoss EAP. If the module is another deployment then see Dynamic Module Naming to determine the module name.

Dependencies can be configured using two methods:

  • Adding entries to the MANIFEST.MF file of the deployment.
  • Adding entries to the jboss-deployment-structure.xml deployment descriptor.

Add a Dependency Configuration to MANIFEST.MF

Maven projects can be configured to create the required dependency entries in the MANIFEST.MF file.

  1. If the project does not have one, create a file called MANIFEST.MF. For a web application (WAR) add this file to the META-INF directory. For an EJB archive (JAR) add it to the META-INF directory.
  2. Add a dependencies entry to the MANIFEST.MF file with a comma-separated list of dependency module names:

    Dependencies: org.javassist, org.apache.velocity, org.antlr
    • To make a dependency optional, append optional to the module name in the dependency entry:

      Dependencies: org.javassist optional, org.apache.velocity
    • A dependency can be exported by appending export to the module name in the dependency entry:

      Dependencies: org.javassist, org.apache.velocity export
    • The annotations flag is needed when the module dependency contains annotations that need to be processed during annotation scanning, such as when declaring EJB interceptors. Without this, an EJB interceptor declared in a module cannot be used in a deployment. There are other situations involving annotation scanning when this is needed too.

      Dependencies: org.javassist, test.module annotations
    • By default items in the META-INF of a dependency are not accessible. The services dependency makes items from META-INF/services accessible so that services in the modules can be loaded.

      Dependencies: org.javassist, org.hibernate services
    • To scan a beans.xml file and make its resulting beans available to the application, the meta-inf dependency can be used.

      Dependencies: org.javassist, test.module meta-inf

Add a Dependency Configuration to the jboss-deployment-structure.xml

  1. If the application does not have one, create a new file called jboss-deployment-structure.xml and add it to the project. This file is an XML file with the root element of <jboss-deployment-structure>.

    <jboss-deployment-structure>
    
    </jboss-deployment-structure>

    For a web application (WAR) add this file to the WEB-INF directory. For an EJB archive (JAR) add it to the META-INF directory.

  2. Create a <deployment> element within the document root and a <dependencies> element within that.
  3. Within the <dependencies> node, add a module element for each module dependency. Set the name attribute to the name of the module.

    <module name="org.javassist" />
    • A dependency can be made optional by adding the optional attribute to the module entry with the value of true. The default value for this attribute is false.

      <module name="org.javassist" optional="true" />
    • A dependency can be exported by adding the export attribute to the module entry with the value of true. The default value for this attribute is false.

      <module name="org.javassist" export="true" />
    • When the module dependency contains annotations that need to be processed during annotation scanning, the annotations flag is used.

      <module name="test.module" annotations="true" />
    • The Services dependency specifies whether and how services found in this dependency are used. The default is none. Specifying a value of import for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/services path from the dependency module. Setting a value of export for this attribute is equivalent to the same action on the export filter list.

      <module name="org.hibernate" services="import" />
    • The META-INF dependency specifies whether and how META-INF entries in this dependency are used. The default is none. Specifying a value of import for this attribute is equivalent to adding a filter at the end of the import filter list which includes the META-INF/** path from the dependency module. Setting a value of export for this attribute is equivalent to the same action on the export filter list.

      <module name="test.module" meta-inf="import" />

Example: jboss-deployment-structure.xml with Two Dependencies

<jboss-deployment-structure>
   <deployment>
      <dependencies>
         <module name="org.javassist" />
         <module name="org.apache.velocity" export="true" />
      </dependencies>
   </deployment>
</jboss-deployment-structure>

JBoss EAP adds the classes from the specified modules to the class path of the application when it is deployed.

Creating a Jandex Index

The annotations flag requires that the module contain a Jandex index. In JBoss EAP 7.0, this is generated automatically. However, to add the index manually, perhaps for backwards compatibility, create a new "index JAR" to add to the module. Use the Jandex JAR to build the index, and then insert it into a new JAR file.

Creating a Jandex index::

  1. Create the index:

    java -jar modules/system/layers/base/org/jboss/jandex/main/jandex-jandex-2.0.0.Final-redhat-1.jar $JAR_FILE
  2. Create a temporary working space:

    mkdir /tmp/META-INF
  3. Move the index file to the working directory

    mv $JAR_FILE.ifx /tmp/META-INF/jandex.idx
    1. Option 1: Include the index in a new JAR file

      jar cf index.jar -C /tmp META-INF/jandex.idx

      Then place the JAR in the module directory and edit module.xml to add it to the resource roots.

    2. Option 2: Add the index to an existing JAR

      java -jar /modules/org/jboss/jandex/main/jandex-1.0.3.Final-redhat-1.jar -m $JAR_FILE
  4. Tell the module import to utilize the annotation index, so that annotation scanning can find the annotations.

    1. Option 1: If you are adding a module dependency using MANIFEST.MF, add annotations after the module name. For example change:

      Dependencies: test.module, other.module

      to

      Dependencies: test.module annotations, other.module
    2. Option 2: If you are adding a module dependency using jboss-deployment-structure.xml add annotations="true" on the module dependency.

      Note

      An annotation index is required when an application wants to use annotated Java EE components defined in classes within the static module. In JBoss EAP 7.0, annotation indexes for static modules are automatically generated, so you do not need to create them. However, you must tell the module import to use the annotations by adding the dependencies to either the MANIFEST.MF or the jboss-deployment-structure.xml file.

3.3. Generate MANIFEST.MF entries using Maven

Maven projects using the Maven JAR, EJB, or WAR packaging plug-ins can generate a MANIFEST.MF file with a Dependencies entry. This does not automatically generate the list of dependencies, but only creates the MANIFEST.MF file with the details specified in the pom.xml.

Before generating the MANIFEST.MF entries using Maven, you will require:

  • A working Maven project, which is using one of the JAR, EJB, or WAR plug-ins (maven-jar-plugin, maven-ejb-plugin, or maven-war-plugin).
  • You must know the name of the project’s module dependencies. Refer to Included Modules for the list of static modules included with JBoss EAP. If the module is another deployment, then refer to Dynamic Module Naming to determine the module name.

Generate a MANIFEST.MF File Containing Module Dependencies

  1. Add the following configuration to the packaging plug-in configuration in the project’s pom.xml file.

    <configuration>
       <archive>
          <manifestEntries>
             <Dependencies></Dependencies>
          </manifestEntries>
       </archive>
    </configuration>
  2. Add the list of module dependencies to the <Dependencies> element. Use the same format that is used when adding the dependencies to the MANIFEST.MF file:

    <Dependencies>org.javassist, org.apache.velocity</Dependencies>

    The optional and export attributes can also be used here:

    <Dependencies>org.javassist optional, org.apache.velocity export</Dependencies>
  3. Build the project using the Maven assembly goal:

    [Localhost ]$ mvn assembly:single

    When the project is built using the assembly goal, the final archive contains a MANIFEST.MF file with the specified module dependencies.

    Example: Configured Module Dependencies in pom.xml

    Note

    The example here shows the WAR plug-in but it also works with the JAR and EJB plug-ins (maven-jar-plugin and maven-ejb-plugin).

    <plugins>
       <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-war-plugin</artifactId>
          <configuration>
             <archive>
                <manifestEntries>
                   <Dependencies>org.javassist, org.apache.velocity</Dependencies>
                </manifestEntries>
             </archive>
          </configuration>
       </plugin>
    </plugins>

3.4. Prevent a Module Being Implicitly Loaded

You can configure a deployable application to prevent implicit dependencies from being loaded. This can be useful when an application includes a different version of a library or framework than the one that will be provided by the application server as an implicit dependency.

Prerequisites

  • A working software project that you want to exclude an implicit dependency from.
  • You must know the name of the module to exclude. Refer to Implicit Module Dependencies for a list of implicit dependencies and their conditions.

Add dependency exclusion configuration to jboss-deployment-structure.xml

  1. If the application does not have one, create a new file called jboss-deployment-structure.xml and add it to the project. This is an XML file with the root element of <jboss-deployment-structure>.

    <jboss-deployment-structure>
    
    </jboss-deployment-structure>

    For a web application (WAR) add this file to the WEB-INF directory. For an EJB archive (JAR) add it to the META-INF directory.

  2. Create a <deployment> element within the document root and an <exclusions> element within that.

    <deployment>
       <exclusions>
    
       </exclusions>
    </deployment>
  3. Within the exclusions element, add a <module> element for each module to be excluded. Set the name attribute to the name of the module.

    <module name="org.javassist" />

    Example: Excluding Two Modules

    <jboss-deployment-structure>
       <deployment>
          <exclusions>
             <module name="org.javassist" />
             <module name="org.dom4j" />
          </exclusions>
       </deployment>
    </jboss-deployment-structure>

3.5. Exclude a Subsystem from a Deployment

Excluding a subsystem provides the same effect as removing the subsystem, but it applies only to a single deployment. You can exclude a subsystem from a deployment by editing the jboss-deployment-structure.xml configuration file.

Exclude a Subsystem

  1. Edit the jboss-deployment-structure.xml file.
  2. Add the following XML inside the <deployment> tags:

    <exclude-subsystems>
      <subsystem name="SUBSYSTEM_NAME" />
    </exclude-subsystems>
  3. Save the jboss-deployment-structure.xml file.

The subsystem’s deployment unit processors will no longer run on the deployment.

Example: jboss-deployment-structure.xml File

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
  <ear-subdeployments-isolated>true</ear-subdeployments-isolated>
  <deployment>
    <exclude-subsystems>
      <subsystem name="jaxrs" />
    </exclude-subsystems>
    <exclusions>
      <module name="org.javassist" />
    </exclusions>
    <dependencies>
      <module name="deployment.javassist.proxy" />
      <module name="deployment.myjavassist" />
      <module name="myservicemodule" services="import"/>
    </dependencies>
    <resources>
      <resource-root path="my-library.jar" />
    </resources>
  </deployment>
  <sub-deployment name="myapp.war">
    <dependencies>
      <module name="deployment.myear.ear.myejbjar.jar" />
    </dependencies>
    <local-last value="true" />
  </sub-deployment>
  <module name="deployment.myjavassist" >
    <resources>
     <resource-root path="javassist.jar" >
       <filter>
         <exclude path="javassist/util/proxy" />
       </filter>
     </resource-root>
    </resources>
  </module>
  <module name="deployment.javassist.proxy" >
    <dependencies>
      <module name="org.javassist" >
        <imports>
          <include path="javassist/util/proxy" />
          <exclude path="/**" />
        </imports>
      </module>
    </dependencies>
  </module>
</jboss-deployment-structure>

3.6. Use the Class Loader Programmatically in a Deployment

3.6.1. Programmatically Load Classes and Resources in a Deployment

You can programmatically find or load classes and resources in your application code. The method you choose will depend on a number of factors. This topic describes the methods available and provides guidelines for when to use them.

Load a Class Using the Class.forName() Method

You can use the Class.forName() method to programmatically load and initialize classes. This method has two signatures:

  • Class.forName(String className): This signature takes only one parameter, the name of the class you need to load. With this method signature, the class is loaded by the class loader of the current class and initializes the newly loaded class by default.
  • Class.forName(String className, boolean initialize, ClassLoader loader): This signature expects three parameters: the class name, a boolean value that specifies whether to initialize the class, and the ClassLoader that should load the class.

The three argument signature is the recommended way to programmatically load a class. This signature allows you to control whether you want the target class to be initialized upon load. It is also more efficient to obtain and provide the class loader because the JVM does not need to examine the call stack to determine which class loader to use. Assuming the class containing the code is named CurrentClass, you can obtain the class’s class loader using CurrentClass.class.getClassLoader() method.

The following example provides the class loader to load and initialize the TargetClass class:

Class<?> targetClass = Class.forName("com.myorg.util.TargetClass", true, CurrentClass.class.getClassLoader());

Find All Resources with a Given Name

If you know the name and path of a resource, the best way to load it directly is to use the standard Java development kit Class or ClassLoader API.

  • Load a Single Resource: To load a single resource located in the same directory as your class or another class in your deployment, you can use the Class.getResourceAsStream() method.

    InputStream inputStream = CurrentClass.class.getResourceAsStream("targetResourceName");
  • Load All Instances of a Single Resource: To load all instances of a single resource that are visible to your deployment’s class loader, use the Class.getClassLoader().getResources(String resourceName) method, where resourceName is the fully qualified path of the resource. This method returns an Enumeration of all URL objects for resources accessible by the class loader with the given name. You can then iterate through the array of URLs to open each stream using the openStream() method.

    The following example loads all instances of a resource and iterates through the results.

    Enumeration<URL> urls = CurrentClass.class.getClassLoader().getResources("full/path/to/resource");
    while (urls.hasMoreElements()) {
        URL url = urls.nextElement();
        InputStream inputStream = null;
        try {
            inputStream = url.openStream();
            // Process the inputStream
            ...
        } catch(IOException ioException) {
            // Handle the error
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e) {
                    // ignore
                }
            }
        }
    }

Because the URL instances are loaded from local storage, it is not necessary to use the openConnection() or other related methods. Streams are much simpler to use and minimize the complexity of the code.

  • Load a Class File From the Class Loader: If a class has already been loaded, you can load the class file that corresponds to that class using the following syntax:

    InputStream inputStream = CurrentClass.class.getResourceAsStream(TargetClass.class.getSimpleName() + ".class");

    If the class is not yet loaded, you must use the class loader and translate the path:

    String className = "com.myorg.util.TargetClass"
    InputStream inputStream = CurrentClass.class.getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");

3.6.2. Programmatically Iterate Resources in a Deployment

The JBoss Modules library provides several APIs for iterating all deployment resources. The JavaDoc for the JBoss Modules API is located here: http://docs.jboss.org/jbossmodules/1.3.0.Final/api/. To use these APIs, you must add the following dependency to the MANIFEST.MF:

Dependencies: org.jboss.modules

It is important to note that while these APIs provide increased flexibility, they will also run much more slowly than a direct path lookup.

This topic describes some of the ways you can programmatically iterate through resources in your application code.

  • List Resources Within a Deployment and Within All Imports: There are times when it is not possible to look up resources by the exact path. For example, the exact path may not be known or you may need to examine more than one file in a given path. In this case, the JBoss Modules library provides several APIs for iterating all deployment resources. You can iterate through resources in a deployment by utilizing one of two methods.

    • Iterate All Resources Found in a Single Module: The ModuleClassLoader.iterateResources() method iterates all the resources within this module class loader. This method takes two arguments: the starting directory name to search and a boolean that specifies whether it should recurse into subdirectories.

      The following example demonstrates how to obtain the ModuleClassLoader and obtain the iterator for resources in the bin/ directory, recursing into subdirectories.

      ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
      Iterator<Resource> mclResources = moduleClassLoader.iterateResources("bin",true);

      The resultant iterator may be used to examine each matching resource and query its name and size (if available), open a readable stream, or acquire a URL for the resource.

    • Iterate All Resources Found in a Single Module and Imported Resources: The Module.iterateResources() method iterates all the resources within this module class loader, including the resources that are imported into the module. This method returns a much larger set than the previous method. This method requires an argument, which is a filter that narrows the result to a specific pattern. Alternatively, PathFilters.acceptAll() can be supplied to return the entire set.

      The following example demonstrates how to find the entire set of resources in this module, including imports.

      ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
      Module module = moduleClassLoader.getModule();
      Iterator<Resource> moduleResources = module.iterateResources(PathFilters.acceptAll());
  • Find All Resources That Match a Pattern: If you need to find only specific resources within your deployment or within your deployment’s full import set, you need to filter the resource iteration. The JBoss Modules filtering APIs give you several tools to accomplish this.

    • Examine the Full Set of Dependencies: If you need to examine the full set of dependencies, you can use the Module.iterateResources() method’s PathFilter parameter to check the name of each resource for a match.
    • Examine Deployment Dependencies: If you need to look only within the deployment, use the ModuleClassLoader.iterateResources() method. However, you must use additional methods to filter the resultant iterator. The PathFilters.filtered() method can provide a filtered view of a resource iterator this case. The PathFilters class includes many static methods to create and compose filters that perform various functions, including finding child paths or exact matches, or matching an Ant-style "glob" pattern.
  • Additional Code Examples For Filtering Resouces: The following examples demonstrate how to filter resources based on different criteria.

    Example: Find All Files Named messages.properties in Your Deployment

    ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
    Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/messages.properties"), moduleClassLoader.iterateResources("", true));

    Example: Find All Files Named messages.properties in Your Deployment and Imports

    ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
    Module module = moduleClassLoader.getModule();
    Iterator<Resource> moduleResources = module.iterateResources(PathFilters.match("**/message.properties"));

    Example: Find All Files Inside Any Directory Named my-resources in Your Deployment

    ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
    Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/my-resources/**"), moduleClassLoader.iterateResources("", true));

    Example: Find All Files Named messages or errors in Your Deployment and Imports

    ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
    Module module = moduleClassLoader.getModule();
    Iterator<Resource> moduleResources = module.iterateResources(PathFilters.any(PathFilters.match("**/messages"), PathFilters.match("**/errors"));

    Example: Find All Files in a Specific Package in Your Deployment

    ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
    Iterator<Resource> mclResources = moduleClassLoader.iterateResources("path/form/of/packagename", false);

3.7. Class Loading and Subdeployments

3.7.1. Modules and Class Loading in Enterprise Archives

Enterprise Archives (EAR) are not loaded as a single module like JAR or WAR deployments. They are loaded as multiple unique modules.

The following rules determine what modules exist in an EAR:

  • The contents of the lib/ directory in the root of the EAR archive is a module. This is called the parent module.
  • Each WAR and EJB JAR subdeployment is a module. These modules have the same behavior as any other module as well as implicit dependencies on the parent module.
  • Subdeployments have implicit dependencies on the parent module and any other non-WAR subdeployments.

The implicit dependencies on non-WAR subdeployments occur because JBoss EAP has subdeployment class loader isolation disabled by default. Dependencies on the parent module persist, regardless of subdeployment class loader isolation.

Important

No subdeployment ever gains an implicit dependency on a WAR subdeployment. Any subdeployment can be configured with explicit dependencies on another subdeployment as would be done for any other module.

Subdeployment class loader isolation can be enabled if strict compatibility is required. This can be enabled for a single EAR deployment or for all EAR deployments. The Java EE specification recommends that portable applications should not rely on subdeployments being able to access each other unless dependencies are explicitly declared as Class-Path entries in the MANIFEST.MF file of each subdeployment.

3.7.2. Subdeployment Class Loader Isolation

Each subdeployment in an Enterprise Archive (EAR) is a dynamic module with its own class loader. By default a subdeployment can access the resources of other subdeployments.

If a subdeployment is not to be allowed to access the resources of other subdeployments, strict subdeployment isolation can be enabled.

3.7.3. Enable Subdeployment Class Loader Isolation Within a EAR

This task shows you how to enable subdeployment class loader isolation in an EAR deployment by using a special deployment descriptor in the EAR. This does not require any changes to be made to the application server and does not affect any other deployments.

Important

Even when subdeployment class loader isolation is disabled it is not possible to add a WAR deployment as a dependency.

  1. Add the deployment descriptor file: Add the jboss-deployment-structure.xml deployment descriptor file to the META-INF directory of the EAR if it doesn’t already exist and add the following content:

    <jboss-deployment-structure>
    
    </jboss-deployment-structure>
  2. Add the <ear-subdeployments-isolated> element: Add the <ear-subdeployments-isolated> element to the jboss-deployment-structure.xml file if it doesn’t already exist with the content of true.

    <ear-subdeployments-isolated>true</ear-subdeployments-isolated>

Result

Subdeployment class loader isolation will now be enabled for this EAR deployment. This means that the subdeployments of the EAR will not have automatic dependencies on each of the non-WAR subdeployments.

3.7.4. Configuring Session Sharing between Subdeployments in Enterprise Archives

JBoss EAP provides the ability to configure enterprise archives (EARs) to share sessions between WAR module subdeployments contained in the EAR. This functionality is disabled by default and must be explicitly enabled in the META-INF/jboss-all.xml file in the EAR.

Important

Since this feature is not a standard servlet feature, your applications may not be portable if this functionality is enabled.

To enable session sharing between WARs within an EAR, you need to declare a shared-session-config element in the META-INF/jboss-all.xml of the EAR:

Example: META-INF/jboss-all.xml

<jboss umlns="urn:jboss:1.0">
  ...
  <shared-session-config xmlns="urn:jboss:shared-session-config:1.0">
  </shared-session-config>
  ...
</jboss>

The shared-session-config element is used to configure the shared session manager for all WARs within the EAR. If the shared-session-config element is present, all WARs within the EAR will share the same session manager. Changes made here will affect all the WARs contained within the EAR.

3.7.4.1. Reference of Shared Session Configuration Options

The shared-session-config element has the following structure:

  • shared-session-config

    • max-active-sessions
    • session-config

      • session-timeout
      • cookie-config

        • name
        • domain
        • path
        • comment
        • http-only
        • secure
        • max-age
      • tracking-mode
    • replication-config

      • cache-name
      • replication-granularity

Example: META-INF/jboss-all.xml

<jboss umlns="urn:jboss:1.0">
    <shared-session-config xmlns="urn:jboss:shared-session-config:1.0">
        <max-active-sessions>10</max-active-sessions>
        <session-config>
            <session-timeout>0</session-timeout>
            <cookie-config>
                <name>JSESSIONID</name>
                <domain>domainName</domain>
                <path>/cookiePath</path>
                <comment>cookie comment</comment>
                <http-only>true</http-only>
                <secure>true</secure>
                <max-age>-1</max-age>
            </cookie-config>
            <tracking-mode>COOKIE</tracking-mode>
        </session-config>
        <replication-config>
            <cache-name>web</cache-name>
            <replication-granularity>SESSION</replication-granularity>
        </replication-config>
    </shared-session-config>
</jboss>

shared-session-config
Root element for the shared session configuration. If this is present in the META-INF/jboss-all.xml, then all deployed WARs contained in the EAR will share a single session manager.
max-active-sessions
Number of maximum sessions allowed.
session-config
Contains the session configuration parameters for all deployed WARs contained in the EAR.
session-timeout
Defines the default session timeout interval for all sessions created in the deployed WARs contained in the EAR. The specified timeout must be expressed in a whole number of minutes. If the timeout is 0 or less, the container ensures the default behavior of sessions is to never time out. If this element is not specified, the container must set its default timeout period.
cookie-config
Contains the configuration of the session tracking cookies created by the deployed WARs contained in the EAR.
name
The name that will be assigned to any session tracking cookies created by the deployed WARs contained in the EAR. The default is JSESSIONID.
domain
The domain name that will be assigned to any session tracking cookies created by the deployed WARs contained in the EAR.
path
The path that will be assigned to any session tracking cookies created by the deployed WARs contained in the EAR.
comment
The comment that will be assigned to any session tracking cookies created by the deployed WARs contained in the EAR.
http-only
Specifies whether any session tracking cookies created by the deployed WARs contained in the EAR will be marked as HttpOnly.
secure
Specifies whether any session tracking cookies created by the deployed WARs contained in the EAR will be marked as secure even if the request that initiated the corresponding session is using plain HTTP instead of HTTPS
max-age
The lifetime (in seconds) that will be assigned to any session tracking cookies created by the deployed WARs contained in the EAR. Default is -1.
tracking-mode
Defines the tracking modes for sessions created by the deployed WARs contained in the EAR.
replication-config
Contains the HTTP session clustering configuration.
cache-name
This option is for use in clustering only. It specifies the name of the Infinispan container and cache in which to store session data. The default value, if not explicitly set, is determined by the application server. To use a specific cache within a cache container, use the form container.cache, for example web.dist. If name is unqualified, the default cache of the specified container is used.
replication-granularity

This option is for use in clustering only. It determines the session replication granularity level. The possible values are SESSION and ATTRIBUTE with SESSION being the default.

If SESSION granularity is used, all session attributes are replicated if any were modified within the scope of a request. This policy is required if an object reference is shared by multiple session attributes. However, this can be inefficient if session attributes are sufficiently large and/or are modified infrequently, since all attributes must be replicated regardless of whether they were modified or not.

If ATTRIBUTE granularity is used, only those attributes that were modified within the scope of a request are replicated. This policy is not appropriate if an object reference is shared by multiple session attributes. This can be more efficient than SESSION granularity if the session attributes are sufficiently large and/or are modified infrequently.

3.8. Deploy Tag Library Descriptors (TLDs) in a Custom Module

If you have multiple applications that use common Tag Library Descriptors (TLDs), it may be useful to separate the TLDs from the applications so that they are located in one central and unique location. This enables easier additions and updates to TLDs without necessarily having to update each individual application that uses them.

This can be done by creating a custom JBoss EAP module that contains the TLD JARs, and declaring a dependency on that module in the applications.

Note

Ensure that at least one JAR contains TLDs and the TLDs are packed in META-INF.

Deploy TLDs in a Custom Module

  1. Using the management CLI, connect to your JBoss EAP instance and execute the following command to create the custom module containing the TLD JAR:

    module add --name=MyTagLibs --resources=/path/to/TLDarchive.jar
    Important

    Using the module management CLI command to add and remove modules is provided as technology preview only. This command is not appropriate for use in a managed domain or when connecting to the management CLI remotely. Modules should be added and removed manually in a production environment. For more information, see the Create a Custom Module Manually and Remove a Custom Module Manually sections of the JBoss EAP Configuration Guide.

    If the TLDs are packaged with classes that require dependencies, use the --dependencies= option to ensure that you specify those dependencies when creating the custom module.

    When creating the module, you can specify multiple JAR resources by separating each one with the file system-specific separator for your system.

    • For linux - :. Example, --resources=<path-to-jar>:<path-to-another-jar>
    • For Windows - ;. Example, --resources=<path-to-jar>;<path-to-another-jar>

      Note
      --resources
      It is required unless --module-xml is used. It lists file system paths, usually JAR files, separated by a file system-specific path separator, for example java.io.File.pathSeparatorChar. The files specified will be copied to the created module’s directory.
      --resource-delimiter
      It is an optional user-defined path separator for the resources argument. If this argument is present, the command parser will use the value here instead of the file system-specific path separator. This allows the modules command to be used in cross-platform scripts.
  2. In your applications, declare a dependency on the new MyTagLibs custom module using one of the methods described in Add an Explicit Module Dependency to a Deployment.
Important

Ensure that you also import META-INF when declaring the dependency. For example, for MANIFEST.MF:

Dependencies: com.MyTagLibs meta-inf

Or, for jboss-deployment-structure.xml, use the meta-inf attribute.

3.9. Reference

3.9.1. Implicit Module Dependencies

The following table lists the modules that are automatically added to deployments as dependencies and the conditions that trigger the dependency.

Table 3.1. Implicit Module Dependencies

Subsystem Responsible for Adding the DependencyPackage Dependencies That Are Always AddedPackage Dependencies That Are Conditionally AddedConditions That Trigger the Addition of the Dependency

Application Client

  • org.omg.api
  • org.jboss.xnio
  

Batch

  • javax.batch.api
  • org.jberet.jberet-core
  • org.wildfly.jberet
  

Bean Validation

  • org.hibernate.validator
  • javax.validation.api
  

Core Server

  • javax.api
  • sun.jdk
  • org.jboss.vfs
  • ibm.jdk
  

DriverDependenciesProcessor

 
  • javax.transaction.api
 

EE

  • org.jboss.invocation (except org.jboss.invocation.proxy.classloading)
  • org.jboss.as.ee (except org.jboss.as.ee.component.serialization, org.jboss.as.ee.concurrent, org.jboss.as.ee.concurrent.handle)
  • org.wildfly.naming
  • javax.annotation.api
  • javax.enterprise.concurrent.api
  • javax.interceptor.api
  • javax.json.api
  • javax.resource.api
  • javax.rmi.api
  • javax.xml.bind.api
  • javax.api
  • org.glassfish.javax.el
  • org.glassfish.javax.enterprise.concurrent
  

EJB 3

  • javax.ejb.api
  • javax.xml.rpc.api
  • org.jboss.ejb-client
  • org.jboss.iiop-client
  • org.jboss.as.ejb3
  • org.wildfly.iiop-openjdk
 

IIOP

  • org.omg.api
  • javax.rmi.api
  • javax.orb.api
  

JAX-RS (RESTEasy)

  • javax.xml.bind.api
  • javax.ws.rs.api
  • javax.json.api
  • org.jboss.resteasy.resteasy-atom-provider
  • org.jboss.resteasy.resteasy-crypto
  • org.jboss.resteasy.resteasy-validator-provider-11
  • org.jboss.resteasy.resteasy-jaxrs
  • org.jboss.resteasy.resteasy-jaxb-provider
  • org.jboss.resteasy.resteasy-jackson2-provider
  • org.jboss.resteasy.resteasy-jsapi
  • org.jboss.resteasy.resteasy-json-p-provider
  • org.jboss.resteasy.resteasy-multipart-provider
  • org.jboss.resteasy.resteasy-yaml-provider
  • org.codehaus.jackson.jackson-core-asl
  • org.jboss.resteasy.resteasy-cdi

The presence of JAX-RS annotations in the deployment.

JCA

  • javax.resource.api
  • javax.jms.api
  • javax.validation.api
  • org.jboss.ironjacamar.api
  • org.jboss.ironjacamar.impl
  • org.hibernate.validator

The deployment of a resource adapter (RAR) archive.

JPA (Hibernate)

  • javax.persistence.api
  • org.jboss.as.jpa
  • org.jboss.as.jpa.spi
  • org.javassist

The presence of an @PersistenceUnit or @PersistenceContext annotation, or a <persistence-unit-ref> or <persistence-context-ref> element in a deployment descriptor.

JBoss EAP maps persistence provider names to module names. If you name a specific provider in the persistence.xml file, a dependency is added for the appropriate module. If this not the desired behavior, you can exclude it using a jboss-deployment-structure.xml file.

JSF (Java Server Faces)

 
  • javax.faces.api
  • com.sun.jsf-impl
  • org.jboss.as.jsf
  • org.jboss.as.jsf-injection

Added to EAR applications.

Added to WAR applications only if the web.xml file does NOT specify a context-param of org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL with a value of true.

JSR-77

  • javax.management.j2ee.api
  

Logging

  • org.jboss.logging
  • org.apache.commons.logging
  • org.apache.log4j
  • org.slf4j
  • org.jboss.logging.jul-to-slf4j-stub
  

Mail

  • javax.mail.api
  • javax.activation.api
  

Messaging

  • javax.jms.api
  • org.wildfly.extension.messaging-activemq
 

PicketLink Federation

 
  • org.picketlink
 

Pojo

  • org.jboss.as.pojo
  

SAR

 
  • org.jboss.modules
  • org.jboss.as.system-jmx
  • org.jboss.common-beans

The deployment of a SAR archive that has a jboss-service.xml.

Seam2

 
  • org.jboss.vfs

.

Security

  • org.picketbox
  • org.jboss.as.security
  • javax.security.jacc.api
  • javax.security.auth.message.api
  

ServiceActivator

 
  • org.jboss.msc
 

Transactions

  • javax.transaction.api
  • org.jboss.xts
  • org.jboss.jts
  • org.jboss.narayana.compensations
 

Undertow

  • javax.servlet.jstl.api
  • javax.servlet.api
  • javax.servlet.jsp.api
  • javax.websocket.api
  • io.undertow.core
  • io.undertow.servlet
  • io.undertow.jsp
  • io.undertow.websocket
  • io.undertow.js
  • org.wildfly.clustering.web.api
 

Web Services

  • javax.jws.api
  • javax.xml.soap.api
  • javax.xml.ws.api
  • org.jboss.ws.api
  • org.jboss.ws.spi

If it is not application client type, then it will add the conditional dependencies.

Weld (CDI)

  • javax.enterprise.api
  • javax.inject.api
  • javax.persistence.api
  • org.javassist
  • org.jboss.as.weld
  • org.jboss.weld.core
  • org.jboss.weld.probe
  • org.jboss.weld.api
  • org.jboss.weld.spi
  • org.hibernate.validator.cdi

The presence of a beans.xml file in the deployment.

3.9.2. Included Modules

For the complete listing of the included modules and whether they are supported, see Red Hat JBoss Enterprise Application Platform 7 Included Modules on the Red Hat Customer Portal.

3.9.3. JBoss Deployment Structure Deployment Descriptor Reference

The key tasks that can be performed using this deployment descriptor are:

  • Defining explicit module dependencies.
  • Preventing specific implicit dependencies from loading.
  • Defining additional modules from the resources of that deployment.
  • Changing the subdeployment isolation behavior in that EAR deployment.
  • Adding additional resource roots to a module in an EAR.