There was no particular request, but I will write a continuation of Try moving WildFly Wild. This time is about class loading. This time we will use the latest WildFly-15.0.0.Final
as of December 2018.
The jars included in WildFly are managed with the idea of modules. There are two types of modules: static modules and dynamic modules.
** 1. Static module ** Refers to the jar installed under the modules directory. You can also put a custom module jar created by the user. ** 2. Dynamic module ** Refers to a jar or class in a war or ear file.
If you want to use a static module from your application, you need to put a deployment descriptor file jboss-deployment-structure.xml
in your application and write a ** dependency ** that declares that you will use this module. There is.
However, some static modules have ** implicit ** dependencies ** [^ 2], which you don't need to write in jboss-deployment-structure.xml
. Will be loaded into.
Classes (modules) are loaded in priority, and if there are classes with the same name in the same package, the one with the highest priority loaded first will be used.
Each module is loaded in the following order [^ 1].
jboss-deployment-structure.xml
I'm skeptical so I'll try to see if it's true.
Check using ʻorg.apache.log4j` in the Implicit Dependency module. First, prepare the following jsp.
logger.jsp
<%@page contentType="text/html; charset=UTF-8" %>
<html>
<body>
<%
Object logger = org.apache.log4j.Logger.getLogger("test");
out.print(logger.getClass().getName());
out.print("<br>");
out.print(logger.toString());
%>
</body>
</html>
Create a fake Logger class like the one below, compile it, and jar it into classloadTestInModules.jar. Install this as a ** static module ** under the modules directory.
Logger.java
package org.apache.log4j;
public class Logger {
public static String getLogger(String name) {
//org.apache.log4j.Returns the string module instead of the Logger class.
return "module";
}
}
Then make a few changes and compile it in the same way into classloadTestInWar.jar. This is included in the application (war) as a ** dynamic module **.
Logger.java
package org.apache.log4j;
public class Logger {
public static String getLogger(String name) {
//org.apache.log4j.Returns the string war instead of the Logger class.
return "war";
}
}
Install the created classloadTestInModules.jar under the modules directory.
Create the following directories. wildfly-15.0.0.Final/modules/system/layers/base/test wildfly-15.0.0.Final/modules/system/layers/base/test/test wildfly-15.0.0.Final/modules/system/layers/base/test/test/main
Place classloadTestInModules.jar below. wildfly-15.0.0.Final/modules/system/layers/base/test/test/main
Create module.xml
with the following contents. test.test
is the name of this module.
module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module name="test.test" xmlns="urn:jboss:module:1.7">
<resources>
<resource-root path="classloadTestInModules.jar"/>
</resources>
</module>
Then place logger.jsp
directly under classloadTestInWar.jar
war in WEB-INF / lib
of the appropriate application helloworld.war
in wildfly-15.0.0.Final / standalone / deployments
.. You're ready to create and deploy the deployment marker file helloworld.war.dodeploy
.
Go to http: //localhost:8080/helloworld/logger.jsp
in your browser.
It was displayed as follows. Now that the Logger class object is back, you can see that the implicit dependency module class is back.
org.apache.log4j.Logger org.apache.log4j.Logger@62af7a58
It worked as expected: clap:
Let's put in a setting that wants to use a user-specified module instead of an implicit dependency module. Create a deployment descriptor file jboss-deployment-structure.xml
in helloworld.war / META-INF
with the following content:
jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.apache.log4j" />
</exclusions>
<dependencies>
<module name="test.test"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
<dependencies>
is the name of the static module you want to use. <exclusions>
is the name of the implicit dependency module you don't want to use. Now go to http: // localhost: 8080 / helloworld / logger.jsp
again to create and redeploy the helloworld.war.dodeploy
file.
It was displayed as follows. The String type with the content module is returned, so you can see that the class of the installed test.test module was used.
java.lang.String module
It worked as expected: clap:
Then set it to use only dynamic modules. Modify jboss-deployment-structure.xml
to the following: Leave only the settings that exclude the implicit dependency module.
jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.apache.log4j" />
</exclusions>
</deployment>
</jboss-deployment-structure>
Create and redeploy the helloworld.war.dodeploy
file again and access http: // localhost: 8080 / helloworld / logger.jsp
.
It was displayed as follows. Since the String type with the content of war is returned, we can see that the class of the dynamic module classloadTestInWar.jar in WEB-INF / lib was used.
java.lang.String war
It worked as expected: clap:
If WildFly is not aware of the priority of loading classes, if the application you create contains the same module as the implicit dependency module, you may suffer from unexpected errors due to different versions etc. Please note that there is.
[^ 1]: Class Loading Priority ⇒ 1.3. Class Loading Precedence [^ 2]: List of modules with implicit dependencies ⇒ 2.3. Which are the implicit module dependencies? Chapter 6 JBoss EAP Class Loading