Resource service is a simple microservice with purpose to provide a rudimentary CRUD API to PERSON database, which is used to hold the following data in each record:
"id": Long,
"first_name": String,
"last_name": String,
"age": Integer,
"favourite_color": String
Main features:
-
built on the basis of Spring Boot 2.4.x with extensive use of Reactive Programming patterns (in this project I am using Spring WebFlux)
-
a persistence layer is built on Reactive H2 In-Memory database
-
contains fine grade access security on the basis of Spring Security
Here are the reasons behind my choice of technologies:
Spring WebFlux is a reactive web framework based on a reactive HTTP layer; such apps can be deployed on Netty or Undertow (with native adapters) or Jetty/Tomcat/any Servlet 3.1 (In this implementation I am using Netty). Reactive approach can be beneficial for efficiency and scalability for workloads dealing with lots of latency and concurrency. In other words reactive approach allows to create responsive, resilient, elastic and message-driven systems.
Spring's reactive concepts have been taken as is from Java 8's Reactor Core library, which implements the reactive programming paradigm. Reactor Core in its turn is built on top of Reactive Streams Specification, which is the industry standard for building reactive applications in the Java world. Finally, all these technologies have been refined and collected under the hood of Spring WebFlux.
Spring WebFlux is an ideal choice if application deals with streams of data (input and output), and is a part of some bigger system where reliability and performance of each component matters (being asynchronous system can deal with latencies and be more scalable)
As for security, fine-grained authorization from Spring Security's modules allows to secure the business tier through
method annotation and the use of interface-based proxies to accomplish AOP. For demonstration purposes
I added default user with username=user and password=123 which has two roles – DB_USER
and DB_ADMIN
In real production system makes sense to use industry-standard oauth2 authorization flow, and implement centralized authorization through separate oauth2 servers (f.e. those on the basis OpenID Connect and OAuth 2.0 API)
Back-end has two different end-points, /api/persons
and /api/persons/{personId}
Currently five methods are supported with the following signature:
Verb | Endpoint |
---|---|
GET | /api/persons |
GET | /api/persons/{personId} |
POST | /api/persons |
PUT | /api/persons |
DELETE | /api/persons/{personId} |
Full API Documentation for back-end server's API is available on http://localhost:9090/api/documentation/swagger-ui/
Swagger UI works in the latest versions of Chrome, Safari, Firefox, and Edge.
- The following command builds image with tag resource-service:1.0. Note the dot at the end of the command. This command must be run from the root directory.
sudo docker build -t resource-service:1.0 .
- The next command instantiates and expose service at localhost:9090:
sudo docker run -p 9090:9090 resource-service:1.0
In order to build and run both back-end the following prerequisites are needed:
Run from the project's root directory:
mvn clean package
Run server as follows:
java -jar resource-1.0.0-SNAPSHOT.jar
Server will start on localhost:9090 address. One can point browser to http://localhost:9090/api/documentation/swagger-ui/ to see API documentation
On first request server will ask to authorize: use the following username/password pair:
Username: user
Password: 123
There are several integration tests written for web and business layers. I used the most popular testing frameworks in the Java ecosystem - JUnit 5 and Mockito, plus out-of-the-box functionality proposed by Spring Boot.
One can test endpoints manually, fe. using curl:
curl -X GET "http://localhost:9090/api/persons" --user user:123 -H "accept: */*"