ivangfr / springboot-rsocket-webflux-aop

The goal of this project is to play with RSocket protocol. For it, we will implement three Spring Boot Java applications, movie-server, movie-client-shell and movie-client-ui. As storage, it's used the reactive NoSQL database MongoDB. All the streaming of movie events and the logging are handling by AOP (Aspect Oriented Programming).

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

springboot-rsocket-webflux-aop

The goal of this project is to play with RSocket protocol. For it, we will implement three Spring Boot Java applications: movie-server, movie-client-shell and movie-client-ui. As storage, it's used the reactive NoSQL database MongoDB. All the streaming of movie events and the logging are handling by AOP (Aspect Oriented Programming).

Proof-of-Concepts & Articles

On ivangfr.github.io, I have compiled my Proof-of-Concepts (PoCs) and articles. You can easily search for the technology you are interested in by using the filter. Who knows, perhaps I have already implemented a PoC or written an article about what you are looking for.

Project Diagram

project-diagram

Applications

  • movie-server

    Spring Boot Java Web application that exposes REST API endpoints or RSocket routes to manage movies. Movies data are stored in reactive MongoDB.

    movie-server has the following profiles:

    • default

      • start REST API on port 8080 and uses HTTP
    • rsocket-tcp

      • start REST API on port 8080 and uses HTTP
      • start RSocket on port 7000 and uses TCP
    • rsocket-websocket

      • start REST API on port 8080 and uses HTTP
      • start RSocket with mapping-path /rsocket and uses WebSocket
  • movie-client-shell

    Spring Boot Shell Java application that has a couple of commands to interact with movie-server.

    The picture below show those commands

    movie-client-shell

    It has the following profiles:

    • default

      • start shell with enabled commands to call movie-server REST API endpoints using HTTP
    • rsocket-tcp

      • start shell with enabled commands to call movie-server REST API endpoints using HTTP
      • start shell with enabled commands to call movie-server RSocket routes using TCP
    • rsocket-websocket

      • start shell with enabled commands to call movie-server REST API endpoints using HTTP
      • start shell with enabled commands to call movie-server RSocket routes using WebSocket
  • movie-client-ui

    Spring Boot Java Web application that uses Thymeleaf and Websocket to show at real-time all the events generated when movies are added, deleted, liked and disliked.

    movie-client-ui

    movie-client-ui has the following profiles:

    • default

      • start REST API on port 8081 and uses HTTP
      • does not connect to movie-server through RSocket; does not receive movie events;
    • rsocket-tcp

      • start REST API on port 8080 and uses HTTP
      • connects to movie-server through RSocketusing TCP; receives movie events;
    • rsocket-websocket

      • start REST API on port 8080 and uses HTTP
      • connects to movie-server through RSocketusing WebSocket; receives movie events;

Demo

The GIF below shows a user running some commands in movie-client-shell, terminal on the right. In the right-top terminal is running movie-server and in the right-bottom, movie-client-ui. On the background, there's a browser where movie events are displayed.

demo

Prerequisites

Start Environment

Open a terminal and inside springboot-rsocket-webflux-aop root folder run

docker compose up -d

Running applications with Maven

  • movie-server

    Open a new terminal and, inside springboot-rsocket-webflux-aop root folder, run one of the following profile's command

    Profile Command
    rsocket-tcp ./mvnw clean spring-boot:run --projects movie-server -Dspring-boot.run.profiles=rsocket-tcp
    rsocket-websocket ./mvnw clean spring-boot:run --projects movie-server -Dspring-boot.run.profiles=rsocket-websocket
    default ./mvnw clean spring-boot:run --projects movie-server
  • movie-client-shell

    Open a new terminal and, inside springboot-rsocket-webflux-aop root folder, run the following command to build the executable jar file

    ./mvnw clean package --projects movie-client-shell -DskipTests
    

    To start movie-client-shell, run the profile's command you picked to run movie-server

    Profile Commands
    rsocket-tcp export SPRING_PROFILES_ACTIVE=rsocket-tcp && ./movie-client-shell/target/movie-client-shell-1.0.0.jar
    rsocket-websocket export SPRING_PROFILES_ACTIVE=rsocket-websocket && ./movie-client-shell/target/movie-client-shell-1.0.0.jar
    default export SPRING_PROFILES_ACTIVE=default && ./movie-client-shell/target/movie-client-shell-1.0.0.jar
  • movie-client-ui

    Open a new terminal and, inside springboot-rsocket-webflux-aop root folder, run the profile's command you picked to run movie-server

    Profile Command
    rsocket-tcp ./mvnw clean spring-boot:run --projects movie-client-ui -Dspring-boot.run.profiles=rsocket-tcp
    rsocket-websocket ./mvnw clean spring-boot:run --projects movie-client-ui -Dspring-boot.run.profiles=rsocket-websocket
    default ./mvnw clean spring-boot:run --projects movie-client-ui

Running applications as Docker containers

  • Build Docker images

    • In a terminal, make sure you are in springboot-rsocket-webflux-aop root folder
    • Run the following script to build the Docker images
      • JVM
        ./docker-build.sh
        
      • Native (it's not working yet, see Issues)
        ./docker-build.sh native
        
  • Environment variables

    • movie-server

      Environment Variable Description
      MONGODB_HOST Specify host of the Mongo database to use (default localhost)
      MONGODB_PORT Specify port of the Mongo database to use (default 27017)
    • movie-client-shell

      Environment Variable Description
      MOVIE_SERVER_HOST Specify host of the movie-server to use (default localhost)
    • movie-client-ui

      Environment Variable Description
      MOVIE_SERVER_HOST Specify host of the movie-server to use (default localhost)
  • Start Docker containers

    • In a terminal, make sure you are inside springboot-rsocket-webflux-aop root folder
    • Run following command
      • rsocket-tcp
        ./start-server-and-ui.sh rsocket-tcp && ./start-shell.sh rsocket-tcp
        
      • rsocket-websocket
        ./start-server-and-ui.sh rsocket-websocket && ./start-shell.sh rsocket-websocket
        
      • default
        ./start-server-and-ui.sh && ./start-shell.sh
        

Application's URL

Application Type Transport URL
movie-server RSocket TCP tcp://localhost:7000
movie-server RSocket WebSocket ws://localhost:8080/rsocket
movie-server REST HTTP http://localhost:8080
movie-client-ui Website HTTP http://localhost:8081

Note: you can see the clients connected to movie-server by calling the info actuator endpoint

curl -i localhost:8080/actuator/info

Playing Around with movie-client-shell commands

Note: to run the commands below, you must start movie-server and movie-client-shell with rsocket-tcp or rsocket-websocket profiles

  • Open a browser and access movie-client-ui at http://localhost:8081

  • Go to movie-client-shell terminal

  • Add a movie using RSocket (Request-Response)

    add-movie-rsocket --imdb aaa --title "RSocketland"
    

    It should return

    {"imdb":"aaa","title":"RSocketland","lastModifiedDate":"2020-07-20T12:43:39.857248","likes":0,"dislikes":0}
    

    A + action should be displayed in movie-client-ui

  • Add a movie using REST

    add-movie-rest --imdb bbb --title "I, REST"
    

    It should return

    {"imdb":"bbb","title":"I, REST","lastModifiedDate":"2020-07-20T12:44:13.266657","likes":0,"dislikes":0}
    

    A + action should be displayed in movie-client-ui

  • Send a like to RSocketland movie using RSocket (Fire-And-Forget)

    like-movie-rsocket --imdb aaa
    

    It should return

    Like submitted
    

    A thumbs-up action should be displayed in movie-client-ui

  • Get all movies using RSocket (Request-Stream)

    get-movies-rsocket
    

    It should return

    {"imdb":"aaa","title":"RSocketland","lastModifiedDate":"2020-07-20T12:56:34.565","likes":1,"dislikes":0}
    {"imdb":"bbb","title":"I, REST","lastModifiedDate":"2020-07-20T12:56:26.846","likes":0,"dislikes":0}
    
  • Select movies using RSocket (Channel)

    select-movies-rsocket --imdbs aaa,bbb
    

    It should return

    | IMBD: aaa        | TITLE: RSocketland                    | LIKES: 1     | DISLIKES: 0     |
    | IMBD: bbb        | TITLE: I, REST                        | LIKES: 0     | DISLIKES: 0     |
    
  • Delete movie RSocketland using RSocket (Request-Response) and movie I, REST using REST

    delete-movie-rsocket --imdb aaa
    delete-movie-rest --imdb bbb
    

    It should return, as response, the IMDB of the movies

    A - actions should be displayed in movie-client-ui

  • Simulation

    There are two scripts that contain some commands to add, retrieve, like, dislikes and delete movies. One uses REST and another RSocket to communicate with movie-server. At the end of the script execution, it's shown the Execution Time in milliseconds.

    • If you are running the applications with Maven

      • REST
        script ../src/main/resources/simulation-rest.txt
        
      • RSocket
        script ../src/main/resources/simulation-rsocket.txt
        
    • If you are running the applications as Docker containers

      • REST
        script /app/resources/simulation-rest.txt
        
      • RSocket
        script /app/resources/simulation-rsocket.txt
        

Useful Commands

  • MongoDB

    Find all movies

    docker exec -it mongodb mongosh moviedb
    db.movies.find()
    

    Type exit to get out of MongoDB shell

Shutdown

  • To stop movie-client-shell, go to the terminal where it is running and type exit
  • To stop movie-server and movie-client-ui
    • If you start them with Maven, go to the terminals where they are running and press Ctrl+C
    • If you start them as Docker containers, go to a terminal and, inside springboot-rsocket-webflux-aop root folder, run the following command
      ./stop-server-and-ui.sh
      
  • To stop and remove docker compose mongodb container, network and volumes, go to a terminal and, inside springboot-rsocket-webflux-aop root folder, run the command below
    docker compose down -v
    

Cleanup

To remove the Docker images created by this project, go to a terminal and, inside springboot-rsocket-webflux-aop root folder, run the script below

./remove-docker-images.sh

References

Issues

movie-server

Docker native image builds and starts up successfully. However, it doesn't accept connections even using JVM version of movie-client-ui and movie-client-shell.

movie-client-ui

After building and starting the Docker native image successfully, the app looks fine (i.e., we can open the page, websocket is connected, etc). However, it is not connecting to movie-server.

movie-client-shell

After building the Docker native image and running it successfully, we have some problems such as

  • there is the following WARN
    Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
    
  • the autocomplete is not working;
  • when tried to run one of script files (simulation-rest.txt or simulation-rsocket.txt) there is the following exception
    movie-client-shell> script /app/resources/simulation-rest.txt
    java.lang.NullPointerException
    Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
    movie-client-shell> stacktrace
    java.lang.NullPointerException
    	at java.base@17.0.7/java.io.FileInputStream.<init>(FileInputStream.java:149)
    	at java.base@17.0.7/java.io.FileReader.<init>(FileReader.java:75)
    	at org.springframework.shell.standard.commands.Script.script(Script.java:60)
    	at java.base@17.0.7/java.lang.reflect.Method.invoke(Method.java:568)
    	at org.springframework.shell.command.invocation.InvocableShellMethod.doInvoke(InvocableShellMethod.java:306)
    	at org.springframework.shell.command.invocation.InvocableShellMethod.invoke(InvocableShellMethod.java:232)
    	at org.springframework.shell.command.CommandExecution$DefaultCommandExecution.evaluate(CommandExecution.java:227)
    	at org.springframework.shell.Shell.evaluate(Shell.java:248)
    	at org.springframework.shell.Shell.run(Shell.java:159)
    	at org.springframework.shell.jline.InteractiveShellRunner.run(InteractiveShellRunner.java:73)
    	at org.springframework.shell.DefaultShellApplicationRunner.run(DefaultShellApplicationRunner.java:65)
    	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762)
    	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:319)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
    	at com.ivanfranchin.movieclientshell.MovieClientShellApplication.main(MovieClientShellApplication.java:10)  
    

About

The goal of this project is to play with RSocket protocol. For it, we will implement three Spring Boot Java applications, movie-server, movie-client-shell and movie-client-ui. As storage, it's used the reactive NoSQL database MongoDB. All the streaming of movie events and the logging are handling by AOP (Aspect Oriented Programming).


Languages

Language:Java 87.7%Language:Shell 4.8%Language:HTML 4.1%Language:JavaScript 3.4%