Avik Kesari
Avik Kesari

Reputation: 289

How to do enrichment of an object in reactor webflux?

I have an interface

    public interface Enricher {
       Mono<MyObject> enrich(MyObject obj);
    }

I have implementations of this interface which returns the updated MyObject.

I have another implementation called CompositeEnricher which takes in List of Enricher in constructor and performs enrichment.

In non-reactive world, I will write something like this

/*
  Please note that following code is applicable only if Enricher interface returns MyObject instead of Mono<MyObject>
*/

public class CompositeEnricher implements Enricher {

  private final List<Enricher> enrichers;

  public CompositeEnricher(List<Enricher> enrichers) {
    this.enrichers = enrichers;
  }

  @Override
  public MyObject enrich(MyObject myObject) {
    MyObject updated = myObject;
    for(Enricher enricher : enrichers) {
      updated = enricher.enrich(updated);
    }
    return updated;
  }
}

How do I change it to reactive so that each of the implementations of Enricher return Mono including CompositeEnricher which implements Enricher interface?

Upvotes: 1

Views: 981

Answers (2)

Avik Kesari
Avik Kesari

Reputation: 289

I figured out the problem using Mono.expand method. But I had to use enrichers.iterator(). Wondering if I can somehow put enrichers also in reactive chain instead of using iterator.

@Override
    public Mono<User> enrich(User user) {
        Iterator<Enricher> iterator = enrichers.iterator();
        Function<User, Publisher<User>> enrichmentFunction = u -> iterator.hasNext() ? iterator.next().enrich(u) : Mono.empty();
        return Mono.just(user)
                .expand(enrichmentFunction)
                .last();
    }

Upvotes: 1

Michael Berry
Michael Berry

Reputation: 72379

There's actually no need for a separate CompositeEnricher class here at all - given a List<Enricher> enrichers, you can simply reduce your enrichers using standard Java streams:

Enricher composite = enrichers.stream()
        .reduce((e1, e2) -> myObj -> e1.enrich(myObj).flatMap(myObj2 -> e2.enrich(myObj2)))
        .get();

You can flesh this out into a class if you need to of course, but you could equally just leave this implemented as a helper method somewhere.

Upvotes: 1

Related Questions