Last Modified 2019.9.19

Java 9 Module

This article covers a Java 9 module example. You will modify the custom connection pool with the Java 9 module example. We recommend that you read the following articles before you begin.

1st Module

Create a new Java Project in Eclipse. It doesn't matter what you name your project. Create the following classes in your project.

DBConnectionPool.java
package net.java_school.db.dbpool; 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DBConnectionPool {
	private static final Logger logger = Logger.getLogger(DBConnectionPool.class.getName());
	
	// Number of connections currently in use
	private int checkedOut;

	// Free Connection List
	private Vector<Connection> freeConnections = new Vector<Connection>();

	// Maximum number of connections
	private int maxConn;

	// Waiting time (maximum time to wait when there is no connection in the pool)
	private int maxWait;

	// Connection Pool Name
	private String poolName;

	// DB Password
	private String passwd;

	// DB URL
	private String URL;

	// DB UserID
	private String userID;

	// Constructor
	public DBConnectionPool(String poolName, 
			String URL, 
			String userID, 
			String passwd, 
			int maxConn, 
			int initConn, 
			int waitTime) {

		this.poolName = poolName;
		this.URL = URL;
		this.userID = userID;
		this.passwd = passwd;
		this.maxConn = maxConn;
		this.maxWait = waitTime;

		for (int i = 0; i < initConn; i++) {
			freeConnections.addElement(newConnection());
		}
	}

	// Returning Connection
	// @param con : Connection to return
	public synchronized void freeConnection(Connection con) {
		freeConnections.addElement(con);
		checkedOut--;
		//Notify thread waiting to get Connection
		notifyAll();
	}

	// Get Connection
	@SuppressWarnings("resource")
	public synchronized Connection getConnection() {
		Connection con = null;
		//If Connection is in Free List, get the first of List
		if (freeConnections.size() > 0) {
			con = (Connection) freeConnections.firstElement();
			freeConnections.removeElementAt(0);

			try {
				//If the connection is closed by the DBMS, request again
				if (con.isClosed()) {
					logger.log(Level.SEVERE, "Removed bad connection from " + poolName);
					con = getConnection();
				}
			} //If strange connection occurs, request again
			catch (SQLException e) {
				logger.log(Level.SEVERE, "Removed bad connection from " + poolName);
				con = getConnection();
			}
		} //If Connection is not in Free List, create new
		else if (maxConn == 0 || checkedOut < maxConn) {
			con = newConnection();
		}

		if (con != null) {
			checkedOut++;
		}

		return con;
	}

	// Get Connection
	// @param timeout : Maximum Wait Time to Obtain a Connection
	public synchronized Connection getConnection(long timeout) {
		long startTime = new Date().getTime();
		Connection con;
		while ((con = getConnection()) == null) {
			try {
				wait(timeout * maxWait);
			} catch (InterruptedException e) {}
			if ((new Date().getTime() - startTime) >= timeout) {
				//Wait timeout
				return null;
			}
		}

		return con;
	}

	// Get Connection
	private Connection newConnection() {
		Connection con = null;
		try {
			if (userID == null) {
				con = DriverManager.getConnection(URL);
			} else {
				con = DriverManager.getConnection(URL, userID, passwd);
			}
			logger.info("Created a new connection in pool " + poolName);
		} catch (SQLException e) {
			StringBuffer sb = new StringBuffer();
			sb.append("Can't create a new connection for ");
			sb.append(URL);
			sb.append(" user: ");
			sb.append(userID);
			sb.append(" passwd: ");
			sb.append(passwd);
			logger.log(Level.SEVERE, sb.toString());
			return null;
		}

		return con;
	}

}
DBConnectionPoolManager.java
package net.java_school.db.dbpool;

import java.sql.Connection;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DBConnectionPoolManager {
	private static final Logger logger = Logger.getLogger(DBConnectionPoolManager.class.getName());
	
	// To apply the singleton pattern to the DBConnectionPoolManager (keep only one instance), declare it as static
	static private DBConnectionPoolManager instance;
	private Vector<String> drivers = new Vector<String>();
	private Hashtable<String, DBConnectionPool> pools = new Hashtable<String, DBConnectionPool>();

	// Obtaining instance of DBConnectionPoolManager
	// @return DBConnectionManger
	static synchronized public DBConnectionPoolManager getInstance() {
		if (instance == null) {
			instance = new DBConnectionPoolManager();
		}

		return instance;
	}

	// Default Constructor
	private DBConnectionPoolManager() {}

	// Send current Connection to Free Connection List
	// @param name : Pool Name
	// @param con : Connection
	public void freeConnection(String name, Connection con) {
		DBConnectionPool pool = (DBConnectionPool) pools.get(name);
		if (pool != null) {
			pool.freeConnection(con);
		}

		logger.info("One Connection of " + name + " was freed");
	}

	// Obtain Open Connection. Creates a new connection if there are no open connections and the maximum number of connections has not been reached.
	// Waits for the default wait time when there are no open connections currently and the maximum number of connections is in use.
	// @param name : Pool Name
	// @return Connection : The connection or null
	public Connection getConnection(String name) {
		DBConnectionPool pool = (DBConnectionPool) pools.get(name);
		if (pool != null) {
			return pool.getConnection(10);
		}
		return null;
	}

	// Create a Connection Pool
	// @param poolName : Name of Pool to create
	// @param url : DB URL
	// @param userID : DB UserID
	// @param passwd : DB Password
	private void createPools(String poolName, 
			String url, 
			String userID,
			String passwd, 
			int maxConn, 
			int initConn, 
			int maxWait) {

		DBConnectionPool pool = new DBConnectionPool(poolName, url, userID, passwd, maxConn, initConn, maxWait);
		pools.put(poolName, pool);
		logger.info("Initialized pool " + poolName);
	}

	// Initialization
	public void init(String poolName, 
			String driver, 
			String url,
			String userID, 
			String passwd, 
			int maxConn, 
			int initConn, 
			int maxWait) {

		loadDrivers(driver);
		createPools(poolName, url, userID, passwd, maxConn, initConn, maxWait);
	}

	// JDBC Driver Loading
	// @param driverClassName : The JDBC driver for the DB you want to use.
	private void loadDrivers(String driverClassName) {
		try {
			Class.forName(driverClassName);
			drivers.addElement(driverClassName);
			logger.info("Registered JDBC driver " + driverClassName);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Can't register JDBC driver: " + driverClassName);
		}
	}

	public Hashtable<String,DBConnectionPool> getPools() {
		return pools;
	}
	
	public int getDriverNumber() {
		return drivers.size();
	}

}
ConnectionManager.java
package net.java_school.db.dbpool;

import java.sql.Connection;

public abstract class ConnectionManager {

	protected DBConnectionPoolManager poolManager;
	protected String poolName;
	
	public ConnectionManager() {
		this.poolManager = DBConnectionPoolManager.getInstance();
	}
	
	public Connection getConnection() {
		return (poolManager.getConnection(poolName));
	}

	public void freeConnection(Connection con) {
		poolManager.freeConnection(poolName, con);
	}
	
	public abstract void initPoolManager(String poolName, String driver, String url, 
			String userID, String passwd, int maxConn, int initConn, int maxWait);
	
	public int getDriverNumber() {
        return poolManager.getDriverNumber();
    }

}

The module-info.java is a module descriptor source file. Create this file in the src directory.

module-info.java
module net.java_school.db.dbpool {
	requires java.logging;
	requires transitive java.sql;
	
	exports net.java_school.db.dbpool;
}

2nd Module

Create a new Java Project in Eclipse. Create the following classes in your project.

OracleConnectionManager.java
package net.java_school.db.dbpool.oracle;

import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.java_school.db.dbpool.ConnectionManager;

public class OracleConnectionManager extends ConnectionManager {
	private static final Logger logger = Logger.getLogger(OracleConnectionManager.class.getName());

	public OracleConnectionManager() {
		this.poolName = "oracle";
		String configFile = "oracle.properties";
		
		try {
			Properties prop = readProperties(configFile);
			String dbServer = prop.getProperty("dbServer");
			String port = prop.getProperty("port");
			String dbName = prop.getProperty("dbName");
			String userID = prop.getProperty("userID");
			String passwd = prop.getProperty("passwd");
			int maxConn = Integer.parseInt(prop.getProperty("maxConn"));
			int initConn = Integer.parseInt(prop.getProperty("initConn"));
			int maxWait = Integer.parseInt(prop.getProperty("maxWait"));
			String driver = "oracle.jdbc.driver.OracleDriver";
			String JDBCDriverType = "jdbc:oracle:thin";
			String url = JDBCDriverType + ":@" + dbServer + ":" + port + ":" + dbName;
			initPoolManager(this.poolName, driver, url, userID, passwd, maxConn, initConn, maxWait);
		} catch (IOException e) {
			logger.log(Level.SEVERE, "Error reading properties of " + configFile);
			throw new RuntimeException(e);
		}

	}

	protected synchronized Properties readProperties(String configFile) throws IOException {
		ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
		URL url = currentThreadClassLoader.getResource(configFile);
		Properties properties = new Properties();
		properties.load(url.openStream());
		return properties;
	}

	@Override
	public void initPoolManager(String poolName, String driver, String url, 
			String userID, String passwd, int maxConn, int initConn, int maxWait) {
		this.poolManager.init(poolName, driver, url, userID, passwd, maxConn, initConn, maxWait);
	}

}
module-info.java
module net.java_school.db.dbpool.oracle {
	requires net.java_school.db.dbpool;
	
	exports net.java_school.db.dbpool.oracle;
	provides net.java_school.db.dbpool.ConnectionManager 
		with net.java_school.db.dbpool.oracle.OracleConnectionManager;
}

Add ojdbc6.jar to the project's build path using Add External JARs... button.
build-path-for-oracle The second module depends on the first module.
With the help of Eclipse's code assist feature, you can easily set up dependencies. Build-Path-of-Project

Create a properties file for the Oracle database in the src folder.

oracle.properties
############################################ 
# Database Connection Properties for Oracle
############################################ 

# Database Server Name OR IP address 
dbServer = 127.0.0.1

# The port number your DB server listents to. 
port = 1521

# Database Name 
dbName = XE

# Database User 
userID = scott

# Database Password 
passwd = tiger

# Maximum Connection Number 
maxConn = 20

# Inital Connection Number 
initConn = 5

# Maximum Wait Time 
maxWait = 5

3rd Module

Create a new Java Project in Eclipse. Create the following classes in your project.

MySqlConnectionManager.java
package net.java_school.db.dbpool.mysql;

import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.java_school.db.dbpool.ConnectionManager;

public class MySqlConnectionManager extends ConnectionManager {
	
	private static final Logger logger = Logger.getLogger(MySqlConnectionManager.class.getName());

	public MySqlConnectionManager() {
		this.poolName = "mysql";
		String configFile = "mysql.properties";
		
		try {
			Properties prop = readProperties(configFile);
			String dbServer = prop.getProperty("dbServer");
			String port = prop.getProperty("port");
			String dbName = prop.getProperty("dbName");
			String userID = prop.getProperty("userID");
			String passwd = prop.getProperty("passwd");
			int maxConn = Integer.parseInt(prop.getProperty("maxConn"));
			int initConn = Integer.parseInt(prop.getProperty("initConn"));
			int maxWait = Integer.parseInt(prop.getProperty("maxWait"));
			String driver = "com.mysql.jdbc.Driver";
			String JDBCDriverType = "jdbc:mysql";
			String url = JDBCDriverType + "://" + dbServer + ":" + port + "/" + 
				dbName + "?useUnicode=yes&characterEncoding=UTF-8";
			initPoolManager(this.poolName, driver, url, userID, passwd, maxConn, initConn, maxWait);
		} catch (IOException e) {
			logger.log(Level.SEVERE, "Error reading properties of " + configFile);
			throw new RuntimeException(e);
		}

	}
	
	protected synchronized Properties readProperties(String configFile) throws IOException {
		ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
		URL url = currentThreadClassLoader.getResource(configFile);
		Properties properties = new Properties();
		properties.load(url.openStream());
		return properties;
	}

	@Override
	public void initPoolManager(String poolName, String driver, String url, 
			String userID, String passwd, int maxConn, int initConn, int maxWait) {
		this.poolManager.init(poolName, driver, url, userID, passwd, maxConn, initConn, maxWait);
	}

}

Create a properties file for the MySQL database in the src folder.

mysql.properties
############################################ 
# Database Connection Properties for MySQL
############################################ 

# Database Server Name OR IP address 
dbServer = localhost

# The port number your DB server listents to. 
port = 3306

# Database Name 
dbName = xe

# Database User 
userID = scott

# Database Password 
passwd = tiger

# Maximum Connection Number 
maxConn = 20

# Inital Connection Number 
initConn = 5

# Maximum Wait Time 
maxWait = 5

Create a MySQL user and database.

mysql --user=root --password mysql

create user 'scott'@'%' identified by 'tiger';
grant all privileges on *.* to 'scott'@'%';

create database xe;
exit;
mysql --user=scott --password xe

CREATE TABLE DEPT (
    DEPTNO DECIMAL(2),
    DNAME VARCHAR(14),
    LOC VARCHAR(13),
    CONSTRAINT PK_DEPT PRIMARY KEY (DEPTNO) 
);
CREATE TABLE EMP (
    EMPNO DECIMAL(4),
    ENAME VARCHAR(10),
    JOB VARCHAR(9),
    MGR DECIMAL(4),
    HIREDATE DATE,
    SAL DECIMAL(7,2),
    COMM DECIMAL(7,2),
    DEPTNO DECIMAL(2),
    CONSTRAINT PK_EMP PRIMARY KEY (EMPNO),
    CONSTRAINT FK_DEPTNO FOREIGN KEY (DEPTNO) REFERENCES DEPT(DEPTNO)
);
CREATE TABLE SALGRADE ( 
    GRADE TINYINT,
    LOSAL SMALLINT,
    HISAL SMALLINT 
);
INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');
INSERT INTO EMP VALUES (7369,'SMITH','CLERK',7902,STR_TO_DATE('17-12-1980','%d-%m-%Y'),800,NULL,20);
INSERT INTO EMP VALUES (7499,'ALLEN','SALESMAN',7698,STR_TO_DATE('20-2-1981','%d-%m-%Y'),1600,300,30);
INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698,STR_TO_DATE('22-2-1981','%d-%m-%Y'),1250,500,30);
INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839,STR_TO_DATE('2-4-1981','%d-%m-%Y'),2975,NULL,20);
INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN',7698,STR_TO_DATE('28-9-1981','%d-%m-%Y'),1250,1400,30);
INSERT INTO EMP VALUES (7698,'BLAKE','MANAGER',7839,STR_TO_DATE('1-5-1981','%d-%m-%Y'),2850,NULL,30);
INSERT INTO EMP VALUES (7782,'CLARK','MANAGER',7839,STR_TO_DATE('9-6-1981','%d-%m-%Y'),2450,NULL,10);
INSERT INTO EMP VALUES (7788,'SCOTT','ANALYST',7566,STR_TO_DATE('13-7-1987','%d-%m-%Y')-85,3000,NULL,20);
INSERT INTO EMP VALUES (7839,'KING','PRESIDENT',NULL,STR_TO_DATE('17-11-1981','%d-%m-%Y'),5000,NULL,10);
INSERT INTO EMP VALUES (7844,'TURNER','SALESMAN',7698,STR_TO_DATE('8-9-1981','%d-%m-%Y'),1500,0,30);
INSERT INTO EMP VALUES (7876,'ADAMS','CLERK',7788,STR_TO_DATE('13-7-1987', '%d-%m-%Y'),1100,NULL,20);
INSERT INTO EMP VALUES (7900,'JAMES','CLERK',7698,STR_TO_DATE('3-12-1981','%d-%m-%Y'),950,NULL,30);
INSERT INTO EMP VALUES (7902,'FORD','ANALYST',7566,STR_TO_DATE('3-12-1981','%d-%m-%Y'),3000,NULL,20);
INSERT INTO EMP VALUES (7934,'MILLER','CLERK',7782,STR_TO_DATE('23-1-1982','%d-%m-%Y'),1300,NULL,10);
INSERT INTO SALGRADE VALUES (1,700,1200);
INSERT INTO SALGRADE VALUES (2,1201,1400);
INSERT INTO SALGRADE VALUES (3,1401,2000);
INSERT INTO SALGRADE VALUES (4,2001,3000);
INSERT INTO SALGRADE VALUES (5,3001,9999);
COMMIT;
exit;
module-info.java
module net.java_school.db.dbpool.mysql {
	requires net.java_school.db.dbpool;
	
	exports net.java_school.db.dbpool.mysql;
	provides net.java_school.db.dbpool.ConnectionManager 
		with net.java_school.db.dbpool.mysql.MySqlConnectionManager;
}

Add the MySQL JDBC driver file using the Add External JARs... button.
build-path-for-mysql

4th Module

Create a new Java Project in Eclipse. Create the following classes in your project.

GetEmp.java
package net.java_school.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import net.java_school.db.dbpool.mysql.MySqlConnectionManager;
import net.java_school.db.dbpool.oracle.OracleConnectionManager;

public class GetEmp {

	public static void main(String[] args) {

		OracleConnectionManager oracleConnectionManager = new OracleConnectionManager();
		
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;

		String sql = "SELECT * FROM emp";

		try {
			con = oracleConnectionManager.getConnection();
			stmt = con.prepareStatement(sql);
			rs = stmt.executeQuery();

			while (rs.next()) {
				String empno = rs.getString(1);
				String ename = rs.getString(2);
				String job = rs.getString(3);
				String mgr = rs.getString(4);
				String hiredate = rs.getString(5);
				String sal = rs.getString(6);
				String comm = rs.getString(7);
				String depno = rs.getString(8);

				System.out.println(empno + " : " + ename + " : " + job + " : " + 
					mgr + " : " + hiredate + " : " + sal + " : " + comm + " : " + depno);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
			} catch (SQLException e) {}
			try {
				stmt.close();
			} catch (SQLException e) {}
			oracleConnectionManager.freeConnection(con);
		}
		
		MySqlConnectionManager mysqlConnectionManager = new MySqlConnectionManager();
		
		con = null;
		stmt = null;
		rs = null;

		sql = "SELECT * FROM EMP";

		try {
			con = mysqlConnectionManager.getConnection();
			stmt = con.prepareStatement(sql);
			rs = stmt.executeQuery();

			while (rs.next()) {
				String empno = rs.getString(1);
				String ename = rs.getString(2);
				String job = rs.getString(3);
				String mgr = rs.getString(4);
				String hiredate = rs.getString(5);
				String sal = rs.getString(6);
				String comm = rs.getString(7);
				String depno = rs.getString(8);

				System.out.println(empno + " : " + ename + " : " + job + " : " + 
					mgr + " : " + hiredate + " : " + sal + " : " + comm + " : " + depno);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
			} catch (SQLException e) {}
			try {
				stmt.close();
			} catch (SQLException e) {}
			mysqlConnectionManager.freeConnection(con);
		}
		
		System.out.println("Driver Number: " + mysqlConnectionManager.getDriverNumber());
		
	}
}
module-info.java
module main.app {
	requires java.sql;
	requires net.java_school.db.dbpool.oracle;
	requires net.java_school.db.dbpool.mysql;
	uses net.java_school.db.dbpool.oracle.OracleConnectionManager;
	uses net.java_school.db.dbpool.mysql.MySqlConnectionManager;
}

Test

Run GetEmp.java by selecting Run As -- Java Application.

Sep 17, 2019 11:46:41 AM net.java_school.db.dbpool.DBConnectionPoolManager loadDrivers
INFO: Registered JDBC driver oracle.jdbc.driver.OracleDriver
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool oracle
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool oracle
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool oracle
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool oracle
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool oracle
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPoolManager createPools
INFO: Initialized pool oracle
7369 : SMITH : CLERK : 7902 : 1980-12-17 00:00:00 : 800 : null : 20
7499 : ALLEN : SALESMAN : 7698 : 1981-02-20 00:00:00 : 1600 : 300 : 30
7521 : WARD : SALESMAN : 7698 : 1981-02-22 00:00:00 : 1250 : 500 : 30
7566 : JONES : MANAGER : 7839 : 1981-04-02 00:00:00 : 2975 : null : 20
7654 : MARTIN : SALESMAN : 7698 : 1981-09-28 00:00:00 : 1250 : 1400 : 30
7698 : BLAKE : MANAGER : 7839 : 1981-05-01 00:00:00 : 2850 : null : 30
7782 : CLARK : MANAGER : 7839 : 1981-06-09 00:00:00 : 2450 : null : 10
7788 : SCOTT : ANALYST : 7566 : 1987-07-13 00:00:00 : 3000 : null : 20
7839 : KING : PRESIDENT : null : 1981-11-17 00:00:00 : 5000 : null : 10
7844 : TURNER : SALESMAN : 7698 : 1981-09-08 00:00:00 : 1500 : 0 : 30
7876 : ADAMS : CLERK : 7788 : 1987-07-13 00:00:00 : 1100 : null : 20
7900 : JAMES : CLERK : 7698 : 1981-12-03 00:00:00 : 950 : null : 30
7902 : FORD : ANALYST : 7566 : 1981-12-03 00:00:00 : 3000 : null : 20
7934 : MILLER : CLERK : 7782 : 1982-01-23 00:00:00 : 1300 : null : 10
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPoolManager freeConnection
INFO: One Connection of oracle was freed
Sep 17, 2019 11:46:42 AM net.java_school.db.dbpool.DBConnectionPoolManager loadDrivers
INFO: Registered JDBC driver com.mysql.jdbc.Driver
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool mysql
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool mysql
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool mysql
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool mysql
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPool newConnection
INFO: Created a new connection in pool mysql
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPoolManager createPools
INFO: Initialized pool mysql
7369 : SMITH : CLERK : 7902 : 1980-12-17 : 800.00 : null : 20
7499 : ALLEN : SALESMAN : 7698 : 1981-02-20 : 1600.00 : 300.00 : 30
7521 : WARD : SALESMAN : 7698 : 1981-02-22 : 1250.00 : 500.00 : 30
7566 : JONES : MANAGER : 7839 : 1981-04-02 : 2975.00 : null : 20
7654 : MARTIN : SALESMAN : 7698 : 1981-09-28 : 1250.00 : 1400.00 : 30
7698 : BLAKE : MANAGER : 7839 : 1981-05-01 : 2850.00 : null : 30
7782 : CLARK : MANAGER : 7839 : 1981-06-09 : 2450.00 : null : 10
7788 : SCOTT : ANALYST : 7566 : 1987-06-28 : 3000.00 : null : 20
7839 : KING : PRESIDENT : null : 1981-11-17 : 5000.00 : null : 10
7844 : TURNER : SALESMAN : 7698 : 1981-09-08 : 1500.00 : 0.00 : 30
7876 : ADAMS : CLERK : 7788 : 1987-07-13 : 1100.00 : null : 20
7900 : JAMES : CLERK : 7698 : 1981-12-03 : 950.00 : null : 30
7902 : FORD : ANALYST : 7566 : 1981-12-03 : 3000.00 : null : 20
7934 : MILLER : CLERK : 7782 : 1982-01-23 : 1300.00 : null : 10
Sep 17, 2019 11:46:43 AM net.java_school.db.dbpool.DBConnectionPoolManager freeConnection
INFO: One Connection of mysql was freed
Driver Number: 2

Command Line Test

Create src, mods, jars folders in the specified directory and copy the files as shown below.

src/
├── net.java_school.db.dbpool
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               ├── DBConnectionPool.java
│   │               ├── DBConnectionPoolManager.java
│   │               └── ConnectionManager.java
│   └── module-info.java
├── net.java_school.db.dbpool.oracle
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── oracle
│   │                   └── OracleConnectionManager.java
│   └── module-info.java
│   └── oracle.properties
├── net.java_school.db.dbpool.mysql
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── mysql
│   │                   └── MySqlConnectionManager.java
│   └── module-info.java
│   └── mysql.properties
mods/
jars/
├── ojdbc6.jar
└── mysql-connector-java-5.1.48.jar

Compile with the following command:

javac -d mods -p jars --module-source-path src $(find src -name "*.java")

The above command should be run from the directory where you see the following three folders when you run ls:

$ ls
jars  mods  src
src/
├── net.java_school.db.dbpool
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               ├── DBConnectionPool.java
│   │               ├── DBConnectionPoolManager.java
│   │               └── ConnectionManager.java
│   └── module-info.java
├── net.java_school.db.dbpool.oracle
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── oracle
│   │                   └── OracleConnectionManager.java
│   └── module-info.java
│   └── oracle.properties
├── net.java_school.db.dbpool.mysql
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── mysql
│   │                   └── MySqlConnectionManager.java
│   └── module-info.java
│   └── mysql.properties
mods/
├── net.java_school.db.dbpool
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               ├── DBConnectionPool.class
│   │               ├── DBConnectionPoolManager.class
│   │               └── ConnectionManager.class
│   └── module-info.class
├── net.java_school.db.dbpool.oracle
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── oracle
│   │                   └── OracleConnectionManager.class
│   └── module-info.class
├── net.java_school.db.dbpool.mysql
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── mysql
│   │                   └── MySqlConnectionManager.class
│   └── module-info.class
jars/
├── ojdbc6.jar
└── mysql-connector-java-5.1.48.jar

Class files are created in the mods folder, but Java property files are not copied to the mods folder.
Before testing, copy the Java property file from the src folder and paste it in the same location as the module descriptor created in the mods folder.

src/
├── net.java_school.db.dbpool
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               ├── DBConnectionPool.java
│   │               ├── DBConnectionPoolManager.java
│   │               └── ConnectionManager.java
│   └── module-info.java
├── net.java_school.db.dbpool.oracle
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── oracle
│   │                   └── OracleConnectionManager.java
│   └── module-info.java
│   └── oracle.properties
├── net.java_school.db.dbpool.mysql
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── mysql
│   │                   └── MySqlConnectionManager.java
│   └── module-info.java
│   └── mysql.properties
mods/
├── net.java_school.db.dbpool
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               ├── DBConnectionPool.class
│   │               ├── DBConnectionPoolManager.class
│   │               └── ConnectionManager.class
│   └── module-info.class
├── net.java_school.db.dbpool.oracle
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── oracle
│   │                   └── OracleConnectionManager.class
│   └── module-info.class
│   └── oracle.properties
├── net.java_school.db.dbpool.mysql
│   ├── net
│   │   └── java_school
│   │       └── db
│   │           └── dbpool
│   │               └── mysql
│   │                   └── MySqlConnectionManager.class
│   └── module-info.class
│   └── mysql.properties
jars/
├── ojdbc6.jar
└── mysql-connector-java-5.1.48.jar

Run with the following command:

java -p mods:jars -m main.app/net.java_school.test.GetEmp

Source: https://github.com/kimjonghoon/java-module-test

References