/reactive-rest-api

Reactive Rest API with Spring Boot + WebFlux

Primary LanguageJava

Reactive Rest API with Spring Boot + WebFlux

Java CI with Maven


This is an boilerplate example of Reactive Rest API with Spring Boot + WebFlux for modern non-blocking rest api development.

It diplays the basic usage of reactive web components via 2 different approaches (both endpoints behave exactly same but are wired up differently).

1st endpoint "/prices/btc/{currency}":

  • annotation-based reactive components: RestController/RequestMapping/GetMapping and WebClient (the good ole way)

2nd endpoint "/prices2/btc/{currency}":

  • functional routing and handling: Router returns ServerResponse, Handler processes ServerRequest

The sample service calls out to Coinbase-API to get PriceData, and returns PriceInfo model containing "price", "currency", and "satsPerFiat":

  • price: decimal amount with 2-decimal points in requested currency
  • currency: requested currency code
  • satsPerFiat: number of satoshis (unit of bitcoin) per requested fiat currency unit

Highlights

  • Spring Boot/WebFlux:
    • uses @Value for constructor injection of config properties from application.yaml
    • application.yaml defines multi-environment properties in single file (can be split up into application-test.yml, application-dev.yml, etc)
    • simple StopWatch to measure time between when Mono is subscribed to, and when Mono completes
  • JUnit5 enabled (see pom.xml's "org.junit.jupiter" dependencies)
    • parameterized unit tests via @ParameterizedTest and @ValueSource
    • testing WebClient with MockWebServer
  • integration tests:
    • uses WebTestClient over http connection to test server for success/failure (can be used with mock req/resp but NO mocks are used in this case)
    • WebTestClient's benefit is the fluent API for verifying responses (expectBody() etc.. see tests)
  • logging:
    • log4j2 enabled via "spring-boot-starter-log4j2" (instead of logback spring default)
    • log4j2-spring.xml defines log patterns (xml could be replaced with YAML/JSON if needed)
  • maven :
    • some example plugins configured - maven-dependency-plugin/maven-enforcer-plugin/maven-checkstyle-plugin
  • metrics :
    • Spring's Actuator w/Micrometer metrics including Prometheus
    • spring actuator endpoints are enabled via application.yaml, and maven dependency (see pom.xml) to enable prometheus
  • spring-boot-devtools (aids local development)
  • Docker: sample Dockerfile and docker-compose included

Custom Log4j2 logging: Custom Logging


Usage

Running Application

You can run spring-boot ReactiveRestApiApplication in your favorite IDE like VSCode. Dockerfile and docker-compose included for convenience (defaults from .env file will be used if not passed).

  • Run with docker-compose:

    $ docker-compose up
    
  • Alternatively, you can also pass in custom JAVA_OPTS like so:

    $ JAVA_OPTS="-Xmx512m" docker-compose up
    
  • plain "docker" command

    docker run -e JAVA_OPTS="-Xmx512m" -p8080:8080 snazzybytes/reactive-rest-api
    
  • "Dockerfile" is the optimized multi-stage build

  • "Dockerfile-simple" is basic non-optimized build (you can ignore this one, only for illustration purposes)

Request:

# 2 reactive endpoints w/ same response
GET http://localhost:8080/prices/btc/USD

GET http://localhost:8080/prices2/btc/EUR

Response:

// success - PriceInfo response
{
  "price": "19764.81",
  "currency": "EUR",
  "satsPerFiat": "5059"
}
// error - bad request  (custom exception handler response with sample json)
{
  "errors": [
    {
      "id": "invalid_request",
      "message": "Currency is invalid"
    }
  ]
}

Reference Documentation