Reputation: 289
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
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
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