voychris
voychris

Reputation: 141

How to pass data down the reactive chain

Whenever I need to pass data down the reactive chain I end up doing something like this:

public Mono<String> doFooAndPassDtoAsMono(Dto dto) {
    return Mono.just(dto)
        .flatMap(dtoMono -> {
            Mono<String> result = // remote call returning a Mono
            return Mono.zip(Mono.just(dtoMono), result);
        })
        .flatMap(tup2 -> {
            return doSomething(tup2.getT1().getFoo(), tup2.getT2()); // do something that requires foo and result and returns a Mono
        });
}

Given the below sample Dto class:

class Dto {
    private String foo;

    public String getFoo() {
        return this.foo;
    }
}

Because it often gets tedious to zip the data all the time to pass it down the chain (especially a few levels down) I was wondering if it's ok to simply reference the dto directly like so:

public Mono<String> doFooAndReferenceParam(Dto dto) {
       Mono<String> result = // remote call returning a Mono
        return result.flatMap(result -> {
            return doSomething(dto.getFoo(), result); // do something that requires foo and result and returns a Mono
        });
}

My concern about the second approach is that assuming a subscriber subscribes to this Mono on a thread pool would I need to guarantee that Dto is thread safe (the above example is simple because it just carries a String but what if it's not)?

Also, which one is considered "best practice"?

Upvotes: 7

Views: 2378

Answers (3)

Archmede
Archmede

Reputation: 1856

This is unintuitive to "clean" code programmers but just keep building nested classes when necessary.

Mono.just(child)
.map(child -> new Parent(child))
.map(parent -> new GrantParent(parent))
.map(grandparent -> {
    // access parent and child here
    Parent parent = grandParent.getParent();
    // get child object and perform operations
    Child child = parent.getChild();
    
    return child.getName();
});

Upvotes: 0

oberlies
oberlies

Reputation: 11723

The case is simple if

  • The reference data is available from the beginning (i.e. before the creation of the chain), and
  • The chain is created for processing at most one event (i.e. starts with a Mono), and
  • The reference data is immutable.

Then you can simple refer to the reference data in a parameter or local variable – just like in your second solution. This is completely okay, and there are no concurrency issues.


Using mutable data in reactive flows is strongly discouraged. If you had a mutable Dto class, you might still be able to use it (assuming proper synchronization) – but this will be very surprising to readers of your code.

Upvotes: 0

Vikram Rawat
Vikram Rawat

Reputation: 1662

Based on what you have shared, you can simply do following:

public Mono<String> doFooAndPassDtoAsMono(Dto dto) {
    return Mono.just(dto.getFoo());
}

The way you are using zip in the first option doesn't solve any purpose. Similarly, the 2nd option will not work either as once the mono is empty then the next flat map will not be triggered.

Upvotes: 0

Related Questions