This is a technology demonstration project to present how to make a simple REST API service with Java 21 and Spring Boot.
The example was designed assuming following functional and non-functional requirements.
- REST API must provide an endpoint to create an account
- Account creation input data must contain: initial account balance in PLN, first name, last name.
- Account creation procedure generates unique account identifier, which is returned and must be used in subsequent REST API calls.
- REST API must provide an endpoint for a currency exchange between PLN and USD.
- Exchange rates must be fetched from a public REST API provided by NBP: http://api.nbp.pl
- REST API must provide an endpoint for fetching account data including balance in PLN and USD.
- Implementation in Java.
- Data are persisted.
- Open sourced.
- Using Maven or Gradle.
- Instruction how to run provided in README file.
Everything not specified can be designed and implemented in any desired way.
My design decisions and technology choice are:
- Java 21, as this is the current LTS Java version.
- Latest stable Spring Boot
- Maven - rationale given here: https://artofcode.wordpress.com/2017/11/17/gradle-vs-maven/
- Embedded database was selected as it is simpler then running a separate database server. H2 database was selected as SQL embedded databases has a very good Spring Boot support. Embedded H2 database (http://www.h2database.com/html/main.html) can persist data on disk, thus it is fulfilling given requirements.
- Java Bean Validation used for validation as this is supported very well by Spring Boot.
- HTTPS will be used to communicate with NBP API instead of HTTP as it is available and it's better suited for fetching critical data: https://api.nbp.pl/
- Negative HTTP response bodies have format defined by RFC-9457.
- GitHub Actions used for CI process.
Execute mvn clean verify
to build the application. As a result a JAR file will be created in
the target
subdirectory of project's root directory.
- Set the environment variable "SPRING_DATASOURCE_URL" defining a directory for database files and a database name. The last part of the path below is a database name ("h2-db").
export SPRING_DATASOURCE_URL=jdbc:h2:/some/path/h2-db
- Run JAR file with the application:
java -jar target/fx-service-example-0.0.1-SNAPSHOT.jar
By default the application starts listening on TCP port 8080.
If the above-mentioned environment variable is not set, the application defaults to start the embedded database in the in-memory mode.
There are 3 REST API endpoints supported to meet above-mentioned requirements:
- POST /accounts
- GET /accounts/{account-id}
- POST /accounts/{account-id}/fx-transactions
Execute following command when the application is running to create an account:
curl -X POST http://localhost:8080/accounts -H "Content-Type: application/json" -d '{"firstName": "Bolek", "lastName": "Nowy", "plnBalance": "1000.23"}'
The response contains full account details, including account ID:
{"id":1,"firstName":"Bolek","lastName":"Nowy","balance":{"PLN":1000.23,"USD":0.00}}
Assuming account ID is 1, use following command to fetch account details:
curl http://localhost:8080/accounts/1
Assuming you want to operate on account with ID 1, use following command to exchange 100.25 PLN to USD:
curl -X POST http://localhost:8080/accounts/1/fx-transactions -H "Content-Type: application/json" -d '{"srcCcy": "PLN", "srcAmount": "100.25", "dstCcy": "USD"}'
The operation returns a summary of an exchange if it was successful (HTTP 200):
{"srcCcy":"PLN","srcAmount":100.25,"dstCcy":"USD","dstAmount":24.02,"price":4.1740,"accountBalance":{"PLN":899.98,"USD":24.02}}
Attributes "srcAmount" and "srcCcy" inform about money that was exchanged. Attributes "dstAmount" and "dstCcy" inform what was exchange result. The attribute "price" contains price that was used in exchange. The attribute "accountBalance" contains account balance after the exchange operation.
In this mode the request body must contain "dstAmount" instead of "srcAmount" attribute:
curl -X POST http://localhost:8080/accounts/1/fx-transactions -H "Content-Type: application/json" -d '{"srcCcy": "PLN", "dstCcy": "USD", "dstAmount": "1.00"}'