The basic idea of bank funds transfer from account A to account B that, if debiting from account A fails then the credit to account B should either never take place or be rolled back. From the user's perspective in actual bank transfers, first of all, the transaction must be created and then should be executed for processing, in our case considering as transfer happens between accounts in the same bank and same currency, hence validation should be pre-transaction record and result should be instant
Sample money transfer scenario. It could be implemented like this:
mutex.lock {
val accountA = accounts.findByName("A")
val accountB = accounts.findByName("B")
accountA.debit(transferAmount)
accountA.save()
accountB.credit(transferAmount)
accountB.save()
transfers.save(Transfer(accountA, accountB))
}The money transfer functionality handled by CreateTransferCommandHandler this class more critical part of the application because it should be executed on safe concurrency. The class contains a method named handle, when the method called and CreateTransferCommand instance passed, and it executes synchronized block provided by Kotlin which works for java threads too, it means the same account cannot start transfer simultaneously from the different threads.
In the diagram above the entry point is Transfer Router that handles HTTP Post request. The second step would be CreateTransferCommandHandler that changes Account Aggregate e.g subtracts and adds money for the current balance according to input parameters, during the action it also creates Domain Events such as Money Debited and Money Credited for each account to be able to trigger side effects across multiple aggregates in our case it triggers Transaction Aggregate using Event Store. Event Store and Command Handler implemented as an in-memory mediator based on an IoC container.
- Java Virtual Machine 8 or higher versions
- Gradle 5.6.2
To be able build standalone app run following command
./gradlew build
For running executable file simple run builded file
java -jar ./build/libs/money-transfer-0.0.1-all.jar
Get all accounts
curl --request GET \
--url http://localhost:8080/api/v1/accounts/allCreating money transfer between two accounts
curl --request POST \
--url http://localhost:8080/api/v1/transfer \
--header 'content-type: application/json' \
--data '{
"sourceAccountId" : "591f6eb1-de7e-4d25-8afa-bd82d85ee565",
"targetAccountId" : "8657792e-8329-4723-bf04-837d3649e9af",
"amount": 10.2,
"currency": "EUR",
"reference": "Some message"
}Getting account transactions
curl --request GET \
--url http://localhost:8080/api/v1/transactions/account/8657792e-8329-4723-bf04-837d3649e9afGet account balance
curl --request GET \
--url http://localhost:8080/api/v1/accounts/591f6eb1-de7e-4d25-8afa-bd82d85ee565/balance