Chapter 5. Overview of JBoss EAP class loading
JBoss EAP uses a modular class loading system for controlling the classpaths 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 to include the classes from that module in its own class path. Because each deployed Java Archive (JAR) and Web Archive (WAR) file is treated as a module, developers can control the contents of their application’s class path by adding module configuration.
5.1. Types of modules in JBoss EAP Copy linkLink copied to clipboard!
A module is a logical grouping of classes used for class loading and dependency management. JBoss EAP identifies two different types of modules:
- Static modules
- Dynamic modules
The main difference between the two is how they are packaged.
JBoss EAP also provides a set of predefined modules.
5.1.1. Static modules in JBoss EAP Copy linkLink copied to clipboard!
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 Java Archive (JAR) files. All the application server-provided APIs are provided as static modules, including the Jakarta EE APIs as well as other APIs.
Example: MySQL JDBC Driver module.xml File
The MySQL driver JAR name, mysql-connector-j-8.0.33.jar, is provided only as an example. For information about the tested MySQL version, see Tested databases.
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.
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
5.1.2. Dynamic modules in JBoss EAP Copy linkLink copied to clipboard!
Dynamic modules are created and loaded by the application server for each Java Archive (JAR) or Web Archive (WAR) deployment, or for each subdeployment in an Enterprise Archive (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 loaded only when required, usually when an application with explicit or implicit dependencies is deployed.
5.1.3. Predefined modules in JBoss EAP Copy linkLink copied to clipboard!
A set of predefined modules is available to you when you use the default module loader in the application server. The special module, org.jboss.modules, which includes all of the JBoss Modules API, is always available and is provided by JBoss Modules. The standard Java Platform Module System (JPMS) modules are also available by their standard names.
For a list of platform modules available on Java 9 or later, see the appropriate JDK documentation.
5.2. Module dependencies in JBoss EAP Copy linkLink copied to clipboard!
A module dependency is a declaration that one module requires the classes of one or more other modules 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.
Deployed applications, such as a Java Archive (JAR) or Web Archive (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.xmlfile. A dynamic module can declare dependencies in the deployment’sMANIFEST.MF, orjboss-deployment-structure.xmldeployment descriptor. - Implicit dependencies
- Implicit dependencies are added automatically by JBoss EAP when certain conditions or metadata are found in a deployment. The Jakarta EE 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.
5.2.1. Optional Dependencies Copy linkLink copied to clipboard!
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.
5.2.2. Exported dependency Copy linkLink copied to clipboard!
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.
5.2.3. Global modules Copy linkLink copied to clipboard!
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.
For more information, see Global modules in JBoss EAP.
5.3. Creating custom modules for JBoss EAP Copy linkLink copied to clipboard!
Creating custom 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.
You can create custom modules in the following ways:
5.3.1. Creating a custom module manually Copy linkLink copied to clipboard!
You can create a module from Java Archive (JAR) or other resource files to make them available to applications in JBoss EAP.
Prerequisites
- You have the JAR or resource files required by the module.
Procedure
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
$ cd EAP_HOME/modules/ $ mkdir -p com/mysql/mainCopy to Clipboard Copied! Toggle word wrap Toggle overflow Copy the JAR files or other necessary resources to the
main/subdirectory.Example: copy MySQL JDBC driver JAR
cp /path/to/mysql-connector-j-8.0.33.jar EAP_HOME/modules/com/mysql/main/
$ cp /path/to/mysql-connector-j-8.0.33.jar EAP_HOME/modules/com/mysql/main/Copy to Clipboard Copied! Toggle word wrap Toggle overflow NoteThe MySQL driver JAR name, mysql-connector-j-8.0.33.jar, is provided only as an example. For information about the tested MySQL version, see Tested databases.
Create a
module.xmlfile in themain/subdirectory, specifying the appropriate resources and dependencies in the file.Example: MySQL JDBC driver
module.xmlfileCopy to Clipboard Copied! Toggle word wrap Toggle overflow NoteThe MySQL driver JAR name, mysql-connector-j-8.0.33.jar, is provided only as an example. For information about the tested MySQL version, see Tested databases.
5.3.2. Creating a custom module by using the management CLI Copy linkLink copied to clipboard!
You can create a module from Java Archive (JAR) or other resource files to make them available to applications in JBoss EAP by using the management CLI.
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:
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.
Prerequisites
- You have the JAR or resource files required for by the module.
Procedure
- Start the JBoss EAP server.
Launch the management CLI.
EAP_HOME/bin/jboss-cli.sh
$ EAP_HOME/bin/jboss-cli.shCopy to Clipboard Copied! Toggle word wrap Toggle overflow Use the
module addmanagement CLI command to add the new core module.Syntax
module add --name=<MODULE_NAME> --resources=<PATH_TO_RESOURCE> --dependencies=<DEPENDENCIES>
module add --name=<MODULE_NAME> --resources=<PATH_TO_RESOURCE> --dependencies=<DEPENDENCIES>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Example: Create a MySQL Module
module add --name=com.mysql --resources=</path/to>/mysql-connector-j-8.0.33.jar --dependencies=java.xml,java.xml.crypto,jdk.xml.dom,jakarta.transaction.api
module add --name=com.mysql --resources=</path/to>/mysql-connector-j-8.0.33.jar --dependencies=java.xml,java.xml.crypto,jdk.xml.dom,jakarta.transaction.apiCopy to Clipboard Copied! Toggle word wrap Toggle overflow NoteThe MySQL driver JAR name, mysql-connector-j-8.0.33.jar, is provided only as an example. For information about the tested MySQL version, see Tested databases.
5.4. Adding a module as a dependency Copy linkLink copied to clipboard!
To access a module’s resources, your application must have the module added 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 Global modules in JBoss EAP 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.
Procedure
Add the JAR file as a core module.
module add --name=myprops --resources=</path/to>/properties.jar
module add --name=myprops --resources=</path/to>/properties.jarCopy to Clipboard Copied! Toggle word wrap Toggle overflow 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})/subsystem=ee:list-add(name=global-modules,value={name=myprops})Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Verification
Verify that your application can retrieve the properties from one of the properties files contained within the Java archive (JAR).
Thread.currentThread().getContextClassLoader().getResource("my.properties");Thread.currentThread().getContextClassLoader().getResource("my.properties");Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.5. Removing custom modules from JBoss EAP Copy linkLink copied to clipboard!
You can remove any unnecessary modules from JBoss EAP in the following ways:
5.5.1. Removing a custom module manually Copy linkLink copied to clipboard!
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.
Procedure
Remove the module’s directory under
EAP_HOME/modules/, which includes itsmodule.xmlfile 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 themainslot.
5.5.2. Removing a custom module by using the management CLI Copy linkLink copied to clipboard!
You can remove a custom module using the module remove management CLI command.
Removing a custom module by using the management CLI command is provided as Technology Preview only. 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.
Prerequisites
- JBoss EAP is running.
Procedure
Launch the management CLI.
EAP_HOME/bin/jboss-cli.sh
$ EAP_HOME/bin/jboss-cli.shCopy to Clipboard Copied! Toggle word wrap Toggle overflow Use the
module removemanagement CLI command to remove the custom module.Syntax
module remove --name=MODULE_NAME
module remove --name=MODULE_NAMECopy to Clipboard Copied! Toggle word wrap Toggle overflow Use the
--slotargument if the module to remove is in a slot other thanmain.Example: remove MySQL module
module remove --name=com.mysql
module remove --name=com.mysqlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Execute
module --helpfor more details on using this command to add and remove modules.
5.6. Global modules in JBoss EAP Copy linkLink copied to clipboard!
You can define a list of global modules for JBoss EAP to add as dependencies to all JBoss EAP 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 8.1 Included Modules on the Red Hat Customer Portal. See the Dynamic module naming conventions for JBoss EAP 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>}]
/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>})
/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.
If you want a global module to be accessible by external dependencies, you must explicitly make it available. The following options are available to make the services in a global module available externally:
-
Add
services="import"to the module in yourjboss-deployment-structure.xml Add
services="true"to the global module definition./subsystem=ee:write-attribute(name=global-modules,value=[{name=module1,services=true}]/subsystem=ee:write-attribute(name=global-modules,value=[{name=module1,services=true}]Copy to Clipboard Copied! Toggle word wrap Toggle overflow Or, when adding multiple modules:
/subsystem=ee:write-attribute(name=global-modules,value=[{name=module1,services=true},{name=module2,services=false}]/subsystem=ee:write-attribute(name=global-modules,value=[{name=module1,services=true},{name=module2,services=false}]Copy to Clipboard Copied! Toggle word wrap Toggle overflow To add a new module to an existing list:
/subsystem=ee:list-add(name=global-modules,value={name=module1,services=true})/subsystem=ee:list-add(name=global-modules,value={name=module1,services=true})Copy to Clipboard Copied! Toggle word wrap Toggle overflow -
When defining the global module using the management console, make sure that the value of the Services property is
On.
5.7. Creating a global directory Copy linkLink copied to clipboard!
A global directory offers a better alternative to the global module approach. For example, if you want to change the name of a library listed in a global module, you must remove the global module, change the library’s name, and then add the library to a new global module. If you change the name of a library that is listed in the global directory, you only need to reload the server to make the library name change available for all deployments.
Using a global directory, you can do the following:
- Share multiple libraries across deployed applications.
- Maintain libraries by moving common frameworks, usually added to application libraries, to a common location.
When you create a global directory, the EE subsystem configures a global directory and then scans the directory to create a JBoss Modules module dependency. The module dependency includes the global directory libraries and JAR files. This module dependency also contains the following resource loaders:
- The path resource loader provides files as a resource to an application.
- The resource loader provides classes, contained in a JAR file, to an application.
The EE subsystem adds a module dependency as a system dependency on each deployed application.
Prerequisites
Create a standard directory on your operating system. This standard directory must contain all the JAR files and resources you need deployed to applications. This creates a directory tree.
Example of a common directory showing a list of common libraries that were copied to applications
/my-common-libs/log4j2.xml /my-common-libs/libs/log4j-api-2.14.1.jar /my-common-libs/libs/log4j-core-2.14.1.jar
/my-common-libs/log4j2.xml /my-common-libs/libs/log4j-api-2.14.1.jar /my-common-libs/libs/log4j-core-2.14.1.jarCopy to Clipboard Copied! Toggle word wrap Toggle overflow NoteSince the server deploys an application and loads the global directory, you cannot configure the global directory to override the server’s library versions. A global directory cannot replace libraries shipped with the server.
Procedure
Depending on your server setup, create a global directory. You can use the optional
relative-toattribute to set the global directory with a relative path.Example of creating a global directory on a standalone server
[standalone@localhost:9990 /] /subsystem=ee/global-directory=my-common-libs:add(path=my-common-libs, relative-to=jboss.home.dir)
[standalone@localhost:9990 /] /subsystem=ee/global-directory=my-common-libs:add(path=my-common-libs, relative-to=jboss.home.dir)Copy to Clipboard Copied! Toggle word wrap Toggle overflow Example of creating a global directory on a server in a managed domain
[domain@localhost:9990 /] /profile=default/subsystem=ee/global-directory=my-common-libs:add(path=my-common-libs, relative-to=jboss.server.data.dir)
[domain@localhost:9990 /] /profile=default/subsystem=ee/global-directory=my-common-libs:add(path=my-common-libs, relative-to=jboss.server.data.dir)Copy to Clipboard Copied! Toggle word wrap Toggle overflow For a server in a managed domain, you can add the global directory under a JBoss EAP profile, which is defined in
domain.xml, by using therelative-pathattribute. You can specify either a system path or a custom system path to thisrelative-toattribute.NoteWhen running a server in managed domain, you must ensure the contents of the global directory are consistent across all server instances. For example, each host must contain a local file system directory that includes the global directory contents.
Reload your server instance to activate the global directory.
You must reload the server, so the server can scan the contents of the directory tree alphabetically, including each subdirectory level, starting from the root directory. The server adds files from each directory level to the JBoss Modules module dependency in alphabetic order.
If you change the contents of the global directory, or you change or add JAR files in a global directory, you must reload the server to make the changes available to the deployed applications. For example, if you replace a JAR library in a global directory, reload the server to ensure it re-scans the global directory and updates the deployed applications with the changed JAR library.
5.8. Reading the current values of a global directory configuration Copy linkLink copied to clipboard!
You can read the current values of a global directory configuration by using the read-resource operation.
Procedure
Depending on your server setup, use the
read-resourceoperation to read the current values of your global directory configuration.Example output of reading the current values of a global directory configuration on a standalone server
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Example output of reading the current values of a global directory configuration on a server in a managed domain
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.9. Removing a global directory Copy linkLink copied to clipboard!
You can remove a global directory from your server configuration. This action removes only the global directory resource from the server configuration file and does not affect the underlying directory or its files.
Procedure
To remove a global directory from your standalone server, use the following command:
[standalone@localhost:9990 /] /subsystem=ee/global-directory=my-common-libs:remove()
[standalone@localhost:9990 /] /subsystem=ee/global-directory=my-common-libs:remove()Copy to Clipboard Copied! Toggle word wrap Toggle overflow To remove a global directory on a server in a managed domain, use the following command:
[domain@localhost:9990 /] /profile=default/subsystem=ee/global-directory=my-common-libs:remove()
[domain@localhost:9990 /] /profile=default/subsystem=ee/global-directory=my-common-libs:remove()Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.10. Subdeployment isolation configuration in JBoss EAP Copy linkLink copied to clipboard!
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.
5.10.1. Enabling subdeployment module isolation for all deployments Copy linkLink copied to clipboard!
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 Enterprise Archive (EAR) deployment.
Procedure
Use the following management CLI command to enable EAR subdeployment isolation:
/subsystem=ee:write-attribute(name=ear-subdeployments-isolated,value=true)
/subsystem=ee:write-attribute(name=ear-subdeployments-isolated,value=true)Copy to Clipboard Copied! Toggle word wrap Toggle overflow Subdeployments in an EAR will no longer be able to access resources from other subdeployments.
5.11. Defining an external JBoss EAP module directory Copy linkLink copied to clipboard!
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.
Procedure
Edit the startup configuration file.
-
When running as a standalone server, edit the
EAP_HOME/bin/standalone.conffile, orstandalone.conf.batfor Windows Server. -
When running in a managed domain, edit the
EAP_HOME/bin/domain.conffile, ordomain.conf.batfor Windows Server.
-
When running as a standalone server, edit the
Set the
JBOSS_MODULEPATHvariable, for example:JBOSS_MODULEPATH="/path/to/modules/directory/"
JBOSS_MODULEPATH="/path/to/modules/directory/"Copy to Clipboard Copied! Toggle word wrap Toggle overflow 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_MODULEPATHvariable:set "JBOSS_MODULEPATH /path/to/modules/directory/"
set "JBOSS_MODULEPATH /path/to/modules/directory/"Copy to Clipboard Copied! Toggle word wrap Toggle overflow To specify a list of directories use a semicolon (
;) to delimit the list of directories.
5.12. Dynamic module naming conventions for JBoss EAP Copy linkLink copied to clipboard!
JBoss EAP loads all deployments as modules, which are named according to the following conventions.
Deployments of Web Archive (WAR) and Java Archive (JAR) files are named using the following format:
deployment.DEPLOYMENT_NAME
deployment.DEPLOYMENT_NAMECopy to Clipboard Copied! Toggle word wrap Toggle overflow For example,
inventory.warandstore.jarwill have the module names ofdeployment.inventory.waranddeployment.store.jarrespectively.Subdeployments within an Enterprise Archive (EAR) are named using the following format:
deployment.EAR_NAME.SUBDEPLOYMENT_NAME
deployment.EAR_NAME.SUBDEPLOYMENT_NAMECopy to Clipboard Copied! Toggle word wrap Toggle overflow For example, the subdeployment of
reports.warwithin the enterprise archiveaccounts.earwill have the module name ofdeployment.accounts.ear.reports.war.