Seeker
Seeker

Reputation: 2483

RestTemplate throwing generic 400 Bad Request, but custom server sent message is not is lost

We have a rest controller API with POST mapping which takes an object as request param and creates the same on DB. We have got few validations on the input object, and if there is any error, then we are throwing exception with a custom message.

If we invoke this API from post man, we see the appropriate error.

Whereas when we invoke this in the caller method of other application with Spring's RestTemplate, all we see is a 400 Bad request with empty body. No error message is seen.

What could be the issue here. How can we get the custom message thrown from the API.

Here is how we are calling the API with rest template.

    String url = "https://localhost:8895/servuceUrl";
    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    HttpEntity<AddRequest> entity = new HttpEntity<AddRequest>(obj, headers);
    ResponseEntity<String> data = null;
    adddata = restTemplate.exchange(syncurl, HttpMethod.POST, entity, String.class);

And one server side we have an exception written as

@ResponseStatus(value=HttpStatus.BAD_REQUEST)
public class InvalidDataException extends Exception {


    public InvalidDataException(String msg) {
        super(msg);
    }
}

The controller looks like

@PostMapping(RestUriMappings.POST_MAPPING)
public ResponseDto add(@Valid @RequestBody AddRequest data) throws InvalidDataException 
{

    logger.debug("Incoming data for add: {}", data.toString());

    // validate the payload
    if(data.getName()==null)
       throw new InvalidDataException("Name shouldnt be null");
}

Upvotes: 0

Views: 10044

Answers (3)

Nuwan Sameera
Nuwan Sameera

Reputation: 819

Following Mukul Bansal's answer I did following modification.

public class MyErrorHandler extends DefaultResponseErrorHandler {

    @Override
    protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode) throws IOException {

    }

} 

Override handleError method without any content.

Then set error handler to RestTemplate.

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyErrorHandler());

Then it return ResponseEntity with actual status code.

Anyway I cannot understand reason for default Spring's implementation.

Upvotes: 0

Francesc Recio
Francesc Recio

Reputation: 2235

You are missing:

headers.setContentType(MediaType.APPLICATION_JSON);

Upvotes: 0

Mukul Bansal
Mukul Bansal

Reputation: 926

Spring's RestTemplate implementation has kind of a weird functionality. Whenever, the response is a 4XX, it throws a HttpClientErrorException instead of returning the response. Similarly, when the response is a 5XX response, it throws a HttpServerErrorException.

When you go inside the library, you will come across the piece of code which is responsible for such functionality inside DefaultResponseErrorHandler.java#handleError(ClientHttpResponse response).

So, if you want to fetch the original 4XX or 5XX response, you would have to write a wrapper over the RestTemplate.java#exchange() method. Something like this-

private ResponseEntity<String> exchange(String url, HttpMethod method, HttpEntity<?> httpEntity,
                                           Class<?> class1, Map<String, String> paramMap) {
        ResponseEntity<String> responseEntity = null;
        try {
            responseEntity = restTemplate.exchange(url, method, httpEntity, String.class, paramMap);
        }catch(HttpClientErrorException e) {
            responseEntity = new ResponseEntity<>(e.getResponseBodyAsString(), HttpStatus.BAD_REQUEST);
        }catch(HttpServerErrorException e) {
            responseEntity = new ResponseEntity<>(e.getResponseBodyAsString(), HttpStatus.INTERNAL_SERVER_ERROR);
            throw e;
        }catch(Exception e) {
            responseEntity = new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
            throw e;
        }
        return responseEntity;
    }

Upvotes: 7

Related Questions