This is in continuation with my synchronized implementation of a bank account in Java. I am trying to implement bank accounts repository and method to transfer money from one account to another. My implementation for the account and the repository looks like:
Account:
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Class to represent an account, it also provides with methods to add and withdraw amount from the
* account.
*
* @author Karan Khanna
* @version 1.0
* @since 3/17/2019
*/
public class Account {
private final ReadWriteLock accountLock;
private BigDecimal balance;
private final String accountNumber;
private final String accountHolder;
public Account(String accountNumber, String accountHolder) {
this.balance = new BigDecimal(0);
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.accountLock = new ReentrantReadWriteLock();
}
public String getAccountNumber() {
return accountNumber;
}
public String getAccountHolder() {
return accountHolder;
}
public ReadWriteLock getAccountLock() {
return accountLock;
}
public double getBalance() {
this.accountLock.readLock().lock();
try {
return this.balance.setScale(2, RoundingMode.HALF_DOWN).doubleValue();
} finally {
this.accountLock.readLock().unlock();
}
}
public void addAmount(double amount) {
this.accountLock.writeLock().lock();
try {
this.balance = this.balance.add(BigDecimal.valueOf(amount));
} finally {
this.accountLock.writeLock().unlock();
}
}
public void withdrawAmount(double amount) {
this.accountLock.writeLock().lock();
try {
this.balance = this.balance.subtract(BigDecimal.valueOf(amount));
} finally {
this.accountLock.writeLock().unlock();
}
}
}
AccountsRepository:
import static java.lang.String.format;
import java.util.HashMap;
import java.util.Map;
import org.spituk.banking.app.repositories.AccountsRepository;
import org.spituk.banking.app.vo.Account;
/**
* Map based account repository.
*
* @author Karan Khanna
* @version 1.0
* @since 3/17/2019
*/
public class AccountsRepositoryImpl implements AccountsRepository {
private final static String SOURCE_ACCOUNT_DONOT_EXIST = "Source account number %s don't exist.";
private final static String DESTINATION_ACCOUNT_DONOT_EXIST = "Destination account number %s don't exist.";
private final static String NOT_ENOUGH_BALANCE = "Account number %s don't have enough balance.";
private final Map<String, Account> accountMap;
public AccountsRepositoryImpl() {
this.accountMap = new HashMap<>();
}
@Override
public void transferAmount(String accountNumberFrom, String accountNumberTo, double amountToTransfer) throws IllegalArgumentException {
if (accountMap.containsKey(accountNumberFrom)) {
if(accountMap.get(accountNumberFrom).getBalance() < amountToTransfer) {
if(accountMap.containsKey(accountNumberTo)) {
Account accountFrom = accountMap.get(accountNumberFrom);
Account accountTo = accountMap.get(accountNumberTo);
accountFrom.getAccountLock().writeLock().lock();
accountTo.getAccountLock().writeLock().lock();
try {
accountFrom.withdrawAmount(amountToTransfer);
accountTo.addAmount(amountToTransfer);
} finally {
accountFrom.getAccountLock().writeLock().unlock();
accountTo.getAccountLock().writeLock().unlock();
}
} else {
throw new IllegalArgumentException(format(DESTINATION_ACCOUNT_DONOT_EXIST, accountNumberTo));
}
} else {
throw new IllegalArgumentException(format(NOT_ENOUGH_BALANCE, accountNumberFrom));
}
} else {
throw new IllegalArgumentException(format(SOURCE_ACCOUNT_DONOT_EXIST, accountNumberFrom));
}
}
}
I am looking for feedback for the implementation.