Issue
I have an Spring Boot rest API that have an LoginController for doing simple authentication processes. This is the token validation action.
@PostMapping("validatetoken")
public ResponseEntity<ValidateTokenResponse> validateToken(
@RequestBody ValidateTokenRequest validateTokenRequest, HttpServletRequest request) throws Exception {
if (StringUtils.isEmpty(validateTokenRequest.getToken())) throw new AuthenticationFailedException("token parameter cannot be null or empty");
Boolean isValid = authenticationService.validateToken(request, validateTokenRequest.getToken());
ValidateTokenResponse response = new ValidateTokenResponse();
response.setIsValid(isValid);
response.setToken(validateTokenRequest.getToken());
return new ResponseEntity<>(response, isValid? HttpStatus.OK : HttpStatus.UNAUTHORIZED);
}
And in my api I'm catching all errors in a ResponseEntityExceptionHandler
and converting a custom object this way.
@ExceptionHandler(AuthenticationFailedException.class)
@ResponseBody
protected ResponseEntity<Object> handleAuthenticationFailed(AuthenticationFailedException ex) {
LogManager.error(ex);
ApiError apiError = new ApiError(HttpStatus.UNAUTHORIZED);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
But when I want to call this api using RestTemplate
like below I'm getting and exception like java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode.
ResponseEntity<String> responseEntity =
restTemplate.exchange(
this.validateTokenUrl,
HttpMethod.POST,
requestHttpEntity,
String.class);
But if I change HttpStatus
from ExceptionHandler
to except HttpStatus.UNAUTHORIZED
I can get true ApiError
object from the client. What can cause this problem and how can I resolve it?
EDIT: Created a github repo that mimics my problemic parts of my project.
Solution
To make it clear, I suggest to autowire resttemplate in separate config file with below detail
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new ErrorHandler());
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setOutputStreaming(false);
restTemplate.setRequestFactory(requestFactory);
return restTemplate;
}
Answered By - Cuong