/reactivlet-sample

Sample project for an article about adopting reactive approach in servlet applications

Primary LanguageJavaMIT LicenseMIT

ReactivLet Demo 📺

ReactivLet (“reactive” + “servlet”) is a sample Java project showcasing some techniques and solutions enabling servlet logic to run in reactive environment with minimal to no changes. This may be helpful to facilitate the smooth transition from traditional servlet stack to reactive one.

The sample accompanies the article series (in Russian only) describing the approach in detail.

Project contents

The sample is a Gradle multi-project application consisting of 3 sub-projects:

  • webmvc – a simple Spring WebMVC (servlet) application providing the only REST API method:

    • GET /{temlpate} – proxies the request to template URI of the Wiremock mock server (see below);
  • webflux – a Spring WebFlux (reactive) application providing the following REST API methods:

    • GET /reactive/{template} proxies the template query to Wiremock by means of reactive WebClient;
    • GET /sync/{template} proxies the template query to Wiremock by means of servlet RestTemplate;
    • GET /feign/{template} proxies the template query to Wiremock by means of OpenFeign client;
  • shared – an internal component (a kind of library) shared between both web applications as a dependency. Not suitable for standalone running but when included into a web application provides it with a REST API method:

    • GET /inspect – returns various data extracted from the request: cookies, headers, URI parameters and attributes.

    Beside this method, the shared component also enriches the web applications with some additional infrastructure facilities:

    • logging of arguments and the results of each @GetMapping-annotated method;
    • setting rid MDC mark in logs;
    • providing consistent access to current HTTP request by means of its HttpRequestAccessor class (much like RequestContextHolder did in Spring WebMVC).

The modules relate as follows:

Gradle modules hierarchy

There is also an additional module not directly included into Gradle modules hierarchy:

  • wiremock – standalone Wiremock distribution serving as a target for proxying request through the sample web applications. Supports two replies (declared in wiremock/mappings directory):
    • /fast – replies immediately with body {"responder":"wiremock","mode":"FAST"}
    • /slow – replies with 2 seconds delay and body {"responder":"wiremock","mode":"SLOW"}

Usage

Prerequisite: Install JDK 17 or newer version.

  1. Check out the repository to a local directory:

    $ git clone https://github.com/Toparvion/reactivlet-sample.git
    $ cd reactivlet-sample
  2. Launch Wiremock as a target for the web applications to proxy incoming requests:

    $ ./gradlew :wiremock

    This will occupy port 8082 and stay active until you stop the mock server with Ctrl+C.

  3. Open another terminal and start WebMVC application:

    $ ./gradlew :webmvc:bootRun

    This will stay active until you stop the application with Ctrl+C. By default the application listens to port 8080 but you can change it by adding --server.port=XXXX argument.

  4. Open one more terminal and start WebFlux application:

    $ gradlew :webflux:bootRun

    This will stay active until you stop the application with Ctrl+C. By default the application listens to port 8081 but you can change it by adding --server.port=XXXX argument.

  5. Keep practicing in opening new terminals and make some requests to the running applications:

    # webmvc application
    $ curl -X GET --location "http://localhost:8080/fast?rid=123"
    $ curl -X GET --location "http://localhost:8080/slow?rid=123"
    $ curl -X GET --location "http://localhost:8080/inspect?rid=123&sid=abc&rid=567" \
        -H "Accept: application/json" \
        -H "Cookie: jid=ABC; cookie2=val2"
    
    # webflux application
    $ curl -X GET --location "http://localhost:8081/reactive/fast?rid=123"
    $ curl -X GET --location "http://localhost:8081/sync/fast?rid=123"
    $ curl -X GET --location "http://localhost:8081/feign/fast?rid=123"
    $ curl -X GET --location "http://localhost:8081/inspect?rid=123&sid=abc&rid=567" \
        -H "Accept: application/json" \
        -H "Cookie: jid=ABC; cookie2=val2"
        
    # wiremock (bypass the proxy)
    $ curl -X GET --location "http://localhost:8082/fast?rid=123"
    $ curl -X GET --location "http://localhost:8082/slow?rid=123"

    Note that every request mirrors its data in logs of corresponding web application as well as on Wiremock console (except of /inspect request).

License

MIT