'What is the right way to consolidate Flux results from different micro-services?

I've got an edge service which consolidates results from 3 different micro-services.

  1. Returns a Flux of customers
  2. Returns Mono of profile for customer
  3. Returns a Flux of roles for customer

What is the correct way to build a Flux of CustomerProfile objects which will include information about customer, profile and roles?

@RequiredArgsConstructor
@RestController
class CrmRestController {
    private final CrmClient crmClient;

    @GetMapping("/customer-profiles")
    public Flux<CustomerProfile> getCustomerProfiles() {
        return crmClient.getCustomerProfiles();
    }
}

@RequiredArgsConstructor
@Component
class CrmClient {
    private final WebClient http;
    private final RSocketRequester rsocket;

    Flux<Customer> getCustomers() {
        return this.http.get().uri("http://localhost:8080/customers").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("profiles.{customerId}", customerId).retrieveMono(Profile.class);
    }

    Flux<CustomerProfile> getCustomerProfiles() {
        //TODO: What is the right way to create CustomerProfile objects and fill in values?
        //my best guess does not compile
        return getCustomers()
                .flatMap(customer -> getProfileFor(customer.getId())
                        .map(profile -> getRolesFor(customer.getId())
                                .collectList().map(roles -> new CustomerProfile(customer, profile, roles))));
    }
}

@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;
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source