Adventures in JDBC and the PostgreSQL JDBC driver: Part 7 - The JDBC driver loading process in Wildfly
Adventures in JDBC and the PostgreSQL JDBC driver: Part 7 - The JDBC driver loading process in Wildfly
In the previous article, we have learned how to add a JDBC database driver module into Wildfly, and how to configure a datasource to use hte driver. In this article, let’s see the JDBC driver loading process in Wildfly.
In Wildfly source code (See https://github.com/wildfly/wildfly), the connector
module contains the datasources
subsystem. Here is the screenshot of the source code structure of wildfly
:
The above screenshot shows the datasources
subsystem. In the subsystem, we can find the org.jboss.as.connector.subsystems.datasources.JdbcDriverAdd
class, and here is its class diagram:
The above diagram shows the methods in JdbcDriverAdd
class. Firstly we need to check the performRuntime(...)
method. Here is the sequence diagram of the method:
From the above diagram, we can find out two things: Firstly the method will try to fetch multiple values defined by the users. For example, there are DRIVER_CLASS_NAME
and DRIVER_XA_DATASOURCE_CLASS_NAME
that users can set in the server configuration file.
Another thing we can see from the above diagram is that the method will try to find the JDBC driver class automatically if driverClass
is null, and it will invoke the loadService(Driver.class)
method for this task.
Let check the above notes one by one. First let’s see the origin class of the DRIVER_CLASS_NAME
and DRIVER_XA_DATASOURCE_CLASS_NAME
constants. They are defined in the org.jboss.as.connector.subsystems.datasources.Constants
class, and here is its class diagram:
The above diagram just show part of the whole class because it is too big. You can check the code directly to get all the constants defined in the class. These constants can mostly be defined in the server configuration file. For example, we can see the string value of DATASOURCE_DRIVER_CLASS_NAME
is driver-class
. Actually we can configure this in the standalone/configuration/standalone.xml
:
<driver name="postgresql" module="org.postgresql">
<driver-class>org.postgresql.Driver</driver-class>
</driver>
But in the last article, we didn’t configure the driver-class
, but Wildfly can still load the driver class correctly. This is because the loadService(...)
method will help us to find the driver class in the module. Here is the relative code in the method:
if (driverClassName == null) {
final ServiceLoader<Driver> serviceLoader = module.loadService(Driver.class);
boolean driverLoaded = false;
if (serviceLoader != null) {
for (Driver driver : serviceLoader) {
startDriverServices(target, moduleId, driver, driverName, majorVersion, minorVersion, dataSourceClassName, xaDataSourceClassName);
driverLoaded = true;
//just consider first definition and create service for this. User can use different implementation only
// w/ explicit declaration of driver-class attribute
break;
}
}
...
From the above code, we can see the module.loadService(Driver.class)
method will try to find the class that implements the Driver.class
interface from the module. If it finds the driver classes, it will install them one by one by using the startDriverServices(...)
method.
To verify our analysis, we can set a breakpoint in JdbcDriverAdd
class. To understand how to debug the Wildfly startup process, you need to read these two articles firstly:
I have introduced the techniques to debug the Wildfly server. I used the methods introduced in above articles to catch the startup process by setting the breakpoint in JdbcDriverAdd
class, and then start the Wildfly server in debug mode. Here is what I get in my IntelliJ IDEA environment:
The above screenshot shows that during the Wildfly server startup process, it will use the JdbcDriverAdd
to load the drivers defined in configuration file. Because we didn’t define the driver-class
in standalone.xml
, so it goes into the logic to find the driver class automatically.
Now I step the code to the startDriverServices(...)
method, and here is the screenshot:
From the above screenshot, we can see Wildfly has found the PostgreSQL JDBC driver, which is org.postgresql.Driver
.
Now let’s go a little big deeper into the startDriverServices(...)
method. I stepped into the method and here is the screenshot:
From the above screenshot, we can see that Wildfly will create a DriverService
for the driver and install it into its micro container. I won’t dive into deeper details in this article, but you may want to learn about the micro container design of Wildfly. If so, you can read these articles:
- An introduction to the JBoss Modular Service Container: Part 1 - Basic architecture of the container
- DRAFT - An introduction to the JBoss Modular Service Container: Part 2 - Transaction layer
The above articles will give you an introduction to the Wildfly micro container design.
In this article, we have checked how does Wildfly load the JDBC driver. In next article, I will introduce the Wildfly datasource loading process.