Here is the following flow in my code: User calls create agency endpoint, containing the agency name and a boolean field ->
Router functions receives call, passes to handler ->
Handler converts request body to Mono, passes that mono so a service ->
Service saves agency to DB, generating an ID in the process, then creates a Response object containing the ID wrapped in a Mono, returns Response back to the Handler.
This is the part where I am stuck. Maintaining a reactive approach, I must save the Agency to Db and create the ID within a "doOnNext() part of the Mono. However, I can't return the ID that I get from the DB in order to create the response object.
What is the reactive way to accomplish this? Thanks in advance!
public RouterFunction<ServerResponse> createAgency() {
return RouterFunctions
.route(POST("/agency").and(accept(MediaType.APPLICATION_JSON)), handler::createAgency);
}
@Component
@AllArgsConstructor
public class AgencyHandler {
private final AgencyServiceImpl service;
@NonNull
public Mono<ServerResponse> createAgency(ServerRequest request){
Mono<CreateAgencyRequest> agency = request.bodyToMono(CreateAgencyRequest.class);
Mono<CreateAgencyResponse> response = service.createAgency(agency);
return ServerResponse.created(URI.create("/agency"))
.contentType(MediaType.APPLICATION_JSON)
.body(response, CreateAgencyResponse.class);
}
}
@Service
@AllArgsConstructor
public class AgencyServiceImpl implements AgencyService {
private final AgencyRepository agencyRepository;
private final UuidGenerator uuidGenerator;
public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
UUID id;
request.doOnNext(agency -> {
UUID agencyId = uuidGenerator.getUUID();
Mono<Agency> newAgency = Mono.just(
new Agency(
agencyId,
agency.getFields().getName()
));
//repository.save(newAgency)
//return Mono.just(new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString())));
});
// return request
return Mono.just(new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString())));
}
}
Something like the following should do the trick:
@Service
@AllArgsConstructor
public class AgencyServiceImpl implements AgencyService {
private final AgencyRepository agencyRepository;
private final UuidGenerator uuidGenerator;
public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
UUID agencyId = uuidGenerator.getUUID();
return request.flatMap(createAgencyRequest -> {
Agency agency = new Agency(agencyId, agency.getFields().getName();
return repository.save(newAgency);
}).map(saved ->
new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString()));
)
}
}
You would create the Agency
in the flatMap
operation and store it in the database. I assume your repository
is also reactive so it should return Mono
as well, hence the flatMap
operation. Afterwards you just need to map whatever the repository
returned (you may want to have some logic here based on the successful operation on the database) to create the CreateAgencyResponse
.