WildFly / JBoss EAP classloading explained
Setting up global modules
This option resembles a bit to the old AS approach for loading common libraries, where you used to place them in the folder JBOSS_HOME/common/lib.
If you define a section named global-modules within your standalone.xml/domain.xml, then you will make the module accessible to other AS modules. For example, instead of declaring a dependency on log4j, you could alternatively use the following section:
<subsystem xmlns="urn:jboss:domain:ee:1.0"> <global-modules> <module name="org.apache.log4j" /> </global-modules> </subsystem>
Although this approach is not generally recommended, as it brings us back to a concept of monolithic application server, it can still yield some benefits. For example, if you are migrating some older applications, and you don't want or simply cannot specify dependencies into the archive.
Advanced deployment strategies
What we have learnt, so far, can be enough for configuring many kind of applications. If you are using a complex archive configuration, such as an EAR archive with several modules and dependencies, it would prove useful to define your classloading strategy in a single file.
The configuration file jboss-deployment-structure.xml can do that exactly this. The advantage of using this file are many:
- You can define the dependencies of all application modules in a single file
- You can load the modules classes using a finer grained manner, by including/excluding all or part of modules
- You can define class loading isolation policy for your applications packaged in an Enterprise archive
Let's see with some practical examples what jboss-deployment-structure.xml can do for you.
Setting up a single module dependency
We have already learnt how to activate a log4j dependency, using the Dependencies attribute in the archive's MANIFEST file. The same effect can be achieved by using the jboss-deployment-structure.xml file. Let's recap the archive structure, which is basically made up of a Web application named WebApp.war.
As you can see, the file jboss-deployment-structure.xml needs to be placed within the META-INF folder of the EAR.
Here's its content:
<jboss-deployment-structure> <sub-deployment name="WebApp.war"> <dependencies> <module name="org.apache.log4j" /> </dependencies> </sub-deployment> </jboss-deployment-structure>
The file jboss-deployment-structure is not for exclusive use of EARs; as a matter of fact, you could deploy it also within the WebApp application, by placing it within the WEB-INF folder of the archive. It is, however, applicable only as top-level archive. Thus if a jboss-deployment-structure.xml is placed in the WAR's WEB-INF folder and the WAR is packaged in a EAR archive, then the jboss-deployment-structure.xml is ignored.
The relevant part of this file is the sub-deployment element, which references the Web application, including within it, the dependencies element. The expected outcome is that the application server will trigger the dependency to log4j Api, which will be therefore visible by our Web application.
Excluding the server automatic dependencies
Earlier in this chapter, we have shown how the application server is able to trigger some dependencies, automatically, when some conditions are met. For example, if you deploy a JSF application (containing the faces-config.xml file), then the JSF 2.1 Api implementation is automatically added.
This might not be always the desired option, for example, because you want to provide another release implementation for that module. You can easily achieve this using the exclusion section in the jboss-deployment-structure.xml, as shown here:
<jboss-deployment-structure> <deployment> <exclusions> <module name="javax.faces.api" /> <module name="com.sun.jsf-impl" /> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> <module name="com.sun.jsf-impl" slot="1.2"/> </dependencies> </deployment> </jboss-deployment-structure>
Notice in the dependencies section, we have added our alternate JSF 1.2 implementation, which will be used by your application. Actually this JSF implementation ships with the application server distribution along with the javax.faces.api module path, under the folder specified by the slot attribute. In our case, this corresponds to JBOSS_HOME/modules/javax/faces/api/1.2 folder.