Modularization - JavaBank
This article covers the modularization of the JDBC Example JavaBank.
Download the JavaBank source with the following command:
git clone https://github.com/kimjonghoon/JavaBank
Download the followings:
- Oracle JDBC Driver from https://www.oracle.com/database/technologies/jdbcdriver-ucp-downloads.html#license-lightbox
- The latest binary release of slf4j-api and slf4j-simple from http://www.slf4j.org/download.html
Copy ojdbc6.jar, slf4j-api-1.7.30.jar and slf4j-simple-1.7.30.jar to lib/ directory.
src/
├── net
│ └── java_school
│ └── bank
│ ├── Account.java
│ ├── Bank.java
│ ├── BankDao.java
│ ├── BankUi.java
│ ├── MyBank.java
│ ├── MyBankDao.java
│ └── Transaction.java
├── simplelogger.properties
lib/
├── ojdbc6.jar
├── slf4j-api-1.7.30.jar
└── slf4j-simple-1.7.30.jar
Connect to the SCOTT account with SQL*PLUS and create the following tables and a trigger that inserts transaction history data in the transaction table whenever the account balance changes.
create table bankaccount ( accountno varchar2(50), owner varchar2(20) not null, balance number, kind varchar2(10), constraint PK_BANKACCOUNT primary key(accountno), constraint CK_BANKACCOUNT_NORMAL CHECK (balance >= CASE WHEN kind='NORMAL' THEN 0 END), constraint CK_BANKACCOUNT_KIND CHECK (kind in ('NORMAL', 'MINUS')) ); create table transaction ( transactiondate timestamp, kind varchar2(10), amount number, balance number, accountno varchar2(50), constraint FK_TRANSACTION FOREIGN KEY(accountno) REFERENCES bankaccount(accountno) ); create or replace trigger bank_trigger after insert or update of balance on bankaccount for each row begin if :new.balance > :old.balance then insert into transaction values ( systimestamp, 'DEPOSIT', :new.balance - :old.balance, :new.balance, :old.accountno ); end if; if :new.balance < :old.balance then insert into transaction values ( systimestamp, 'WITHDRAW', :old.balance - :new.balance, :new.balance, :old.accountno ); end if; end; /
Before modularization, check if the program works.
Test on Windows
Compile
C:\ Command Promptmkdir out set classpath=lib\slf4j-api-1.7.30.jar javac -d out src\net\java_school\bank\*.java
Copy properties to out/ directory.
C:\ Command Promptcopy src\simplelogger.properties out\
Run
C:\ Command Promptset classpath=lib\slf4j-api-1.7.30.jar;lib\slf4j-simple-1.7.30.jar;lib\ojdbc6.jar;out java net.java_school.bank.BankUi
Test on Linux
Compile
CP=lib/slf4j-api-1.7.30.jar javac -cp $CP -d out -sourcepath src $(find src -name "*.java")
Copy properties to out/ directory.
cp src/simplelogger.properties out/
Run
CP+=:lib/slf4j-simple-1.7.30.jar CP+=:lib/ojdbc6.jar java -cp $CP:out net.java_school.bank.BankUi
Run the following to check the external library on which JavaBank depends.
jdeps -summary -cp lib/*.jar out
.. out -> lib/slf4j-api-1.7.30.jar ..
We found that JavaBank depends on slf4j-api-1.7.30.jar. Remember that a library like this should be in the module path. Jars that are not modules in the module path become automatic modules.
Modularization
Download the custom connection pool modules.
git clone https://github.com/kimjonghoon/java-module-test
Place the JavaBank sources in the src/ folder of java-module-test and Remove the main.app and net.java_school.db.dbpool.mysql modules in java-module-test.
src/
├── net.java_school.javabank
│ ├── net
│ │ └── java_school
│ │ └── bank
│ │ ├── Account.java
│ │ ├── Bank.java
│ │ ├── BankDao.java
│ │ ├── BankUi.java
│ │ ├── MyBank.java
│ │ ├── MyBankDao.java
│ │ └── Transaction.java
│ ├── module-info.java
│ └── simplelogger.properties
├── net.java_school.db.dbpool.api
│ ├── net
│ │ └── java_school
│ │ └── db
│ │ └── dbpool
│ │ └── api
│ │ └── ConnectionManageable.java
│ └── module-info.java
├── 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
lib/
├── slf4j-simple-1.7.30.jar
jars/
├── ojdbc6.jar
└── slf4j-api-1.7.30.jar
Add jars/ to the module path. Non-module jars in the module path become automatic modules.
Add lib/ to the classpath. Non-module jars in the classpath become unnamed modules.
Only automatic modules can read unnamed modules. You can easily infer that slf4j-api will read slf4j-simple from their name.
Create the module-info.java of the net.java_school.javabank module.
module net.java_school.javabank { requires net.java_school.db.dbpool.api; uses net.java_school.db.dbpool.api.ConnectionManageable; }
Compile to see how the names of the automatic modules are determined.
Compile on Windows
C:\ Command Promptjavac -p jars -d out --module-source-path src ^ -m net.java_school.javabank,net.java_school.db.dbpool.api, net.java_school.db.dbpool,net.java_school.db.dbpool.oracle
Compile on Linux
javac -p jars -d out --module-source-path src $(find src -name "*.java")
Compile error occurs.
src/net.java_school.javabank/net/java_school/bank/MyBankDao.java:12: error: package org.slf4j is not visible import org.slf4j.Logger; ^ (package org.slf4j is declared in module org.slf4j, but module net.java_school.javabank does not read it) src/net.java_school.javabank/net/java_school/bank/MyBankBankDao.java:13: error: package org.slf4j is not visible import org.slf4j.LoggerFactory; ^ (package org.slf4j is declared in module org.slf4j, but module net.java_school.javabank does not read it) 2 errors
(package org.slf4j is declared in module org.slf4j, but module net.java_school.javabank does not read it)
You found the module name is org.slf4j from the error message. Edit the module-info.java in the net.java_school.javabank module as follows.
module net.java_school.javabank { requires net.java_school.db.dbpool.api; requires org.slf4j; uses net.java_school.db.dbpool.api.ConnectionManageable; }
Test on Windows
Compile
C:\ Command Promptjavac -p jars -d out --module-source-path src ^ -m net.java_school.javabank,net.java_school.db.dbpool.api, net.java_school.db.dbpool,net.java_school.db.dbpool.oracle
Copy properties to the module directory.
C:\ Command Promptcopy src\net.java_school.db.dbpool.oracle\oracle.properties ^ out\net.java_school.db.dbpool.oracle\ copy src\net.java_school.javabank\simplelogger.properties ^ out\net.java_school.javabank\
Run
C:\ Command Promptset classpath=lib\slf4j-simple-1.7.30.jar java -p jars;out ^ -m net.java_school.javabank/net.java_school.bank.BankUi
Test on Linux
Compile
javac -p jars -d out --module-source-path src $(find src -name "*.java")
Copy properties to the module directory.
cp src/net.java_school.db.dbpool.oracle/oracle.properties \ out/net.java_school.db.dbpool.oracle/ cp src/net.java_school.javabank/simplelogger.properties \ out/net.java_school.javabank/
Run
CP=lib/slf4j-simple-1.7.30.jar java -cp $CP -p jars:out \ -m net.java_school.javabank/net.java_school.bank.BankUiReferences