Class loading in AS7 is considerably different to previous versions of JBoss AS. Class loading is based on the JBoss Modules project. Instead of the more familiar hierarchical class loading environment, AS7's class loading is based on modules that have to define explicit dependencies on other modules. Deployments in AS7 are also modules, and do not have access to classes that are defined in jars in the application server unless an explicit dependency on those classes is defined.
Module names for top level deployments follow the format deployment.myarchive.war while sub deployments are named like deployment.myear.ear.mywar.war.
This means that it is possible for a deployment to import classes from another deployment using the other deployments module name, the details of how to add an explicit module dependency are explained below.
Even though in AS7 modules are isolated by default, as part of the deployment process some dependencies on modules defined by the application server are set up for you automatically. For instance, if you are deploying a Java EE application a dependency on the Java EE API's will be added to your module automatically. Similarly if your module contains a beans.xml file a dependency on Weld will be added automatically, along with any supporting modules that weld needs to operate.
For a complete list of the automatic dependencies that are added see this page.
Automatic dependencies can be excluded through the use of jboss-deployment-structure.xml.
A common source of errors in Java applications is including API classes in a deployment that are also provided by the container. This can result in multiple versions of the class being created and the deployment failing to deploy properly. To prevent this in AS7, module dependencies are added in a specific order that should prevent this situation from occurring.
In order of highest priority to lowest priority
- System Dependencies - These are dependencies that are added to the module automatically by the container, including the Java EE api's.
- User Dependencies - These are dependencies that are added through jboss-deployment-structure.xml or through the Dependencies: manifest entry.
- Local Resource - Class files packaged up inside the deployment itself, e.g. class files from WEB-INF/classes or WEB-INF/lib of a war.
- Inter deployment dependencies - These are dependencies on other deployments in an ear deployment. This can include classes in an ear's lib directory, or classes defined in other ejb jars.
The war is considered to be a single module, so classes defined in WEB-INF/lib are treated the same as classes in WEB-INF/classes. All classes packaged in the war will be loaded with the same class loader.
Ear deployments are multi-module deployments. This means that not all classes inside an ear will necessarily have access to all other classes in the ear, unless explicit dependencies have been defined. By default the EAR/lib directory is a single module, and every WAR or EJB jar deployment is also a separate module. Sub deployments (wars and ejb-jars) always have a dependency on the parent module, which gives them access to classes in EAR/lib, however they do not always have an automatic dependency on each other. This behaviour is controlled via the ear-subdeployments-isolated setting in the ee subsystem configuration:
By default this is set to false, which allows the sub-deployments to see classes belonging to other sub-deployments within the .ear.
For example, consider the following .ear deployment:
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes belonging to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from ejb2.jar (and vice-versa).
|The ear-subdeployments-isolated element value has no effect on the isolated classloader of the .war file(s). i.e. irrespective of whether this flag is set to true or false, the .war within a .ear will have a isolated classloader and other sub-deployments within that .ear will not be able to access classes from that .war. This is as per spec.|
If the ear-subdeployments-isolated is set to true then no automatic module dependencies between the sub-deployments are set up. User must manually setup the dependency with Class-Path entries, or by setting up explicit module dependencies.
The Java EE specification says that portable applications should not rely on sub deployments having access to other sub deployments unless an explicit Class-Path entry is set in the MANIFEST.MF. So portable applications should always use Class-Path entry to explicitly state their dependencies.
|It is also possible to override the ear-subdeployments-isolated element value at a per deployment level. See the section on jboss-deployment-structure.xml below.|
Dependencies: Manifest Entries
Deployments (or more correctly modules within a deployment) may set up dependencies on other modules by adding a Dependencies: manifest entry. This entry consists of a comma separated list of module names that the deployment requires. The available modules can be seen under the modules directory in the application server distribution. For example to add a dependency on javassist and apache velocity you can add a manifest entry as follows:
Dependencies: org.javassist export,org.apache.velocity export services,org.antlr
Each dependency entry may also specify some of the following parameters by adding them after the module name:
- export This means that the dependencies will be exported, so any module that depends on this module will also get access to the dependency.
- services By default items in META-INF of a dependency are not accessible, this makes items from META-INF/services accessible so services in the modules can be loaded.
- optional If this is specified the deployment will not fail if the module is not available.
- annotations If a jandex index has be created for the module these annotations will be merged into the deployments annotation index. The Jandex index can be generated using the Jandex ant task , and must be named META-INF/jandex.idx. Note that it is not necessary to break open the jar being indexed to add this to the modules class path, a better approach is to create a jar containing just this index, and adding it as an additional resource root in the module.xml file.
|Adding a dependency to all modules in an EAR|
Using the export parameter it is possible to add a dependency to all sub deployments in an ear. If a module is exported from a Dependencies: entry in the top level of the ear (or by a jar in the ear/lib directory) it will be available to all sub deployments as well.
|To generate a MANIFEST.MF entry when using maven put the following in your pom.xml:
If your deployment is a jar you must use the maven-jar-plugin rather than the maven-war-plugin.
It is also possible to add module dependencies on other modules inside the deployment using the Class-Path manifest entry. This can be used within an ear to set up dependencies between sub deployments, and also to allow modules access to additional jars deployed in an ear that are not sub deployments and are not in the EAR/lib directory. If a jar in the EAR/lib directory references a jar via Class-Path: then this additional jar is merged into the parent ear's module, and is accessible to all sub deployments in the ear.
It is also possible to set up global modules, that are accessible to all deployments. This is done by modifying the configuration file (standalone/domain.xml).
For example, to add javassist to all deployments you can use the following XML:
Note that the slot field is optional and defaults to main.
jboss-deployment-structure.xml is a JBoss specific deployment descriptor that can be used to control class loading in a fine grained manner. It should be placed in the top level deployment, in META-INF (or WEB-INF for web deployments). It can do the following:
- Prevent automatic dependencies from being added
- Add additional dependencies
- Define additional modules
- Change an EAR deployments isolated class loading behaviour
- Add additional resource roots to a module
|Exclude Subsystem Dependency|
To exclude subsystem within a module, you will will want to exclude the entire module and then add back in each of the subsystems that make the module minus the subsystem that needs to be excluded.
e.g. exclude javax.ws.rs.api from javaee.api module
An example of a complete jboss-deployment-structure.xml file for an ear deployment is as follows:
|The xsd for jboss-deployment-structure.xml is available at http://www.jboss.org/schema/jbossas/jboss-deployment-structure-1_0.xsd|