Building Reactive Java Applications with Spring Framework

Pieter Humphrey - Jun 29 '22 - - Dev Community

Image description

In one of our many free tutorials on DataStax Developers YouTube channel, we walked you through how to build a reactive implementation of Spring PetClinic in Apache Cassandra® using Spring WebFlux. The full series is available on YouTube.

If you’re a Java developer who uses the Spring ecosystem, you’ve probably seen the Spring Pet Clinic. In this workshop, we will walk you through a new reactive implementation of the Pet Clinic backend that uses Spring WebFlux and Apache Cassandra® (via DataStax Astra DB).

The cloud-native database-as-a-service built on Cassandra fits the highly concurrent, non-blocking nature of our reactive application. We’ll do all of our work in the cloud with Gitpod’s open-source, zero-install and collaborative development environment.

Image description

Figure 1: A REST API using the Spring framework.

The steps we will take you through are:

  • Setting up Astra database
  • Theory: synchronous vs. asynchronous vs. reactive programming
  • Using the Gitpod platform
  • Introducing the Spring Boot and WebFlux frameworks
  • Reviewing backend code
  • Starting frontend application

Setting up your free Astra database

DataStax Astra DB, built on the best distribution of Cassandra, provides the ability to develop and deploy data-driven applications with a cloud-native service, without the hassles of database and infrastructure administration. By automating tuning and configuration, DataStax Astra radically simplifies database operations.

Image description

Figure 2: Datastax Astra DB Benefits.

Follow the step-by-step instructions to create your Astra database, and once your database is ready, you can copy your credentials over to GitHub.

Synchronous vs. asynchronous vs. reactive programming

Most Java developers use synchronous programming. When you initiate a session, you execute quickly and you will get a response. Then you send the parameter to the API, and the driver will create a query. You bind the parameter that simply maps the parameter to the query. You execute the query and get back an object called a ResultSet.

Image description

Figure 3: Synchronous queries weaknesses.

The issue with synchronous programming is that you need to wait. It can take a lot of time if you are querying for a lot of data, or a big cluster. Although synchronous programming is very simple, it can block communication. This means that nothing else in the application proceeds until the result from the query is returned. The application blocks for the entire round trip, from when the query is first sent to the database until the results are retrieved and returned to the application.

The advantage of synchronous queries, however, is that it is simple to tell when a query completes, so the execution logic of the application is easy to follow. However, synchronous queries cause poor application throughput.

Image description

Figure 4: Asynchronous queries weaknesses.

An asynchronous query executes call does not block for results. With asynchronous queries, you will put the parameter in to prepare your queries, bind the parameters to your queries, and execute the query.

But instead of waiting for the result, the customer and the driver will immediately give you an object called a completion stage. A future is returned from the asynchronous execute call. A future is a placeholder object that stands in for the result until the result is returned from the database. Depending on the driver and feature set of the language, this future can facilitate asynchronous processing of results. This typically allows high throughput. However, because you can process the result only when you get a callback, this can create sync resistance.

Image description

Figure 5: The Reactive Manifesto.

Now, coming to the reactive manifesto, the programming offers what is missing with the synchronous-only stack by achieving a responsive service. This means that the system always responds in a timely manner and stays responsive even in the face of any failure. It also offers a scale-out dynamic.

When it comes to huge volumes of data or multi-users, we often need asynchronous processing to make our systems fast and responsive. In Java, a representative of old object-oriented programming, asynchronicity can become really troublesome and make the code hard to understand and maintain. So, reactive programming is especially beneficial for this ‘purely’ object-oriented environment as it simplifies dealing with asynchronous flows.

Image description

Figure 6: Reactive Queries.

Using the GitPod platform

Gitpod is an open-source Kubernetes application providing prebuilt, collaborative development environments in your browser. Gitpod provides step-by-step screenshots to launch and build the Spring PetClinic Reactive backend application, created by our special workshop guest, Moritz Eysholdt from TypeFox.

Image description

Figure 7: When Gitpod finishes building the app, a new tab will open in your browser showing the following.

Introducing the Spring Boot and WebFlux frameworks

With its simple abstraction, Spring Reactor is a popular framework for Java from Spring developers. Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring enables you to build applications from “plain old Java objects” (POJOs) and to apply enterprise services non-invasively to POJOs.

Image description

Figure 8: What Spring can do.

We will also introduce Spring Boot, a tool that makes developing web applications and microservices with Spring Framework faster and easier. Spring Boot can create stand-alone Spring applications (without deploying WAR files), simplify your build configuration, and automatically configure Spring and 3rd party libraries. Spring Boot also has production-ready features such as metrics, health checks, and externalized configuration.

At the heart of the Spring Framework are two fundamental features: inversion of control (IoC) and dependency injection (DI).

  • Inversion of control essentially transfers the control of objects to the Spring Framework. Unlike traditional programming, where custom code makes calls to a library, IoC allows the framework to control the flow of a program. This keeps Java classes independent of each other for increased modularity and extensibility.
  • Dependency injection is a pattern in Spring that’s used to implement IoC, where the Spring container is in charge of “injecting” objects into the right dependencies. This allows for the loose coupling of components and shifts the responsibility of managing components onto the container.

Image description

Figure 9: How Spring Boot works.

Reviewing backend code

Let’s have a look inside the main component spring-petclinic-reactive to see which libraries and frameworks have been used.

Image description

Figure 10: Understanding the architecture.

  • Spring-boot: Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can “just run”. We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.
  • Spring-Security: Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements.
  • Spring-WebFlux: Spring sub-framework to create Reactive Rest Endpoint.
  • Spring-Actuator: Expose Endpoints to expose metrics to third party systems. Examples are health, infos, jmx,and prometheus.
  • Spring-Test: Enabled unit testing and mocking with Spring configuration and beans.
  • Spring-Cloud: Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, cluster state). Coordination of distributed systems leads to boilerplate patterns, and using Spring Cloud developers can quickly stand up services and applications that implement those patterns. They will work well in any distributed environment, including the developer’s own laptop, bare metal data centers, and managed platforms such as Cloud Foundry.
  • SpringFox (Swagger): Annotation-based rest documentation generation and test client generation (swagger-ui).

To understand the underlying data model implemented in Apache Cassandra, check out our Gitpod guide.

Starting frontend application

Image description

Figure 11: Frontend of Spring PetClinic.

Once you configure and run the application, you can also test CRUD with Swagger as a hands-on exercise as follows:

Image description

Figure 12: Test CRUD with Swagger.

And with that, we conclude our workshop on a reactive implementation of Spring PetClinic with Cassandra. To keep learning about open-source technologies and how to use them, simply register for any of our free DataStax Workshops to get started on your next big app.

Explore more tutorials on our DataStax Developers YouTube channel and subscribe to our event alert to get notified about new developer workshops. For exclusive posts on all things data: Cassandra, streaming, Kubernetes, and more; follow DataStax on Medium.

Resources

  1. Build a Reactive app in Apache Cassandra™ with Spring Framework
  2. Github Workshop Spring Reactive
  3. Join our Discord: Fellowship of the (Cassandra) Rings
  4. Astra DB — Managed Apache Cassandra as a Service
  5. Building Microservices with Spring Data, Cassandra, and Stargate.io
  6. DataStax Academy
  7. DataStax Certifications
  8. DataStax Workshops
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .