Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Handling Empty Mono Values and Conditional Logic in Project Reactor

Tech 1

Imperative baseline

public void imperativeCheck(Token token) {
  if (token == null) {
    // business logic for missing token
    return;
  }
  if (token.isExpired()) {
    // business logic for expired token
    return;
  }
  // business logic for valid token
}

A naive reactive rewrite that fails

public Mono<Void> naiveReactiveCheck(Mono<Token> token$) {
  return token$
      .flatMap(t -> {
        if (t == null) {
          // Unreachable: flatMap is not invoked when the source is empty
          // business logic for missing token
          return Mono.empty();
        }
        if (t.isExpired()) {
          // business logic for expired token
          return Mono.empty();
        }
        // business logic for valid token
        return Mono.empty();
      });
}

flatMap (and most operators) act only on onNext signals. If the upstrema Mono compeltes with out emitting, the flatMap lambda is never called. As a result, t is never null inside the lambda; it either exists or the lambda is skipped entirely.

Propagating emptiness with Opitonal

Transform the stream to carry an Optional<Token>, provide a default when the upstream is empty, and then handle all branches in one place.

public Mono<Void> robustReactiveCheck(Mono<Token> token$) {
  return token$
      // Wrap value-bearing monos as Optional.of(value)
      .map(Optional::of)
      // If upstream is empty, substitute Optional.empty()
      .defaultIfEmpty(Optional.empty())
      // Now this stage always runs exactly once
      .flatMap(opt -> {
        if (opt.isEmpty()) {
          // business logic for missing token
          return Mono.empty();
        }
        Token t = opt.get();
        if (t.isExpired()) {
          // business logic for expired token
          return Mono.empty();
        }
        // business logic for valid token
        return Mono.empty();
      });
}

Alternatives to empty Mono handling

  • Using switchIfEmpty to branch when the source is empty:
public Mono<Void> checkWithSwitch(Mono<Token> token$) {
  return token$
      .flatMap(t -> {
        if (t.isExpired()) {
          // business logic for expired token
          return Mono.empty();
        }
        // business logic for valid token
        return Mono.empty();
      })
      .switchIfEmpty(Mono.defer(() -> {
        // business logic for missing token
        return Mono.empty();
      }));
}
  • Using defaultIfEmpty with a sentinel and a discriminator:
public Mono<Void> checkWithSentinel(Mono<Token> token$) {
  Token SENTINEL = new Token(/* mark as special */);

  return token$
      .defaultIfEmpty(SENTINEL)
      .flatMap(t -> {
        if (t == SENTINEL) {
          // business logic for missing token
          return Mono.empty();
        }
        if (t.isExpired()) {
          // business logic for expired token
          return Mono.empty();
        }
        // business logic for valid token
        return Mono.empty();
      });
}
  • Repeating until a value appears (Flux or Mono with repeatWhenEmpty):
public Mono<Token> fetchWithRetries(Mono<Token> source) {
  return source
      .repeatWhenEmpty(repeat -> repeat
          .take(3) // retry up to 3 times when empty
      );
}

Reactor provides defaultIfEmpty, switchIfEmpty, and repeatWhenEmpty to model empty-source behavior without relying on null checks inside flatMap.

Tags: reactor

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.