I have a spring-boot project called carrental-crud with an h2 memory database, and I want to access one of the endpoints from another project called carrental-api.
I use webClientBuilder for this on my other endpoints, but it is throwing status 500 with bad request when I try using it in postman.
I use JPArepository to access the h2 db with a query, this is how my orderRepository looks :
@Transactional @Query(nativeQuery = true,value = "select count(*) from TBL_ORDER WHERE CUSTOMER_ID=?1") public int getTotalOrders(long customerId);
Then in my adminCustomerService class, I use it like this :
public int getTotalOrders(long customerId) { loggerService.writeLoggerMsg("LISTED TOTAL ORDERS FOR A CUSTOMER"); return orderRepository.getTotalOrders(customerId); }
And then in my adminCustomerController :
@GetMapping(path = "/totalorders") public int getTotalOrders(@RequestBody Customer customer) { return adminCustomerService.getTotalOrders(customer.getCustomerId()); }
and in my postman request body, I write :
{ "customerId": 2 }
This works in my carrental-crud, but how can I recreate this in my carrental-api?
And using the same request body in postman, but I keep getting the error status 500 with bad request
EDIT : I managed to get this to work by using parameters instead of a request body.
This is how my adminCustomerService looks :
public int getTotalOrders(long customerId) { int orders = webClientBuilder.build() .get() .uri("http://localhost:8081/crud/v1/totalorders/" + customerId) .retrieve() .bodyToMono(new ParameterizedTypeReference<Integer>() {}) .log() .block(); return orders; }
And my adminCustomerController :
@GetMapping(path = "/totalorders/{customerId}") public int getTotalOrders(@PathVariable long customerId) { return adminCustomerService.getTotalOrders(customerId); }
Advertisement
Answer
The issue is that you are simply sending customerId
as a Long
in your programmatic call when you should be sending something like the JSON that you showed. The simplest way to solve this is by creating a class that matches such JSON structure:
public class CustomerRequest { private long customerId; public CustomerRequest(long customerId) { this.customerId = customerId; } public long getCustomerId() { return customerId; } }
And then you need to create an instance of such class when calling the API as follows:
public Flux<Integer> getTotalOrders(long customerId) { loggerService.writeLoggerMsg("LISTED TOTAL ORDERS FOR A CUSTOMER"); return ((RequestBodySpec) webClientBuilder .build() .get() .uri("localhost:8081/crud/v1/totalorders")) .body(Flux.just(new CustomerRequest(customerId)), CustomerRequest.class) .retrieve() .bodyToFlux(Integer.class); }
Still, I would suggest you having a more RESTful approach in your endpoint and use path parameter instead of a request body in a GET request. Something along the following lines:
@GetMapping(path = "/customers/{customerId}/total-orders") public int getTotalOrders(@PathVariable long customerId) { return adminCustomerService.getTotalOrders(customerId); }
Then you would make a request to this endpoint as follows:
public Flux<Integer> getTotalOrders(long customerId) { loggerService.writeLoggerMsg("LISTED TOTAL ORDERS FOR A CUSTOMER"); return webClientBuilder .build() .get() .uri("localhost:8081/crud/v1/customers/{customerId}/total-orders", customerId)) .retrieve() .bodyToFlux(Integer.class); }
I would suggest you read the following online resources: