DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Trending

  • The Modern Data Stack Is Overrated — Here’s What Works
  • Understanding Java Signals
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • A Guide to Container Runtimes
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring WebFlux: First Steps

Spring WebFlux: First Steps

Spring 5 comes with WebFlux — support for reactive programming practices in Spring applications. See how to introduce it into an old annotation-style controller.

By 
Biju Kunjummen user avatar
Biju Kunjummen
·
Mar. 22, 17 · Tutorial
Likes (14)
Comment
Save
Tweet
Share
81.7K Views

Join the DZone community and get the full member experience.

Join For Free

Spring WebFlux is used for denoting the Reactive programming support in Spring's web layer. It provides support for both creating reactive, server-based web applications and also has client libraries to make remote REST calls.

In this post, I will demonstrate a sample web application that makes use of Spring WebFlux. As detailed here, the WebFlux support in Spring 5+ supports two different programming styles — the traditional, annotation-based style and the new functional style. In this post, I will be sticking to the traditional annotation style and try to follow it up in another blog post detailing a similar application, but with endpoints defined in a functional style. My focus is going to be the programming model.

Data and Services Layer

I have a fairly simple REST interface supporting CRUD operations of a Hotel resource with a structure along these lines:

public class Hotel {
    private UUID id;
    private String name;
    private String address;
    private String state;
    private String zip;
    ....
}


I am using Cassandra as a store of this entity, and using the reactive support in Spring Data Cassandra allows the data layer to be reactive, supporting an API that looks like this. I have two repositories here, one facilitating the storage of the Hotel entity above, and another maintaining duplicated data, which makes searching for a Hotel entity by its first letter a little more efficient:

public interface HotelRepository  {
    Mono<Hotel> save(Hotel hotel);
    Mono<Hotel> update(Hotel hotel);
    Mono<Hotel> findOne(UUID hotelId);
    Mono<Boolean> delete(UUID hotelId);
    Flux<Hotel> findByState(String state);
}

public interface HotelByLetterRepository {
    Flux<HotelByLetter> findByFirstLetter(String letter);
    Mono<HotelByLetter> save(HotelByLetter hotelByLetter);
    Mono<Boolean> delete(HotelByLetterKey hotelByLetterKey);
}


The operations that return one instance of an entity now return a Mono type, and operations that return more than one element return a Flux type.

Given this, let me touch on one quick use of returning reactive types: When a Hotel is updated, I have to delete the duplicated data maintained via the HotelByLetter repository and recreate it again. This can be accomplished with something like the following, using the excellent operators provided by the Flux and Mono types:

public Mono<Hotel> update(Hotel hotel) {
    return this.hotelRepository.findOne(hotel.getId())
            .flatMap(existingHotel ->
                    this.hotelByLetterRepository.delete(new HotelByLetter(existingHotel).getHotelByLetterKey())
                            .then(this.hotelByLetterRepository.save(new HotelByLetter(hotel)))
                            .then(this.hotelRepository.update(hotel))).next();
}

Web Layer

Now to the focus of the article: support for annotation-based reactive programming model support in the web layer!

The @Controller and @RestController annotations have been the workhorses of the Spring MVC's REST endpoint support for years now. Traditionally, they have enabled taking in and returning Java POJOs. These controllers in the reactive model have now been tweaked to take in and return the Reactive types — Mono and Flux in my examples — but additionally the Rx-Java 1/2 and Reactive Streams types.

Given this, my controller, in almost its entirety, looks like this:

@RestController
@RequestMapping("/hotels")
public class HotelController {

    ....

    @GetMapping(path = "/{id}")
    public Mono<Hotel> get(@PathVariable("id") UUID uuid) {
        return this.hotelService.findOne(uuid);
    }

    @PostMapping
    public Mono<ResponseEntity<Hotel>> save(@RequestBody Hotel hotel) {
        return this.hotelService.save(hotel)
                .map(savedHotel -> new ResponseEntity<>(savedHotel, HttpStatus.CREATED));
    }

    @PutMapping
    public Mono<ResponseEntity<Hotel>> update(@RequestBody Hotel hotel) {
        return this.hotelService.update(hotel)
                .map(savedHotel -> new ResponseEntity<>(savedHotel, HttpStatus.CREATED))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @DeleteMapping(path = "/{id}")
    public Mono<ResponseEntity<String>> delete(
            @PathVariable("id") UUID uuid) {
        return this.hotelService.delete(uuid).map((Boolean status) ->
                new ResponseEntity<>("Deleted", HttpStatus.ACCEPTED));
    }

    @GetMapping(path = "/startingwith/{letter}")
    public Flux<HotelByLetter> findHotelsWithLetter(
            @PathVariable("letter") String letter) {
        return this.hotelService.findHotelsStartingWith(letter);
    }

    @GetMapping(path = "/fromstate/{state}")
    public Flux<Hotel> findHotelsInState(
            @PathVariable("state") String state) {
        return this.hotelService.findHotelsInState(state);
    }
}


The traditional @RequestMapping, @GetMapping, and @PostMapping is unchanged. What is different is the return types. For instance, where at most 1 result is expected, I am now returning a Mono type, and where a list would have been returned before, now a Flux type is returned.

With the use of the reactive support in Spring Data Cassandra, the entire web-to-services-and-back setup is reactive and, specifically for the focus of the article, eminently readable and intuitive.

It may be easier to simply try out the code behind this post, which I have available in my GitHub repo here.

Spring Framework

Published at DZone with permission of Biju Kunjummen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!