I try to make sequential API calls and merge the result in a mono . The first API contains a List of Id for the second API.
@Service
@AllArgsConstructor
public class AggregateService {
private OperationClient operationClient;
private OuvrageClient ouvrageClient;
public Mono<OperationDetailDto> getDetails(String operationId){
final Mono<OperationFullDto> operationMono = operationClient.getOperation(operationId);
return operationMono
.flatMap(operation -> {
final OperationDetailDto detail = new OperationDetailDto();
final Mono<List<OuvrageDto>> ouvrageMono = ouvrageClient.getOuvrages(operation.getOuvrageIds());
Mono<Tuple2<OperationFullDto, List<OuvrageDto>>> tuple2 = Mono.zip(operationMono,ouvrageMono);
tuple2.map(result ->{
detail.setId(ServiceUtils.formatUuid(operationId));
detail.setTitre(result.getT1().getTitre());
detail.setOuvrages(result.getT2());
return detail;
});
return Mono.just(detail);
}
);
}
}
My functional WebClient
@Service
public class OperationClient {
private final WebClient webClient;
public OperationClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("lb://operation-microservice/operation/").build();
}
public Mono<OperationFullDto> getOperation(String operationId){
return webClient
.get()
.uri("{id}" , operationId)
.retrieve()
.bodyToMono(OperationFullDto.class)
.subscribeOn(Schedulers.parallel())
.log()
.onErrorResume(ex->Mono.empty());
}
}
The ouvrageClient was invoked but I don't see log
public class OuvrageClient {
private final WebClient webClient;
public OuvrageClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("lb://ouvrage-microservice/ouvrage/").build();
}
public Mono<List<OuvrageDto>> getOuvrages(List<Long> ids){
System.out.println("the void getOuvrages was invoked " ids );
return webClient
.get()
.uri("multi/{ids}",ids)
.retrieve()
.bodyToFlux(OuvrageDto.class)
.subscribeOn(Schedulers.parallel())
.collectList()
.onErrorReturn(Collections.emptyList())
.log();
}
}
Log
2022-06-21 10:54:37.872 INFO 252 --- [ctor-http-nio-3] reactor.Mono.SubscribeOn.1 : onSubscribe(MonoSubscribeOn.SubscribeOnSubscriber)
2022-06-21 10:54:37.875 INFO 252 --- [ctor-http-nio-3] reactor.Mono.SubscribeOn.1 : request(unbounded)
2022-06-21 10:54:38.724 INFO 252 --- [ctor-http-nio-1] reactor.Mono.SubscribeOn.1 : onNext(OperationFullDto(id=c4f62ea6-0387-4021-b5de-d056105612ce, titre=test3, ouvrageIds=[2]))
the void getOuvrages was invoked [2]
2022-06-21 10:54:38.796 INFO 252 --- [ctor-http-nio-1] reactor.Mono.SubscribeOn.1 : onComplete()
The ouvrageClient was invoked but I don't see log for the ouvrageClient .... and the global result of my AggregateService is empty
{"id": null,"titre": null,"ouvrages": null}
Thanks
Thanks for the answer ! what do you think of this piece of code?
public Mono<OperationDetailDto> getDetails(String operationId){
final Mono<OperationFullDto> operationMono = operationClient.getOperation(operationId);
return operationMono.zipWhen( operation -> ouvrageClient.getOuvrages(operation.getOuvrageIds()) )
.map( tuple2 -> {
OperationDetailDto detail = new OperationDetailDto();
detail.setId(ServiceUtils.formatUuid(operationId));
detail.setTitre(tuple2.getT1().getTitre());
detail.setOuvrages(tuple2.getT2());
return detail;
});
}
CodePudding user response:
You could return the tuple2.map
to the flatMap
operation directly, but make sure you create and return the OperationDetailDto
inside the map
's lambda.
.flatMap(operation -> {
final Mono<List<OuvrageDto>> ouvrageMono =
ouvrageClient.getOuvrages(operation.getOuvrageIds());
Mono<Tuple2<OperationFullDto, List<OuvrageDto>>> tuple2 =
Mono.zip(operationMono, ouvrageMono);
return tuple2.map(result -> {
final OperationDetailDto detail = new OperationDetailDto();
detail.setId(ServiceUtils.formatUuid(operationId));
detail.setTitre(result.getT1().getTitre());
detail.setOuvrages(result.getT2());
return detail;
});
})