Search code examples
spring-bootspring-webfluxspring-data-r2dbc

Record not persisted into R2DB using Spring boot webflux reactive


I am trying to build an application using reactive. Initially i used to get proper response but after modifying the code, the record is not persisted into Database, but when I changed the logic to modify the response body, I see a success response but no record was found in DB nor I can see an error in logs.

Code before Modifying:

public Mono<ServerResponse> createCustomer(ServerRequest serverRequest) {
        return serverRequest.bodyToMono(Customer.class).flatMap(customer -> {
            ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(customerRepository.save(customer), Customer.class);

        });
    }

But I want to return a generic API Response for all API calls and modified the code as below:

public Mono<ServerResponse> createCustomer(ServerRequest serverRequest) {
        Response response = new Response();
        return serverRequest.bodyToMono(Customer.class).flatMap(customer -> {
            saveCustomer(customer,apiResponse);
            return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(Mono.just(apiResponse), Response.class);

        }).doOnError(err -> {
                    log.error("Exception while creating customr record", err);
        }).onErrorResume(err ->  {
            apiResponse.setError(new Error(err.getMessage(),err.getCause()));
            return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(Mono.just(apiResponse), ApiResponse.class);
        });
    }

    public Response saveCustomer(Customer customer,Response apiResponse){
        customerRepository.save(customer);
        apiResponse.setCode("0");
        apiResponse.setMessage("Successfully Created customer");
        return apiResponse;
    }

Any thoughts are appreciated please.


Solution

  • I doubt this code - customerRepository.save(customer);

    If you are using R2DBC, the save method does not save directly. It will return a publisher type. It has to be subscribed to make it work. Otherwise it will not insert records.

    You need to do this!

    customerRepository.save(customer).subscribe();

    However this is NOT a good practice to directly subscribe like this. Instead you should do something like this.

    public Mono<Response> saveCustomer(Customer customer,Response apiResponse){
        return customerRepository.save(customer)
                 .map(c -> {
                      apiResponse.setCode("0");
                      apiResponse.setMessage("Successfully Created customer");
                      return apiResponse;
                  });
    }
    

    then modify your

    return serverRequest.bodyToMono(Customer.class).flatMap(customer -> {.....

    code to something like this.

    return serverRequest.bodyToMono(Customer.class)
                         .flatMap(customer -> saveCustomer(customer, response))
                         .flatMap(r -> ServerResponse.ok()
                                     .contentType(MediaType.APPLICATION_JSON)
                                     .body(Mono.just(r), Response.class))