Logging a Reactive Sequence

1. Overview

With the introduction of Spring WebFlux, we got another powerful tool to write reactive, non-blocking applications. While using this technology is now way easier than before, debugging reactive sequences in Spring WebFlux can be quite cumbersome.

In this quick tutorial, we’ll see how to easily log events in asynchronous sequences and how to avoid some simple mistakes.

2. Maven Dependency

Let’s add the Spring WebFlux dependency to our project so we can create reactive streams:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

We can get the latest spring-boot-starter-webflux dependency from Maven Central.

3. Creating a Reactive Stream

To begin let’s create a reactive stream using Flux and use the log() method to enable logging:

Flux<Integer> reactiveStream = Flux.range(1, 5).log();

Next, we will subscribe to it to consume generated values:

reactiveStream.subscribe();

4. Logging Reactive Stream

After running the above application we see our logger in action:

2018-11-11 22:37:04 INFO | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription)
2018-11-11 22:37:04 INFO | request(unbounded)
2018-11-11 22:37:04 INFO | onNext(1)
2018-11-11 22:37:04 INFO | onNext(2)
2018-11-11 22:37:04 INFO | onNext(3)
2018-11-11 22:37:04 INFO | onNext(4)
2018-11-11 22:37:04 INFO | onNext(5)
2018-11-11 22:37:04 INFO | onComplete()

We see every event that occurred on our stream. Five values were emitted and then stream closed with an onComplete() event.

5. Advanced Logging Scenario

We can modify our application to see a more interesting scenario. Let’s add take() to Flux which will instruct the stream to provide only a specific number of events:

Flux<Integer> reactiveStream = Flux.range(1, 5).log().take(3);

After executing the code, we’ll see the following output:

2018-11-11 22:45:35 INFO | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription)
2018-11-11 22:45:35 INFO | request(unbounded)
2018-11-11 22:45:35 INFO | onNext(1)
2018-11-11 22:45:35 INFO | onNext(2)
2018-11-11 22:45:35 INFO | onNext(3)
2018-11-11 22:45:35 INFO | cancel()

As we can see, take() caused the stream to cancel after emitting three events.

The placement of log() in your stream is crucial. Let’s see how placing log() after take() will produce different output:

Flux<Integer> reactiveStream = Flux.range(1, 5).take(3).log();

And the output:

2018-11-11 22:49:23 INFO | onSubscribe([Fuseable] FluxTake.TakeFuseableSubscriber)
2018-11-11 22:49:23 INFO | request(unbounded)
2018-11-11 22:49:23 INFO | onNext(1)
2018-11-11 22:49:23 INFO | onNext(2)
2018-11-11 22:49:23 INFO | onNext(3)
2018-11-11 22:49:23 INFO | onComplete()

As we can see changing the point of observation changed the output. Now the stream produced three events, but instead of cancel(), we see onComplete()This is because we observe the output of using take() instead of what was requested by this method.

6. Conclusion

In this quick article, we saw how to log reactive streams using built-in log() method.

And as always, the source code for the above example can be found over on GitHub.

Related posts:

Introduction to Spring Data JDBC
Introduction to the Java NIO Selector
Java Program to Implement Range Tree
Java Program to Find Minimum Number of Edges to Cut to make the Graph Disconnected
Guava CharMatcher
Java Program to Encode a Message Using Playfair Cipher
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
Java Program to Implement Graph Coloring Algorithm
Spring REST API with Protocol Buffers
Spring Boot - Exception Handling
Spring 5 Functional Bean Registration
Một số tính năng mới về xử lý ngoại lệ trong Java 7
Using a Mutex Object in Java
Java Program to Check Cycle in a Graph using Graph traversal
Java Program to Implement Fisher-Yates Algorithm for Array Shuffling
Java Program to Find All Pairs Shortest Path
Java Program to Implement Fermat Primality Test Algorithm
Java Program to Optimize Wire Length in Electrical Circuit
The “final” Keyword in Java
CharSequence vs. String in Java
Spring @RequestParam Annotation
Spring Security Login Page with React
Java Program to Implement Sorted Circular Doubly Linked List
Java Program to Construct K-D Tree for 2 Dimensional Data
Java Program to Perform the Sorting Using Counting Sort
Java Program to Implement Queue using Two Stacks
OAuth2 for a Spring REST API – Handle the Refresh Token in AngularJS
Java Program to Find Location of a Point Placed in Three Dimensions Using K-D Trees
Lớp TreeMap trong Java
Spring Boot - Tracing Micro Service Logs
Java Program to Implement the String Search Algorithm for Short Text Sizes
Giới thiệu về Stream API trong Java 8