I have a Spring Webflux reactive service which receives a DTO and inserts it into multiple table. Sometimes we may need to skip inserting into some tables based on the incoming DTO.
These are the requirements:
- Create a new Client
- Create a new Client referral if the client referral is present in the DTO.
- Create a client Secondary contact if present in the DTO
- Create client phones if present in the DTO
Questions:-
- Not sure how to apply the if condition in the reactive flow.
- Is there any better way of doing this?
- Here, except the first one all other operation can run in parallel.
public Mono<ServerResponse> createClientProfile(ServerRequest request) {
return secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
return toNewClient(client, usr).flatMap(clientRepository::save).flatMap(clientRes -> {
return toNewClientReferral(clientRes.getClientId(), client.getDiscount(), usr)
.flatMap(clientReferralRepository::save).flatMap(clientReferralRes -> {
return toNewClientSyContact(clientRes.getClientId(), client.getSecondary(), usr)
.flatMap(clientSyContactRepository::save).flatMap(clientSyContactRes -> {
return clientPhoneRepository
.saveAll(toNewClientPhone(clientRes.getClientId(), client.getPhones(), usr))
.collectList().flatMap(phoneRes -> {
return ServerResponse
.created(URI.create(String.format(CLIENT_URI_FORMAT,
clientRes.getClientId())))
.contentType(APPLICATION_JSON).build();
});
});
});
});
});
});
}
private Mono<Referral> toNewClientReferral(final long clientId, final Discount dto) {
Referral referral = Referral.of(clientId,
dto.getName(), dto.getType(), dto.getAmount(), dto.getStatus());
return Mono.just(referral);
}
client.getDiscount() can be null,
client.getSecondary() can be null, client.getPhones() can be empty.
I separated the flow with 3 different methods.
public void createSyContact(ServerRequest request, long clientId) {
secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
if (client.getSecondary() != null) {
return toNewClientSyContact(clientId, client.getSecondary(), usr)
.flatMap(clientSyContactRepository::save).flatMap(clientRes -> {
return Mono.just(clientRes.getClientId());
});
} else {
return Mono.empty();
}
});
});
}
public void createReferral(ServerRequest request, long clientId) {
secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
if (client.getDiscount() != null) {
return toNewClientReferral(clientId, client.getDiscount(), usr)
.flatMap(clientReferralRepository::save).flatMap(clientRes -> {
return Mono.just(clientRes.getClientId());
});
} else {
return Mono.empty();
}
});
});
}
public Mono<Long> createClientWithPhones(ServerRequest request) {
return secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
return toNewClient(client, usr).flatMap(clientRepository::save).flatMap(clientRes -> {
return clientPhoneRepository
.saveAll(toNewClientPhone(clientRes.getClientId(), client.getPhones(), usr)).collectList()
.flatMap(phoneRes -> {
return Mono.just(clientRes.getClientId());
});
});
});
});
}
Here, createClientWithPhones is mandatory, so no if check there. But the other 2 methods createReferral & createSyContact have if checks. Need to execute createClientWithPhones first and it will return clientId. This clientId should be used in createReferral & createSyContact.
public Mono<ServerResponse> createClientProfile(ServerRequest request) {
final List<Long> clinetIdList = new ArrayList<>();
createClientWithPhones(request).subscribe(result -> {
clinetIdList.add(result.longValue());
createSyContact(request, result.longValue());
createReferral(request, result.longValue());
});
return ServerResponse
.created(URI.create(String.format(CLIENT_URI_FORMAT,
clinetIdList.get(0))))
.contentType(APPLICATION_JSON).build();
}
Is this the way to handle this?