This repository is a clone of Reactive Spring Forex Trade [ https://github.com/gavinklfong/reactive-spring-forex-trade ]. This project converted the implementation to servlet. It is to demonstrate the blocking technology of Spring framework Servlet MVC.
It is an API service which serves the use case of foreign currency trading. Here is list of API endpoints:
- [GET] /rates/latest/ : Fetch the latest foreign currency rates
- [GET] /rates/book : Reserve an exchange rate
- [GET] /deals : Fetch list of deals of specific customer
- [POST] /deals : Submit a new foreign exchange deal
Maven pom.xml was generated on Spring Initializr with the following dependent libraries:
- Spring Web - Web Framework of blocking operations
- Spring Data JPA - Persistent data access
- Spring Validation - Validation definition using annotations
- H2 Database - In-memory database for testing
This application depends on external service for the retrieval of the latest currency exchange rate.
The service is provided by a mock server, so you need firstly to install json server on your machine
npm install -g json-server
This is Maven project, you can clone this repository to your local machine and then use maven command to build and running this application.
You can follow the commands below:
Build:
json-server ./mock-server/mock-data.json
mvn install
Run:
mvn spring-boot:run
Alternatively, you can run this application using the published docker image.
docker run --rm -p 8080:8080 whalebig27/servlet-spring-forex-trade
The Use Case is a foreign currency trade service. Due to a constant fluctuation of currency prices, customers are only informed of the exact exchange rate upon completion of transaction posting. Some people are not comfortable with making a deal without knowing the cost before making a deal.
In order to offer a better customer experience, some financial institutions allow customers to reserve an exchange rate so that customers are well informed of the rate prior to transaction submission. Certainly, such rate booking is only valid within a short period of time for sake of risk management. In addition, different preferential rates would be offered to customers with different account tiers.
The use case diagram below shows the simplified version of forex trade service with 4 functions:
-
Retrieve the latest forex rates
-
Book forex rate
-
Post forex trade deal. it includes rate booking as customers need to have a valid rate booking prior to transaction submission.
-
Retrieve list of forex transaction of a customer
I published an article in medium.com for about the high level technical design of this system. You can refer to this link here:
Spring — A Faster Way To Build Production-Ready API in a Well- Defined Structure
Application specific configuration resides in spring boot default configuration file - applicaton.yaml
- [app.rate-booking-duration] - Valid period of rate booking in second.
- [app.default-base-currency] - Default base currency.
- [app.forex-rate-api-url] - External API service for currency rate retrieval
There are 3 entities Customer, Rate Booking and Trade Deal with one-to-many relationship.
The whole system consists of controllers, services and repositories. Each type component is assigned with a distinct role:
- Controller: Expose business service to HTTP and handle all system logic related to HTTP protocol
- Service: Integrate various component to business logic
- Repository: The interface for access to persistent store
Illustration of the interaction between components is shown in the data flow diagram below
Unit test code is built for each components. To isolate the target component, all other components the target depends on are mocked. In order to speed test execution, sliced spring context is loaded, meaning that only necessary spring bean will be initialized and injected.
Controller
- Service component is mocked for testing on controller
- Use of @WebFluxTest annotation to loaded sliced spring context with the target controller class
Service
- Repository component is mocked for testing on service.
- Use of @SpringJUnitConfig and @ContextConfiguration annotation to loaded sliced spring context with the target service class
Repository
- In-memory database will be used for testing on repository.
- Use of @DataJpaTest annotation to load sliced spring context
Next, end-to-end test is executed as if a real application. Thus, spring context is fully loaded using @SpringBootTest annotation
WebTestClient is used as API client which triggers HTTP requests to API endpoints and verify the actual result.
This sample demonstrates the contract test on the provider side. The test reads contract definition from resource folder "pacts" and verify whether the forex APIs conforms to the contract.