Chapter 6. JBoss EAP Class Loading
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.
6.1. 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
.
Starting with JBoss EAP 7.1, the use of absolute paths in the resource-root path
element of the module.xml
file is also supported. This way, your resource libraries can be made accessible without needing to move them to the EAP_HOME/modules
directory.
Example: Absolute Path in the module.xml
File
<?xml version="1.0" ?> <module xmlns="urn:jboss:module:1.1" name="oracle.jdbc"> <resources> <resource-root path="/home/redhat/test.jar"/> </resources> </module>
Dynamic Modules
Dynamic modules are created and loaded by the application server for each JAR or WAR deployment, or for each 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.
6.2. 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.
See the Modules section for complete details about modules and the modular class loading system.
Deployed applications, such as a JAR or WAR, 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’sMANIFEST.MF
orjboss-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.
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 for details.
6.3. Create a Custom Module
Custom static modules can be added to make resources available for deployments running on JBoss EAP. You can create the module manually or by using the management CLI.
Once you create the module, you must add the module as a dependency if its resources need to be made available to applications.
Create a Custom Module Manually
You can create a custom module manually using the following steps.
Create the appropriate directory structure in the
EAP_HOME/modules/
directory.Example: Create MySQL JDBC Driver Directory Structure
$ cd EAP_HOME/modules/ $ mkdir -p com/mysql/main
Copy the JAR files or other necessary resources to the
main/
subdirectory.Example: Copy MySQL JDBC Driver JAR
$ cp /path/to/mysql-connector-java-5.1.36-bin.jar EAP_HOME/modules/com/mysql/main/
Create a
module.xml
file in themain/
subdirectory, specifying the appropriate resources and dependencies in the file.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>
Create a Custom Module Using the Management CLI
You can create a custom module using the module add
management CLI command.
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.
Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend to use them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
See Technology Preview Features Support Scope on the Red Hat Customer Portal for information about the support scope for Technology Preview features.
- Start the JBoss EAP server.
Launch the management CLI, but do not use the
--connect
or-c
argument to connect to the running instance.$ EAP_HOME/bin/jboss-cli.sh
Use the
module add
management CLI command to add the new core module.module add --name=MODULE_NAME --resources=PATH_TO_RESOURCE --dependencies=DEPENDENCIES
Example: Create a MySQL Module
module add --name=com.mysql --resources=/path/to/mysql-connector-java-5.1.36-bin.jar --dependencies=javax.api,javax.transaction.api
See Module Command Arguments for the available arguments to customize this command, such as providing your own
module.xml
file, using an external module directory, or specifying an alternative slot for the module. You can also executemodule --help
for more details on using this command to add and remove modules.
Add the Module as a Dependency
In order for your application to be able to access this module’s resources, you must add the module as a dependency.
- See the Add an Explicit Module Dependency to a Deployment section of the JBoss EAP Development Guide for adding application-specific dependencies using deployment descriptors.
- See the Define Global Modules section for instructions on adding modules as dependencies to all applications.
As an example, the following steps add a JAR file containing several properties files as a module and define a global module, so that an application can then load these properties.
Add the JAR file as a core module.
module add --name=myprops --resources=/path/to/properties.jar
Define this module as a global module so that it is made available to all deployments.
/subsystem=ee:list-add(name=global-modules,value={name=myprops})
The application can then retrieve the properties from one of the properties files contained within the JAR.
Thread.currentThread().getContextClassLoader().getResource("my.properties");
6.4. Remove a Custom Module
Custom static modules can be removed manually or by using the management CLI.
Remove a Custom Module Manually
Before manually removing a module, ensure that it is not required by deployed applications or elsewhere in the server configuration, such as by a datasource.
To remove a custom module, remove the module’s directory under EAP_HOME/modules/
, which includes its module.xml
file and associated JAR files or other resources. For example, remove the EAP_HOME/modules/com/mysql/main/
directory to remove a custom MySQL JDBC driver module in the main
slot.
Remove a Custom Module Using the Management CLI
You can remove a custom module using the module remove
management CLI command.
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.
Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend to use them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
See Technology Preview Features Support Scope on the Red Hat Customer Portal for information about the support scope for Technology Preview features.
- Start the JBoss EAP server.
Launch the management CLI, but do not use the
--connect
or-c
argument to connect to the running instance.$ EAP_HOME/bin/jboss-cli.sh
Use the
module remove
management CLI command to remove the custom module.module remove --name=MODULE_NAME
-
Use the
--slot
argument if the module to remove is in a slot other thanmain
.
Example: Remove a MySQL Module
module remove --name=com.mysql
-
Use the
Execute module --help
for more details on using this command to add and remove modules.
6.5. Define Global Modules
A list of global modules can be defined for JBoss EAP, which will add the modules as dependencies to all deployments.
You must know the name of the modules that are to be configured as global 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. See the Dynamic Module Naming section for naming conventions for modules in deployments.
Use the following management CLI command to define the list of global modules.
/subsystem=ee:write-attribute(name=global-modules,value=[{name=MODULE_NAME_1},{name=MODULE_NAME_2}]
Use the following management CLI command to add a single module to the list of existing global modules.
/subsystem=ee:list-add(name=global-modules,value={name=MODULE_NAME})
Global modules can also be added and removed using the management console by navigating to the EE subsystem from the Configuration tab and selecting the Global Modules section.
6.6. Configure Subdeployment Isolation
Each subdeployment in an Enterprise Archive (EAR) is a dynamic module with its own class loader. Subdeployments always have an implicit dependency on the parent module, which gives them access to classes in EAR/lib
. By default, a subdeployment can access the resources of other subdeployments within that EAR.
If you do not want a subdeployment to be allowed to access classes belonging to other subdeployments, then strict subdeployment isolation can be enabled in JBoss EAP. This setting will affect all deployments.
Enable Subdeployment Module Isolation for All Deployments
Subdeployment isolation can be enabled or disabled using the management console or the management CLI from the ee
subsystem. By default, subdeployment isolation is set to false, which allows the subdeployments to access resources of other subdeployments within an EAR deployment.
Use the following management CLI to enable EAR subdeployment isolation.
/subsystem=ee:write-attribute(name=ear-subdeployments-isolated,value=true)
Subdeployments in an EAR will no longer be able to access resources from other subdeployments.
6.7. Define an External JBoss EAP Module Directory
The default directory for JBoss EAP modules is EAP_HOME/modules
. You can specify a different directory for JBoss EAP modules using the JBOSS_MODULEPATH
variable. Follow the below steps to set this variable in the JBoss EAP startup configuration file.
You can also set JBOSS_MODULEPATH
as an environment variable instead of setting this in the JBoss EAP startup configuration files.
Edit the startup configuration file.
-
When running as a standalone server, edit the
EAP_HOME/bin/standalone.conf
file, orstandalone.conf.bat
for Windows Server. -
When running in a managed domain, edit the
EAP_HOME/bin/domain.conf
file, ordomain.conf.bat
for Windows Server.
-
When running as a standalone server, edit the
Set the
JBOSS_MODULEPATH
variable, for example:JBOSS_MODULEPATH="/path/to/modules/directory/"
To specify a list of directories use a colon (
:
) to delimit the list of directories.NoteFor Windows Server, use the following syntax to set the
JBOSS_MODULEPATH
variable:set "JBOSS_MODULEPATH /path/to/modules/directory/"
To specify a list of directories use a semicolon (
;
) to delimit the list of directories.
6.8. 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
andstore.jar
will have the module names ofdeployment.inventory.war
anddeployment.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 archiveaccounts.ear
will have the module name ofdeployment.accounts.ear.reports.war
.