¿Cuál es la forma correcta de consolidar los resultados de Flux de diferentes microservicios?
Tengo un servicio de frontera que consolida los resultados de 3 microservicios diferentes.
- Devuelve un Flux de clientes
- Devuelve un Mono de perfil para el cliente
- Devuelve un Flux de roles para el cliente
¿Cuál es la forma correcta de construir un Flux de objetos CustomerProfile que incluirá información sobre el cliente, el perfil y los roles?
“`java
@RequiredArgsConstructor
@RestController
class CrmRestController {
private final CrmClient crmClient;
<pre><code>@GetMapping("/perfiles-cliente")
public Flux<CustomerProfile> getCustomerProfiles() {
return crmClient.getCustomerProfiles();
}
</code></pre>
}
@RequiredArgsConstructor
@Component
class CrmClient {
private final WebClient http;
private final RSocketRequester rsocket;
<pre><code>Flux<Customer> getCustomers() {
return this.http.get().uri("http://localhost:8080/clientes").retrieve().bodyToFlux(Customer.class);
}
Flux<Role> getRolesFor(Integer customerId) {
return this.http.get().uri("http://localhost:8183/roles").retrieve().bodyToFlux(Role.class);
}
Mono<Profile> getProfileFor(Integer customerId) {
return this.rsocket.route("perfiles.{customerId}", customerId).retrieveMono(Profile.class);
}
Flux<CustomerProfile> getCustomerProfiles() {
//TODO: ¿Cuál es la forma correcta de crear los objetos CustomerProfile y completar los valores?
//mi mejor suposición no se compila
return getCustomers()
.flatMap(customer -> getProfileFor(customer.getId())
.map(profile -> getRolesFor(customer.getId())
.collectList().map(roles -> new CustomerProfile(customer, profile, roles))));
}
</code></pre>
}
@Data
@AllArgsConstructor
class Customer {
private Integer id;
private String name;
}
@Data
@AllArgsConstructor
class Profile {
Integer id;
Date registered;
}
@Data
@AllArgsConstructor
class Role {
private Integer id;
private String title;
}
@Data
@AllArgsConstructor
class CustomerProfile {
private Customer customer;
private Profile profile;
private List<Role> roles;
}
“`
davy.ai
La forma correcta de construir un Flux de objetos CustomerProfile que incluirá información sobre el cliente, el perfil y los roles es utilizando algunos operadores reactivos, principalmente
flatMap
,zip
ycollectList
:En este código, usamos
flatMap
para extraer cada ID de cliente y luego llamar agetProfileFor
ygetRolesFor
para ese ID, produciendo unMono
y unFlux
respectivamente. UsamosMono.zip
para combinar elMono
y elFlux
en un soloMono<><profile,></profile,><role>>>
, donde elTuple2
contiene el perfil y una lista de roles. Finalmente, usamosmap
para combinar elCustomer
,Profile
yList<role>
en un objetoCustomerProfile
.