diff --git a/README.md b/README.md
index a1d2939..213be0b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,13 @@
SpringCore
==========
+example with xml metadata configuration
+
+homework - review code, ask questions
+
+homework - change constructor injection with setter injection
+
+homework - do validation for AccountMapper class
+
+homework - do validation for Transaction Validator
+
+homework - tbd
diff --git a/pom.xml b/pom.xml
index 902ab97..4eaf1a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,28 +1,30 @@
-
-
4.0.0
app
SpringCore
1.0-SNAPSHOT
+ jar
-
-
- 4.0.2.RELEASE
+ SpringCore
+
+ 4.0.3.RELEASE
+ 1.4
+ 2.3.2
1.7.6
1.1.1
- 4.11-20120805-1225
+ 4.11
+ 1.9.5
+ Core utilities used by other modules.
+ Define this if you use Spring Utility APIs (org.springframework.core.*/org.springframework.util.*)
+ -->
org.springframework
spring-core
@@ -59,16 +61,32 @@
${org.springframework.version}
-
org.springframework
- spring-context-support
+ spring-jdbc
${org.springframework.version}
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+ test
+
+
+
+
+ commons-dbcp
+ commons-dbcp
+ ${commons-dbcp.version}
+
+
+
+ org.hsqldb
+ hsqldb
+ ${org.hsqldb.version}
+
+
@@ -100,6 +118,12 @@
test
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
@@ -111,7 +135,12 @@
1.7
1.7
-
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
org.codehaus.mojo
@@ -119,10 +148,24 @@
2.1
false
+ false
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.0.1
+
+
+ compile
+
+ check
+ cpd-check
+
+
+
+
-
-
\ No newline at end of file
+
diff --git a/src/main/java/app/Main.java b/src/main/java/app/Main.java
new file mode 100644
index 0000000..b6ada8b
--- /dev/null
+++ b/src/main/java/app/Main.java
@@ -0,0 +1,30 @@
+package app;
+
+import app.domain.Account;
+import app.domain.Transaction;
+import app.service.AccountManagerService;
+import app.service.MoneyTransferService;
+import app.service.TransferService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.math.BigDecimal;
+
+public class Main {
+
+ public static void main(String[] args) {
+
+ ApplicationContext context = new ClassPathXmlApplicationContext("/spring/application-config.xml","/spring/database-config.xml");
+
+ Transaction transaction = new Transaction("12345678901234", "12345678909876", BigDecimal.TEN);
+ TransferService transferService = context.getBean("transferService", MoneyTransferService.class);
+ transferService.transferAmount(transaction);
+
+ AccountManagerService accountService = context.getBean("accountService", AccountManagerService.class);
+ Account payerAccount = accountService.findByNumber("12345678901234");
+ Account beneficiaryAccount = accountService.findByNumber("12345678909876");
+
+ System.out.println(payerAccount);
+ System.out.println(beneficiaryAccount);
+ }
+}
diff --git a/src/main/java/app/domain/Account.java b/src/main/java/app/domain/Account.java
new file mode 100644
index 0000000..d2809b8
--- /dev/null
+++ b/src/main/java/app/domain/Account.java
@@ -0,0 +1,41 @@
+package app.domain;
+
+import java.math.BigDecimal;
+
+public class Account extends Entity {
+
+ private String number;
+ private String name;
+ private BigDecimal moneyAmount;
+
+ public Account(String number, String name, BigDecimal moneyAmount) {
+ this.number = number;
+ this.name = name;
+ this.moneyAmount = moneyAmount;
+ }
+
+ public String getNumber() {
+ return number;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public BigDecimal getMoneyAmount() {
+ return moneyAmount;
+ }
+
+ public void setMoneyAmount(BigDecimal moneyAmount) {
+ this.moneyAmount = moneyAmount;
+ }
+
+ @Override
+ public String toString() {
+ return "Account{" +
+ "number='" + number + '\'' +
+ ", name='" + name + '\'' +
+ ", moneyAmount=" + moneyAmount +
+ '}';
+ }
+}
diff --git a/src/main/java/app/domain/Entity.java b/src/main/java/app/domain/Entity.java
new file mode 100644
index 0000000..969e057
--- /dev/null
+++ b/src/main/java/app/domain/Entity.java
@@ -0,0 +1,21 @@
+package app.domain;
+
+public class Entity {
+
+ private long entityId;
+
+ public long getEntityId() {
+ return entityId;
+ }
+
+ public void setEntityId(long entityId) {
+ this.entityId = entityId;
+ }
+
+ @Override
+ public String toString() {
+ return "Entity{" +
+ "entityId=" + entityId +
+ '}';
+ }
+}
diff --git a/src/main/java/app/domain/Transaction.java b/src/main/java/app/domain/Transaction.java
new file mode 100644
index 0000000..6271c7e
--- /dev/null
+++ b/src/main/java/app/domain/Transaction.java
@@ -0,0 +1,45 @@
+package app.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+public class Transaction extends Entity {
+
+ private String payerAccountNumber;
+ private String beneficiaryAccountNumber;
+ private BigDecimal moneyAmount;
+ private Date date;
+
+ public Transaction(String payerAccountNumber, String beneficiaryAccount, BigDecimal moneyAmount) {
+ this.payerAccountNumber = payerAccountNumber;
+ this.beneficiaryAccountNumber = beneficiaryAccount;
+ this.moneyAmount = moneyAmount;
+ this.date = new Date();
+ }
+
+ public String getPayerAccountNumber() {
+ return payerAccountNumber;
+ }
+
+ public String getBeneficiaryAccountNumber() {
+ return beneficiaryAccountNumber;
+ }
+
+ public BigDecimal getMoneyAmount() {
+ return moneyAmount;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ @Override
+ public String toString() {
+ return "Transaction{" +
+ ", payerAccountNumber='" + payerAccountNumber + '\'' +
+ ", beneficiaryAccountNumber='" + beneficiaryAccountNumber + '\'' +
+ ", moneyAmount=" + moneyAmount +
+ ", date=" + date +
+ '}';
+ }
+}
diff --git a/src/main/java/app/repository/AccountRepository.java b/src/main/java/app/repository/AccountRepository.java
new file mode 100644
index 0000000..e1698c9
--- /dev/null
+++ b/src/main/java/app/repository/AccountRepository.java
@@ -0,0 +1,15 @@
+package app.repository;
+
+
+import app.domain.Account;
+
+import java.util.List;
+
+public interface AccountRepository {
+
+ List findByNumber(String number);
+
+ int insert(Account account);
+
+ int updateMoneyAmount(Account account);
+}
diff --git a/src/main/java/app/repository/JdbcAccountRepository.java b/src/main/java/app/repository/JdbcAccountRepository.java
new file mode 100644
index 0000000..538a168
--- /dev/null
+++ b/src/main/java/app/repository/JdbcAccountRepository.java
@@ -0,0 +1,43 @@
+package app.repository;
+
+import app.domain.Account;
+import app.util.AccountMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+import java.util.List;
+
+public class JdbcAccountRepository implements AccountRepository {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public JdbcAccountRepository(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public List findByNumber(String number) {
+ return jdbcTemplate.query(
+ "SELECT * FROM t_account WHERE number = ?",
+ new AccountMapper(),
+ number);
+ }
+
+ @Override
+ public int insert(Account account) {
+ return jdbcTemplate.update(
+ "INSERT INTO t_account (number, name, money_amount) VALUES(?, ?, ?)",
+ account.getNumber(),
+ account.getName(),
+ account.getMoneyAmount());
+ }
+
+ @Override
+ public int updateMoneyAmount(Account account) {
+ return jdbcTemplate.update(
+ "UPDATE t_account SET money_amount = ? WHERE id = ?",
+ account.getMoneyAmount(),
+ account.getEntityId()
+ );
+ }
+}
diff --git a/src/main/java/app/repository/JdbcTransactionRepository.java b/src/main/java/app/repository/JdbcTransactionRepository.java
new file mode 100644
index 0000000..71d6876
--- /dev/null
+++ b/src/main/java/app/repository/JdbcTransactionRepository.java
@@ -0,0 +1,25 @@
+package app.repository;
+
+import app.domain.Transaction;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+public class JdbcTransactionRepository implements TransactionRepository {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public JdbcTransactionRepository(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public int insert(Transaction transaction) {
+ return jdbcTemplate.update(
+ "INSERT INTO t_transaction (payer_account, beneficiary_account, money_amount, date) VALUES(?, ?, ?, ?)",
+ transaction.getPayerAccountNumber(),
+ transaction.getBeneficiaryAccountNumber(),
+ transaction.getMoneyAmount(),
+ transaction.getDate());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/app/repository/TransactionRepository.java b/src/main/java/app/repository/TransactionRepository.java
new file mode 100644
index 0000000..9301e14
--- /dev/null
+++ b/src/main/java/app/repository/TransactionRepository.java
@@ -0,0 +1,9 @@
+package app.repository;
+
+import app.domain.Transaction;
+
+public interface TransactionRepository {
+
+ int insert(Transaction transaction);
+
+}
diff --git a/src/main/java/app/service/AccountManagerService.java b/src/main/java/app/service/AccountManagerService.java
new file mode 100644
index 0000000..1af754c
--- /dev/null
+++ b/src/main/java/app/service/AccountManagerService.java
@@ -0,0 +1,51 @@
+package app.service;
+
+import app.domain.Account;
+import app.repository.AccountRepository;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+
+import java.util.List;
+
+public class AccountManagerService implements AccountService {
+
+ private AccountRepository accountRepository;
+
+ public AccountManagerService(AccountRepository accountRepository) {
+ this.accountRepository = accountRepository;
+ }
+
+ @Override
+ public Account findByNumber(String number) {
+ List accounts = accountRepository.findByNumber(number);
+ if (accounts == null || accounts.size() ==0) {
+ throw new EmptyResultDataAccessException("No account found for number " + number + ".", 1);
+ }
+ if (accounts.size() > 1) {
+ throw new IncorrectResultSizeDataAccessException("More than one account found for number" + number + ".", 1);
+ }
+ return accounts.get(0);
+ }
+
+ @Override
+ public void save(Account account) {
+ int count = accountRepository.insert(account);
+ if (count == 0) {
+ throw new IncorrectResultSizeDataAccessException("Account not saved.", 1);
+ }
+ if (count > 1) {
+ throw new IncorrectResultSizeDataAccessException("More than once account was saved.", 1);
+ }
+ }
+
+ @Override
+ public void updateMoneyAmount(Account account) {
+ int count = accountRepository.updateMoneyAmount(account);
+ if (count == 0) {
+ throw new IncorrectResultSizeDataAccessException("No accounts were updated", 1);
+ }
+ if (count > 1) {
+ throw new IncorrectResultSizeDataAccessException("More than once account was updated", 1);
+ }
+ }
+}
diff --git a/src/main/java/app/service/AccountService.java b/src/main/java/app/service/AccountService.java
new file mode 100644
index 0000000..49c9dd3
--- /dev/null
+++ b/src/main/java/app/service/AccountService.java
@@ -0,0 +1,12 @@
+package app.service;
+
+import app.domain.Account;
+
+public interface AccountService {
+
+ Account findByNumber(String number);
+
+ void save(Account account);
+
+ void updateMoneyAmount(Account account);
+}
diff --git a/src/main/java/app/service/MoneyTransferService.java b/src/main/java/app/service/MoneyTransferService.java
new file mode 100644
index 0000000..17ec6f6
--- /dev/null
+++ b/src/main/java/app/service/MoneyTransferService.java
@@ -0,0 +1,37 @@
+package app.service;
+
+import app.domain.Account;
+import app.domain.Transaction;
+import app.util.TransactionValidator;
+
+import java.math.BigDecimal;
+
+public class MoneyTransferService implements TransferService {
+
+ private AccountService accountService;
+ private TransactionService transactionService;
+
+ public MoneyTransferService(AccountService accountService, TransactionService transactionService) {
+ this.accountService = accountService;
+ this.transactionService = transactionService;
+ }
+
+ @Override
+ public void transferAmount(Transaction transaction) {
+
+ TransactionValidator.validate(transaction);
+
+ Account payerAccount = accountService.findByNumber(transaction.getPayerAccountNumber());
+ Account beneficiaryAccount = accountService.findByNumber(transaction.getBeneficiaryAccountNumber());
+
+ BigDecimal amount = transaction.getMoneyAmount();
+ payerAccount.setMoneyAmount(payerAccount.getMoneyAmount().subtract(amount));
+ beneficiaryAccount.setMoneyAmount(beneficiaryAccount.getMoneyAmount().add(amount));
+
+ accountService.updateMoneyAmount(payerAccount);
+ accountService.updateMoneyAmount(beneficiaryAccount);
+
+ transactionService.save(transaction);
+ }
+
+}
diff --git a/src/main/java/app/service/TransactionManagerService.java b/src/main/java/app/service/TransactionManagerService.java
new file mode 100644
index 0000000..76b36f1
--- /dev/null
+++ b/src/main/java/app/service/TransactionManagerService.java
@@ -0,0 +1,25 @@
+package app.service;
+
+import app.domain.Transaction;
+import app.repository.TransactionRepository;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+
+public class TransactionManagerService implements TransactionService {
+
+ private TransactionRepository transactionRepository;
+
+ public TransactionManagerService(TransactionRepository transactionRepository) {
+ this.transactionRepository = transactionRepository;
+ }
+
+ @Override
+ public void save(Transaction transaction) {
+ int count = transactionRepository.insert(transaction);
+ if (count == 0) {
+ throw new IncorrectResultSizeDataAccessException("Transaction not saved.", 1);
+ }
+ if (count > 1) {
+ throw new IncorrectResultSizeDataAccessException("More than once transaction was saved.", 1);
+ }
+ }
+}
diff --git a/src/main/java/app/service/TransactionService.java b/src/main/java/app/service/TransactionService.java
new file mode 100644
index 0000000..3773b81
--- /dev/null
+++ b/src/main/java/app/service/TransactionService.java
@@ -0,0 +1,9 @@
+package app.service;
+
+import app.domain.Transaction;
+
+public interface TransactionService {
+
+ void save(Transaction transaction);
+
+}
diff --git a/src/main/java/app/service/TransferService.java b/src/main/java/app/service/TransferService.java
new file mode 100644
index 0000000..9256b57
--- /dev/null
+++ b/src/main/java/app/service/TransferService.java
@@ -0,0 +1,9 @@
+package app.service;
+
+import app.domain.Transaction;
+
+public interface TransferService {
+
+ void transferAmount(Transaction transaction);
+
+}
diff --git a/src/main/java/app/util/AccountMapper.java b/src/main/java/app/util/AccountMapper.java
new file mode 100644
index 0000000..c7adef8
--- /dev/null
+++ b/src/main/java/app/util/AccountMapper.java
@@ -0,0 +1,20 @@
+package app.util;
+
+import app.domain.Account;
+import org.springframework.jdbc.core.RowMapper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class AccountMapper implements RowMapper {
+
+ @Override
+ public Account mapRow(ResultSet resultSet, int i) throws SQLException {
+ Account account = new Account(
+ resultSet.getString("number"),
+ resultSet.getString("name"),
+ resultSet.getBigDecimal("money_amount", 2));
+ account.setEntityId(resultSet.getLong("id"));
+ return account;
+ }
+}
diff --git a/src/main/java/app/util/TransactionValidator.java b/src/main/java/app/util/TransactionValidator.java
new file mode 100644
index 0000000..8ff3c2f
--- /dev/null
+++ b/src/main/java/app/util/TransactionValidator.java
@@ -0,0 +1,30 @@
+package app.util;
+
+import app.domain.Transaction;
+
+import java.math.BigDecimal;
+
+public class TransactionValidator {
+
+ private static final String ACCOUNT_NUMBER_FORMAT_REGEXP = "\\d{14}";
+
+ public static void validate(Transaction transaction) {
+
+ BigDecimal amount = transaction.getMoneyAmount();
+ if (amount == null || amount.compareTo(BigDecimal.ZERO) < 0) {
+ throw new IllegalArgumentException("Invalid transaction, amount value is null or less than zero.");
+ }
+ String payerAccount = transaction.getPayerAccountNumber();
+ if (payerAccount == null || !isValidAccountNumberFormat(payerAccount)) {
+ throw new IllegalArgumentException("Invalid transaction, payer account has an invalid format.");
+ }
+ String beneficiaryAccount = transaction.getBeneficiaryAccountNumber();
+ if (beneficiaryAccount == null || !isValidAccountNumberFormat(beneficiaryAccount)) {
+ throw new IllegalArgumentException("Invalid transaction, beneficiary account has an invalid format.");
+ }
+ }
+
+ private static boolean isValidAccountNumberFormat(String accountNumber) {
+ return accountNumber.matches(ACCOUNT_NUMBER_FORMAT_REGEXP);
+ }
+}
diff --git a/src/main/resources/database.properties b/src/main/resources/database.properties
new file mode 100644
index 0000000..3867621
--- /dev/null
+++ b/src/main/resources/database.properties
@@ -0,0 +1,4 @@
+db.driver=org.hsqldb.jdbcDriver
+db.url=jdbc:hsqldb:file:src/main/resources/testdbdata/data
+db.username=sa
+db.password=
\ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..50b03e0
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/spring/application-config.xml b/src/main/resources/spring/application-config.xml
new file mode 100644
index 0000000..916da7e
--- /dev/null
+++ b/src/main/resources/spring/application-config.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/spring/database-config.xml b/src/main/resources/spring/database-config.xml
new file mode 100644
index 0000000..fd24228
--- /dev/null
+++ b/src/main/resources/spring/database-config.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/testdb/data.sql b/src/main/resources/testdb/data.sql
new file mode 100644
index 0000000..f83b7d3
--- /dev/null
+++ b/src/main/resources/testdb/data.sql
@@ -0,0 +1,2 @@
+insert into T_ACCOUNT (NUMBER, NAME, MONEY_AMOUNT) values ('12345678901234', 'Bogdan', '100.00');
+insert into T_ACCOUNT (NUMBER, NAME, MONEY_AMOUNT) values ('12345678909876', 'Dragos', '100.00');
diff --git a/src/main/resources/testdb/schema.sql b/src/main/resources/testdb/schema.sql
new file mode 100644
index 0000000..3606469
--- /dev/null
+++ b/src/main/resources/testdb/schema.sql
@@ -0,0 +1,19 @@
+drop table T_ACCOUNT if exists;
+drop table T_TRANSACTION if exists;
+
+create table T_ACCOUNT(
+ ID integer identity primary key,
+ NUMBER varchar(14) not null,
+ NAME varchar(50) not null,
+ MONEY_AMOUNT double not null,
+ unique(NUMBER)
+);
+
+create table T_TRANSACTION(
+ ID integer identity primary key,
+ PAYER_ACCOUNT varchar(14) not null,
+ BENEFICIARY_ACCOUNT varchar(14) not null,
+ MONEY_AMOUNT double not null,
+ DATE date not null,
+ unique(PAYER_ACCOUNT, BENEFICIARY_ACCOUNT, MONEY_AMOUNT, DATE)
+);
\ No newline at end of file
diff --git a/src/main/resources/testdbdata/data.log b/src/main/resources/testdbdata/data.log
new file mode 100644
index 0000000..f0f01b4
--- /dev/null
+++ b/src/main/resources/testdbdata/data.log
@@ -0,0 +1,34 @@
+/*C8*/SET SCHEMA PUBLIC
+drop table T_ACCOUNT if exists
+drop table T_TRANSACTION if exists
+create table T_ACCOUNT( ID integer identity primary key, NUMBER varchar(14) not null, NAME varchar(50) not null, MONEY_AMOUNT double not null, unique(NUMBER) )
+create table T_TRANSACTION( ID integer identity primary key, PAYER_ACCOUNT varchar(14) not null, BENEFICIARY_ACCOUNT varchar(14) not null, MONEY_AMOUNT double not null, DATE date not null, unique(PAYER_ACCOUNT, BENEFICIARY_ACCOUNT, MONEY_AMOUNT, DATE) )
+INSERT INTO T_ACCOUNT VALUES(0,'12345678901234','Bogdan',100.0E0)
+COMMIT
+INSERT INTO T_ACCOUNT VALUES(1,'12345678909876','Dragos',100.0E0)
+COMMIT
+DISCONNECT
+/*C9*/SET SCHEMA PUBLIC
+DISCONNECT
+/*C10*/SET SCHEMA PUBLIC
+DISCONNECT
+/*C11*/SET SCHEMA PUBLIC
+DELETE FROM T_ACCOUNT WHERE ID=0
+INSERT INTO T_ACCOUNT VALUES(0,'12345678901234','Bogdan',90.0E0)
+COMMIT
+DISCONNECT
+/*C12*/SET SCHEMA PUBLIC
+DELETE FROM T_ACCOUNT WHERE ID=1
+INSERT INTO T_ACCOUNT VALUES(1,'12345678909876','Dragos',110.0E0)
+COMMIT
+DISCONNECT
+/*C13*/SET SCHEMA PUBLIC
+INSERT INTO T_TRANSACTION VALUES(0,'12345678901234','12345678909876',10.0E0,'2014-03-30')
+COMMIT
+DISCONNECT
+/*C14*/SET SCHEMA PUBLIC
+DISCONNECT
+/*C15*/SET SCHEMA PUBLIC
+DISCONNECT
+/*C16*/SET SCHEMA PUBLIC
+DISCONNECT
diff --git a/src/main/resources/testdbdata/data.properties b/src/main/resources/testdbdata/data.properties
new file mode 100644
index 0000000..e869e9d
--- /dev/null
+++ b/src/main/resources/testdbdata/data.properties
@@ -0,0 +1,4 @@
+#HSQL Database Engine 2.3.2
+#Sun Mar 30 14:10:53 EEST 2014
+version=2.3.2
+modified=yes
diff --git a/src/main/resources/testdbdata/data.script b/src/main/resources/testdbdata/data.script
new file mode 100644
index 0000000..9ee52eb
--- /dev/null
+++ b/src/main/resources/testdbdata/data.script
@@ -0,0 +1,53 @@
+SET DATABASE UNIQUE NAME HSQLDB451294B2C7
+SET DATABASE GC 0
+SET DATABASE DEFAULT RESULT MEMORY ROWS 0
+SET DATABASE EVENT LOG LEVEL 0
+SET DATABASE TRANSACTION CONTROL LOCKS
+SET DATABASE DEFAULT ISOLATION LEVEL READ COMMITTED
+SET DATABASE TRANSACTION ROLLBACK ON CONFLICT TRUE
+SET DATABASE TEXT TABLE DEFAULTS ''
+SET DATABASE SQL NAMES FALSE
+SET DATABASE SQL REFERENCES FALSE
+SET DATABASE SQL SIZE TRUE
+SET DATABASE SQL TYPES FALSE
+SET DATABASE SQL TDC DELETE TRUE
+SET DATABASE SQL TDC UPDATE TRUE
+SET DATABASE SQL TRANSLATE TTI TYPES TRUE
+SET DATABASE SQL CONCAT NULLS TRUE
+SET DATABASE SQL UNIQUE NULLS TRUE
+SET DATABASE SQL CONVERT TRUNCATE TRUE
+SET DATABASE SQL AVG SCALE 0
+SET DATABASE SQL DOUBLE NAN TRUE
+SET FILES WRITE DELAY 500 MILLIS
+SET FILES BACKUP INCREMENT TRUE
+SET FILES CACHE SIZE 10000
+SET FILES CACHE ROWS 50000
+SET FILES SCALE 32
+SET FILES LOB SCALE 32
+SET FILES DEFRAG 0
+SET FILES NIO TRUE
+SET FILES NIO SIZE 256
+SET FILES LOG TRUE
+SET FILES LOG SIZE 50
+CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e'
+ALTER USER SA SET LOCAL TRUE
+CREATE SCHEMA PUBLIC AUTHORIZATION DBA
+SET SCHEMA PUBLIC
+CREATE MEMORY TABLE PUBLIC.T_ACCOUNT(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,NUMBER VARCHAR(14) NOT NULL,NAME VARCHAR(50) NOT NULL,MONEY_AMOUNT DOUBLE NOT NULL,UNIQUE(NUMBER))
+ALTER TABLE PUBLIC.T_ACCOUNT ALTER COLUMN ID RESTART WITH 2
+CREATE MEMORY TABLE PUBLIC.T_TRANSACTION(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,PAYER_ACCOUNT VARCHAR(14) NOT NULL,BENEFICIARY_ACCOUNT VARCHAR(14) NOT NULL,MONEY_AMOUNT DOUBLE NOT NULL,DATE DATE NOT NULL,UNIQUE(PAYER_ACCOUNT,BENEFICIARY_ACCOUNT,MONEY_AMOUNT,DATE))
+ALTER TABLE PUBLIC.T_TRANSACTION ALTER COLUMN ID RESTART WITH 1
+ALTER SEQUENCE SYSTEM_LOBS.LOB_ID RESTART WITH 1
+SET DATABASE DEFAULT INITIAL SCHEMA PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.SQL_IDENTIFIER TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.YES_OR_NO TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.TIME_STAMP TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CARDINAL_NUMBER TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CHARACTER_DATA TO PUBLIC
+GRANT DBA TO SA
+SET SCHEMA SYSTEM_LOBS
+INSERT INTO BLOCKS VALUES(0,2147483647,0)
+SET SCHEMA PUBLIC
+INSERT INTO T_ACCOUNT VALUES(0,'12345678901234','Bogdan',90.0E0)
+INSERT INTO T_ACCOUNT VALUES(1,'12345678909876','Dragos',110.0E0)
+INSERT INTO T_TRANSACTION VALUES(0,'12345678901234','12345678909876',10.0E0,'2014-03-30')
diff --git a/src/test/java/app/repository/JdbcAccountRepositoryIT.java b/src/test/java/app/repository/JdbcAccountRepositoryIT.java
new file mode 100644
index 0000000..3dd2425
--- /dev/null
+++ b/src/test/java/app/repository/JdbcAccountRepositoryIT.java
@@ -0,0 +1,140 @@
+package app.repository;
+
+import app.domain.Account;
+import app.util.AccountMapper;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.sql.DataSource;
+import java.math.BigDecimal;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNull.notNullValue;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class JdbcAccountRepositoryIT {
+
+ private static String ACCOUNT_NUMBER = "12345678901234";
+ private static String ACCOUNT_NAME = "NAME";
+ private static BigDecimal ACCOUNT_MONEY_AMOUNT = new BigDecimal("100.00");
+
+ @Autowired
+ private AccountRepository accountRepository;
+
+ @Autowired
+ private DataSource dataSource;
+
+ private JdbcTemplate jdbcTemplate;
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Before
+ public void setUp() throws Exception {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Test
+ @DirtiesContext
+ public void testFindByNumberReturnOnceResult() throws Exception {
+
+ jdbcTemplate.update(
+ "INSERT INTO t_account (number, name, money_amount) VALUES(?, ?, ?)",
+ ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_MONEY_AMOUNT);
+
+ List accounts = accountRepository.findByNumber(ACCOUNT_NUMBER);
+
+ assertThat(accounts, is(notNullValue()));
+ assertThat(accounts.size(), is(1));
+
+ Account account = accounts.get(0);
+ assertThat(account.getEntityId(), is(0L));
+ assertThat(account.getName(), is(ACCOUNT_NAME));
+ assertThat(account.getNumber(), is(ACCOUNT_NUMBER));
+ assertThat(account.getMoneyAmount(), is(ACCOUNT_MONEY_AMOUNT));
+ }
+
+ @Test
+ public void testFindByNumberReturnEmptyList() throws Exception {
+
+ List accounts = accountRepository.findByNumber(ACCOUNT_NUMBER);
+
+ assertThat(accounts, is(notNullValue()));
+ assertThat(accounts.size(), is(0));
+ }
+
+ @Test
+ @DirtiesContext
+ public void testInsertSuccess() throws Exception {
+
+ accountRepository.insert(new Account(ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_MONEY_AMOUNT));
+
+ List accounts = jdbcTemplate.query(
+ "SELECT * FROM t_account WHERE number = ?",
+ new AccountMapper(),
+ ACCOUNT_NUMBER);
+
+ assertThat(accounts, is(notNullValue()));
+ assertThat(accounts.size(), is(1));
+
+ Account account = accounts.get(0);
+ assertThat(account.getEntityId(), is(0L));
+ assertThat(account.getName(), is(ACCOUNT_NAME));
+ assertThat(account.getNumber(), is(ACCOUNT_NUMBER));
+ assertThat(account.getMoneyAmount(), is(ACCOUNT_MONEY_AMOUNT));
+ }
+
+ @Test
+ public void testInsertFailed() throws Exception {
+ exception.expect(DataIntegrityViolationException.class);
+
+ accountRepository.insert(new Account(null, ACCOUNT_NAME, ACCOUNT_MONEY_AMOUNT));
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void testUpdateMoneyAmountSuccess() throws Exception {
+
+ jdbcTemplate.update(
+ "INSERT INTO t_account (number, name, money_amount) VALUES(?, ?, ?)",
+ ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_MONEY_AMOUNT);
+
+ List accounts = jdbcTemplate.query("SELECT * FROM t_account WHERE number = ?",
+ new AccountMapper(),
+ ACCOUNT_NUMBER);
+
+ BigDecimal NEW_MONEY_AMOUNT = ACCOUNT_MONEY_AMOUNT.add(BigDecimal.TEN);
+ Account account = accounts.get(0);
+ account.setMoneyAmount(NEW_MONEY_AMOUNT);
+
+ accountRepository.updateMoneyAmount(account);
+
+ BigDecimal moneyAmount = jdbcTemplate.queryForObject(
+ "SELECT money_amount FROM t_account WHERE id = ?", BigDecimal.class, account.getEntityId());
+ moneyAmount = moneyAmount.setScale(2);
+
+ assertThat(moneyAmount, is(NEW_MONEY_AMOUNT));
+ }
+
+ @Test
+ public void testUpdateMoneyAmountFail() throws Exception {
+
+ Account account = new Account(ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_MONEY_AMOUNT);
+ account.setEntityId(0L);
+
+ accountRepository.updateMoneyAmount(account);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/app/repository/JdbcTransactionRepositoryIT.java b/src/test/java/app/repository/JdbcTransactionRepositoryIT.java
new file mode 100644
index 0000000..c366680
--- /dev/null
+++ b/src/test/java/app/repository/JdbcTransactionRepositoryIT.java
@@ -0,0 +1,91 @@
+package app.repository;
+
+import app.domain.Transaction;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.sql.DataSource;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNull.notNullValue;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class JdbcTransactionRepositoryIT {
+
+ private static final String PAYER_ACCOUNT_NUMBER = "12345678901234";
+ private static final String BENEFICIARY_ACCOUNT_NUMBER = "12345678909876";
+ private static final BigDecimal MONEY_AMOUNT = new BigDecimal("10.00");
+
+ @Autowired
+ private TransactionRepository transactionRepository;
+
+ @Autowired
+ private DataSource dataSource;
+
+ private JdbcTemplate jdbcTemplate;
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Before
+ public void setUp() throws Exception {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Test
+ @DirtiesContext
+ public void testInsertSuccess() throws Exception {
+
+ transactionRepository.insert(new Transaction(PAYER_ACCOUNT_NUMBER, BENEFICIARY_ACCOUNT_NUMBER, MONEY_AMOUNT));
+
+ List transactions = jdbcTemplate.query(
+ "SELECT * FROM t_transaction WHERE payer_account = ? and beneficiary_account = ? and money_amount = ?",
+ new RowMapper() {
+ @Override
+ public Transaction mapRow(ResultSet resultSet, int i) throws SQLException {
+ Transaction transaction = new Transaction(
+ resultSet.getString("payer_account"),
+ resultSet.getString("beneficiary_account"),
+ resultSet.getBigDecimal("money_amount", 2));
+ transaction.setEntityId(resultSet.getLong("id"));
+ return transaction;
+ }
+ },
+ PAYER_ACCOUNT_NUMBER, BENEFICIARY_ACCOUNT_NUMBER, MONEY_AMOUNT);
+
+ assertThat(transactions, is(notNullValue()));
+ assertThat(transactions.size(), is(1));
+
+ Transaction transaction = transactions.get(0);
+ assertThat(transaction.getEntityId(), is(0L));
+ assertThat(transaction.getPayerAccountNumber(), is(PAYER_ACCOUNT_NUMBER));
+ assertThat(transaction.getBeneficiaryAccountNumber(), is(BENEFICIARY_ACCOUNT_NUMBER));
+ assertThat(transaction.getMoneyAmount(), is(MONEY_AMOUNT));
+ assertThat(transaction.getDate(), is(CoreMatchers.notNullValue()));
+ }
+
+ @Test
+ public void testInsertFailed() throws Exception {
+ exception.expect(DataIntegrityViolationException.class);
+
+ transactionRepository.insert(new Transaction(null, BENEFICIARY_ACCOUNT_NUMBER, MONEY_AMOUNT));
+
+ }
+}
diff --git a/src/test/java/app/service/AccountManagerServiceTest.java b/src/test/java/app/service/AccountManagerServiceTest.java
new file mode 100644
index 0000000..5fe49a1
--- /dev/null
+++ b/src/test/java/app/service/AccountManagerServiceTest.java
@@ -0,0 +1,121 @@
+package app.service;
+
+import app.domain.Account;
+import app.repository.AccountRepository;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AccountManagerServiceTest {
+
+ private static String ACCOUNT_NUMBER = "12345678901234";
+ private static String ACCOUNT_NAME = "NAME";
+ private static BigDecimal ACCOUNT_MONEY_AMOUNT = new BigDecimal("100.00");
+ private static Account ACCOUNT = new Account(ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_MONEY_AMOUNT);
+
+ @InjectMocks
+ private AccountManagerService accountService;
+
+ @Mock
+ private AccountRepository accountRepository;
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void testFindByNumberSuccess() throws Exception {
+
+ when(accountRepository.findByNumber(ACCOUNT_NUMBER)).thenReturn(Arrays.asList(ACCOUNT));
+
+ Account actualAccount = accountService.findByNumber(ACCOUNT_NUMBER);
+
+ assertThat(actualAccount, is(ACCOUNT));
+ verify(accountRepository, times(1)).findByNumber(ACCOUNT_NUMBER);
+ }
+
+ @Test
+ public void testFindByNumberFail() throws Exception {
+ exception.expect(EmptyResultDataAccessException.class);
+ exception.expectMessage("No account found for number " + ACCOUNT_NUMBER);
+
+ when(accountRepository.findByNumber(ACCOUNT_NUMBER)).thenReturn(Collections.emptyList());
+
+ accountService.findByNumber(ACCOUNT_NUMBER);
+ }
+
+ @Test
+ public void testSaveSuccess() throws Exception {
+
+ when(accountRepository.insert(ACCOUNT)).thenReturn(1);
+
+ accountService.save(ACCOUNT);
+
+ verify(accountRepository, times(1)).insert(ACCOUNT);
+ }
+
+ @Test
+ public void testSaveFailNoUpdate() throws Exception {
+ exception.expect(IncorrectResultSizeDataAccessException.class);
+ exception.expectMessage("Account not saved.");
+
+ when(accountRepository.insert(ACCOUNT)).thenReturn(0);
+
+ accountService.save(ACCOUNT);
+
+ }
+
+ @Test
+ public void testSaveFailMoreThanOneFieldUpdate() throws Exception {
+ exception.expect(IncorrectResultSizeDataAccessException.class);
+ exception.expectMessage("More than once account was saved.");
+
+ when(accountRepository.insert(ACCOUNT)).thenReturn(2);
+
+ accountService.save(ACCOUNT);
+ }
+
+ @Test
+ public void testUpdateMoneyAmountSuccess() throws Exception {
+
+ when(accountRepository.updateMoneyAmount(ACCOUNT)).thenReturn(1);
+
+ accountService.updateMoneyAmount(ACCOUNT);
+
+ verify(accountRepository, times(1)).updateMoneyAmount(ACCOUNT);
+ }
+
+ @Test
+ public void testUpdateMoneyAmountFailNoUpdate() throws Exception {
+ exception.expect(IncorrectResultSizeDataAccessException.class);
+ exception.expectMessage("No accounts were updated");
+
+ when(accountRepository.updateMoneyAmount(ACCOUNT)).thenReturn(0);
+
+ accountService.updateMoneyAmount(ACCOUNT);
+ }
+
+ @Test
+ public void testUpdateMoneyAmountMoreThanOneFieldUpdate() throws Exception {
+ exception.expect(IncorrectResultSizeDataAccessException.class);
+ exception.expectMessage("More than once account was updated");
+
+ when(accountRepository.updateMoneyAmount(ACCOUNT)).thenReturn(2);
+
+ accountService.updateMoneyAmount(ACCOUNT);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/app/service/MoneyTransferServiceTest.java b/src/test/java/app/service/MoneyTransferServiceTest.java
new file mode 100644
index 0000000..7d432ab
--- /dev/null
+++ b/src/test/java/app/service/MoneyTransferServiceTest.java
@@ -0,0 +1,53 @@
+package app.service;
+
+import app.domain.Account;
+import app.domain.Transaction;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.math.BigDecimal;
+
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MoneyTransferServiceTest {
+
+ private static String PAYER_ACCOUNT_NUMBER = "12345678901234";
+ private static String BENEFICIARY_ACCOUNT_NUMBER = "12345678909876";
+ private static BigDecimal MONEY_AMOUNT = BigDecimal.TEN;
+ private static Account PAYER_ACCOUNT = new Account(PAYER_ACCOUNT_NUMBER, "NAME1", new BigDecimal("100.00"));
+ private static Account BENEFICIARY_ACCOUNT = new Account(BENEFICIARY_ACCOUNT_NUMBER, "NAME2", new BigDecimal("100.00"));
+ private static Transaction TRANSACTION = new Transaction(PAYER_ACCOUNT_NUMBER, BENEFICIARY_ACCOUNT_NUMBER, MONEY_AMOUNT);
+
+ @InjectMocks
+ private MoneyTransferService transferService;
+
+ @Mock
+ private TransactionService transactionService;
+
+ @Mock
+ private AccountService accountService;
+
+ @Before
+ public void setUp() throws Exception {
+
+ when(accountService.findByNumber(PAYER_ACCOUNT_NUMBER)).thenReturn(PAYER_ACCOUNT);
+ when(accountService.findByNumber(BENEFICIARY_ACCOUNT_NUMBER)).thenReturn(BENEFICIARY_ACCOUNT);
+ }
+
+ @Test
+ public void testTransferAmount() throws Exception {
+
+ transferService.transferAmount(TRANSACTION);
+
+ verify(accountService,times(1)).updateMoneyAmount(PAYER_ACCOUNT);
+ verify(accountService,times(1)).updateMoneyAmount(BENEFICIARY_ACCOUNT);
+
+ verify(transactionService, times(1)).save(TRANSACTION);
+ }
+
+}
diff --git a/src/test/java/app/service/TransactionManagerServiceTest.java b/src/test/java/app/service/TransactionManagerServiceTest.java
new file mode 100644
index 0000000..56f6674
--- /dev/null
+++ b/src/test/java/app/service/TransactionManagerServiceTest.java
@@ -0,0 +1,67 @@
+package app.service;
+
+import app.domain.Transaction;
+import app.repository.TransactionRepository;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+
+import java.math.BigDecimal;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TransactionManagerServiceTest {
+
+ private static final String PAYER_ACCOUNT_NUMBER = "12345678901234";
+ private static final String BENEFICIARY_ACCOUNT_NUMBER = "12345678909876";
+ private static final BigDecimal MONEY_AMOUNT = new BigDecimal("10.00");
+ private static final Transaction TRANSACTION = new Transaction(PAYER_ACCOUNT_NUMBER, BENEFICIARY_ACCOUNT_NUMBER, MONEY_AMOUNT);
+
+ @InjectMocks
+ private TransactionManagerService transactionService;
+
+ @Mock
+ private TransactionRepository transactionRepository;
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+
+ @Test
+ public void testSaveSuccess() throws Exception {
+
+ when(transactionRepository.insert(TRANSACTION)).thenReturn(1);
+
+ transactionService.save(TRANSACTION);
+
+ verify(transactionRepository, times(1)).insert(TRANSACTION);
+ }
+
+ @Test
+ public void testSaveFailNoUpdate() throws Exception {
+ exception.expect(IncorrectResultSizeDataAccessException.class);
+ exception.expectMessage("Transaction not saved.");
+
+ when(transactionRepository.insert(TRANSACTION)).thenReturn(0);
+
+ transactionService.save(TRANSACTION);
+ }
+
+ @Test
+ public void testSaveFailMoreThanOneFieldUpdate() throws Exception {
+ exception.expect(IncorrectResultSizeDataAccessException.class);
+ exception.expectMessage("More than once transaction was saved.");
+
+ when(transactionRepository.insert(TRANSACTION)).thenReturn(2);
+
+ transactionService.save(TRANSACTION);
+ }
+}
diff --git a/src/test/resources/app/repository/JdbcAccountRepositoryIT-context.xml b/src/test/resources/app/repository/JdbcAccountRepositoryIT-context.xml
new file mode 100644
index 0000000..425a54d
--- /dev/null
+++ b/src/test/resources/app/repository/JdbcAccountRepositoryIT-context.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/app/repository/JdbcTransactionRepositoryIT-context.xml b/src/test/resources/app/repository/JdbcTransactionRepositoryIT-context.xml
new file mode 100644
index 0000000..622b028
--- /dev/null
+++ b/src/test/resources/app/repository/JdbcTransactionRepositoryIT-context.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/spring/database-test-config.xml b/src/test/resources/spring/database-test-config.xml
new file mode 100644
index 0000000..dd79093
--- /dev/null
+++ b/src/test/resources/spring/database-test-config.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file