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);
}
CodePudding user response:
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: