Skip to content

Spring 5 showcase application with a Thymeleaf HTML5 interface

License

Notifications You must be signed in to change notification settings

danielfernandez/reactive-matchday

Repository files navigation

Reactive MatchDay

Reactive MatchDay is a testing Java application that uses the following technology stack:

  • Thymeleaf 3.0 (master:3.0.9.RELEASE, dev:3.0.10-SNAPSHOT)
  • Spring Boot 2.0.0 (master:2.0.0.M5, dev:2.0.0.BUILD-SNAPSHOT)
  • Spring Framework 5 (master:5.0.0.RELEASE, dev:5.0.1.BUILD-SNAPSHOT)
  • Spring WebFlux (master:5.0.0.RELEASE, dev:5.0.1.BUILD-SNAPSHOT)
  • Spring Data MongoDB (Reactive) (master:2.0.0.RELEASE, dev:2.0.1.BUILD-SNAPSHOT)
  • MongoDB (3.4+)

Highlights of this application are:

  • Use of Thymeleaf's integration module for Spring 5's WebFlux reactive web framework.
  • Use of Thymeleaf's data-driven support for rendering HTML in a reactive-friendly manner.
  • Use of Server-Sent Events (SSE) rendered in HTML by Thymeleaf from a reactive data stream.
  • Use of Server-Sent Events (SSE) rendered in JSON by Spring WebFlux from a reactive data stream.
  • Use of Spring Data MongoDB's reactive (Reactive Streams) driver support.
  • Use of Spring Data MongoDB's support for infinite reactive data streams based on MongoDB tailable cursors.
  • Use of Thymeleaf's fully-HTML5-compatible syntax
  • Use of many weird, randomly generated team and player names.

Running

First make sure MongoDB (3.4+) is running:

$ mongod [your options]

By default this application will expect MongoDB running on localhost with a default configuration and no authentication, and it will create a database called matchday in your server. If you need a different configuration you can adjust the connection at the Spring Boot application.properties file in the app.

Once MongoDB is running, just execute from the project's folder:

$ mvn -U clean compile spring-boot:run

This should start the Spring Boot 2.0 + Spring 5 WebFlux managed Netty HTTP server on port 8080. It also starts two agents, separate threads which insert random match events and match comments into MongoDB collections (each n seconds) so that the web interface has some data to show.

Once started, point your browser to http://localhost:8080:

Matchday: matches page

This first page presents a list of the (randomly generated) football matches that are currently being played in our league. This list of matches is rendered by from a @Controller which includes a Flux<MatchInfo> object in the Model, then calls a Thymeleaf view to be rendered. Before actually rendering, Spring WebFlux will fully resolve the Flux (non-blocking) so that Thymeleaf can iterate it.

If you click on See Match:

Matchday: match page

This page allows us to follow a specific match.

On the left side, the current score and the list of events is rendered by means of HTML Server-Sent Events (SSE) retrieved by an EventSource JavaScript object, which calls a @Controller that retrieves the match events as a MongoDB tailable cursor (see here) in the form of a Flux<MatchEvent>. This is put into the model as a Thymeleaf data-driver context variable so that Thymeleaf can execute in a reactive-friendly manner and produce SSE events rendered in HTML in a reactive way, as MongoDB notifies the application of the existence of new events in the database. So it is MongoDB who effectively pushes its new data into the application, triggering the rendering of a chunk of HTML and its sending to the browser, all of this in a reactive, non-blocking manner.

On the right side, the comments for the match are retrieved in two steps:

1st a list of the comments so far (until the moment the @Controller executes) are retrieved at the server side and put into a Thymeleaf data-driver context variable, so that Thymeleaf renders them into HTML in a reactive-friendly way (non-blocking) as they are returned by MongoDB. This is not a tailable cursor, so the query cursor actually completes.

2nd, once the list reaches the browser, another EventSource JavaScript object performs a call to a different @Controller, which this time collects the rest of the match comments (the ones generated after the moment the page was rendered) in the form of another tailable cursor, and renders them in JSON (@ResponseBody). This way MongoDB will be able to push new comments inserted by the comments agent directly towards the browser in the form of JSON-rendered Server-Sent Events (SSE), which a bit of JavaScript at the browser then will parse and insert into the Document Object Model.


NOTE: This demo application does not work (or style properly) in Microsoft IE/Edge, due to the lack of support for EventSource in these browsers. Several polyfill options exist to palliate this, but they have not been applied to this application for the sake of simplicity.