Spring OAuth2 Rest exception swallows HttpResponse code - java

Restservice I am invoking using oauth2resttemplate returns a response with status code 403. I see that in my ClientHttpRequestInterceptor log lines injected to the resttemplate.
This is the interceptor to intercept request and response. traceResponse() logs response status code as 403 which I expected.
public class RequestInterceptor implements ClientHttpRequestInterceptor {
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
try
{
traceRequest(request, body);
} catch (Exception e)
{
ManagerLog.alertLog("Exception occurred", e);
}
ClientHttpResponse response = execution.execute(request, body);
traceResponse(response);
return response;
}
private void traceRequest(HttpRequest request, byte[] body) throws Exception {
ManagerLog.infoLog("===========================request begin================================================");
ManagerLog.infoLog("URI : "+request.getURI());
ManagerLog.infoLog("Method : "+request.getMethod());
ManagerLog.infoLog("Headers : "+request.getHeaders() );
ManagerLog.infoLog("Request body : "+new String(body, "UTF-8"));
ManagerLog.infoLog("==========================request end================================================");
}
private void traceResponse(ClientHttpResponse response) throws IOException {
ManagerLog.infoLog("============================response begin==========================================");
ManagerLog.infoLog("Response Status code : "+ response.getStatusCode());
ManagerLog.infoLog("Response Status text : "+ response.getStatusText());
ManagerLog.infoLog("Response Headers : "+ response.getHeaders());
// ManagerLog.infoLog("Response body : "+ StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
ManagerLog.infoLog("=======================response end=================================================");
}
}
But down here I see 400 instead of 403. But I see in the spring source code it is actually hardcoded to 400 in parent class(OAuth2Exception.java) of InvalidGrantException.
try{
objectResponseEntity = oauth2RestTemplate.exchange(url, httpMethod, httpEntity, pojo) -- throws an InvalidGrantException
} catch (HttpStatusCodeException e)
{
...
} catch(InvalidGrantException e)
{
errorCode = e.getHttpErrorCode(); -- was expecting 403 but returning 400
...
}
Any idea on how to get the actual http response code from the exception?

Related

See response in API call which returns an unsuitable response

I have this method:
public Response issueConfirmation(String issueUrl) {
try {
ParameterizedTypeReference<Response> tRef = new ParameterizedTypeReference<Response>() {
};
HttpHeaders headers = createHeaders();
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<Response> res = restTemplate.exchange(myUrl,
HttpMethod.GET, request, tRef);
if (res.getStatusCode().is2xxSuccessful()) {
LOG.debug("Request successful.");
return response.getBody();
} else {
return null; // tbc
}
} catch (RestClientException e) {
LOG.debug("RestClientException: {} {}", e.getMessage());
}
return null; // tbc
}
The format of myUrl is http://localhost:8081/issueConfirmation?customer=1234&order=5678&dob=01/01/1990.
If the URL contains an incorrect dob an unsuitable response message is returned and a RestClientException is thrown. This is the message in the exception:
Could not extract response: no suitable HttpMessageConverter found for response type [class com.avis.myapi.model.Response] and content type [text/html;charset=utf-8]
Part of the issue here seems to be that I'm expecting application/json but the response is text/html.
How can I see the response from my GET?

How do I get the response status code from this WebClient Call?

I am consuming an API and this one in particular response with nothing but status code 201 in postman. In my code, how do I extract the status code using WebClient?
public HttpStatus createUser(String uuid) throws Exception {
MultiValueMap<String, String> bodyValues = new LinkedMultiValueMap<>();
bodyValues.add("providerCallbackHost", "https://webhook.site/c6c0a388-2af5-41e1-8d6d-c280820affad");
try {
HttpStatus response = webClient.post()
.uri("https://sandbox.momodeveloper.mtn.com/v1_0/apiuser")
.header("X-Reference-Id", uuid)
.header("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY_SECONDARY)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(bodyValues))
.retrieve()
.bodyToMono(HttpStatus.class)
.block();
return response;
} catch (Exception exception) {
throw new Exception(exception.getMessage());
}
}

How to get json response in Java in case of 4XX and 5XX error

I was trying out RestTemplate and Retrofit2. Both the libraries throw exception in case api returns 4XX/5XX. The api when hit from postman gives a JSON response body, along with 4XX/5XX.
How can I retrieve this JSON response using RestTemplate or Retrofit2.
Thanks.
Use the HttpClientErrorException, HttpStatusCodeException after try block as below.
try{
restTemplate.exchange("url", HttpMethod.GET, null, String.class);
}
catch (HttpClientErrorException errorException){
logger.info("Status code :: {}, Exception message :: {} , response body ::{}" , e.getStatusCode()
e.getMessage(), e.getResponseBodyAsString());
}
catch (HttpStatusCodeException e){
logger.info("Status code :: {}, Exception message :: {} , response body ::{}" , e.getStatusCode()
e.getMessage(), e.getResponseBodyAsString());
}
For that you have to create RestTemplateError handler and register that class while creating bean for RestTemplate.
#Bean
public RestTemplate getBasicRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new RestTemplateResponseErrorHandler());
return restTemplate;
}
where your handler class has to implements ResponseErrorHandler. You can read the json response that is stored in the body.
#Component
public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateResponseErrorHandler.class);
#Override
public boolean hasError(ClientHttpResponse httpResponse) throws IOException {
return httpResponse.getStatusCode().series() == CLIENT_ERROR
|| httpResponse.getStatusCode().series() == SERVER_ERROR;
}
#Override
public void handleError(ClientHttpResponse httpResponse) throws IOException {
if (httpResponse.getStatusCode().series() == SERVER_ERROR) {
LOGGER.error("Handling server error response statusCode:{} ", httpResponse.getStatusCode());
} else if (httpResponse.getStatusCode().series() == CLIENT_ERROR) {
LOGGER.error("Handling Client error response statusCode:{} ", httpResponse.getStatusCode());
String body;
InputStreamReader inputStreamReader = new InputStreamReader(httpResponse.getBody(),
StandardCharsets.UTF_8);
body = new BufferedReader(inputStreamReader).lines().collect(Collectors.joining("\n"));
throw new CustomException(httpResponse.getStatusCode().toString(), httpResponse, body);
}
}
}

Suppress all null values into java API request

I use Java 8 application based on springboot and gradle and i try to suppress all null values into my JSON request body :
{"typePersonne":"Adherent","adressePrincipale":{"ligne1":null,"ligne2":null}
I have create interceptor to see my json query :
public class RequestResponseLoggingInterceptor implements ClientHttpRequestInterceptor {
private final org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass());
private void logRequest(final HttpRequest request, final byte[] body) throws IOException {
if (log.isDebugEnabled()) {
log.debug("===========================request begin================================================");
log.debug("URI : {}", request.getURI());
log.debug("Method : {}", request.getMethod());
log.debug("Headers : {}", request.getHeaders());
log.debug("Request body: {}", new String(body, "UTF-8"));
log.debug("==========================request end================================================");
}
}
private void logResponse(final ClientHttpResponse response) throws IOException {
if (log.isDebugEnabled()) {
log.debug("============================response begin==========================================");
log.debug("Status code : {}", response.getStatusCode());
log.debug("Status text : {}", response.getStatusText());
log.debug("Headers : {}", response.getHeaders());
log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
log.debug("=======================response end=================================================");
}
}
#Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
logRequest(request, body);
final ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
return response;
}
}
How can i suppress all key corresponding to the null values when i call the API ?
final HttpEntity<?> httpEntity = new HttpEntity<>(adherent, headersCompleted);
responseEntity = restTemplate.exchange(urlComplete, HttpMethod.PUT, httpEntity,String.class);
Thanks :)

Obtaining exception from rest service in string variable

I have this JSON request framed in Java. I will be hitting a rest template with my URL and this request.
{
"searchRequest":{
"header":{
"agency":"1111",
"agent":"2222";
"from":"0";
"size":"15"
},
"requestParam":{
"firstName":"JOHN",
"lastName":"PAK",
"dob":"",
"driverLicense":"",
"membershipNumber":"",
"phoneNumbers": "null",
"addresses":"null"
}
}
}
CASE 1: Whenever I get a successful response, I get the same JSON which my rest template gives in the response variable.
public #ResponseBody String mpdValidate(#RequestBody String inputRequest, #RequestHeader String url)
throws JsonParseException, JsonMappingException, IOException, JSONException {
System.out.println(inputRequest);
System.out.println(url);
String response = null;
if (url == null || url.isEmpty()) {
url = "myURL";
}
try {
HttpHeaders headers = new HttpHeaders();
headers.set("X-ApplicationContext",
"{\"userId\":\"user\",\"transactionType\":\"realtime\",\"application\":\"app\",\"subSystem\":\"mpd\",\"address\":\"1.0.0.0\",\"correlationId\":\"0f333c\"} ");
HttpEntity<String> request = new HttpEntity<String>(inputRequest, headers);
response = restTemplate.postForObject(url, request, String.class);
} catch (Exception e) {
response = e.getMessage();
}
return response;
}
CASE 2: And when there is a wrong request framed and there is a failed response, the rest template returns this response.
{
"httpCode": 400,
"httpMessage": "Bad Request",
"moreInformation": "Request parameter is null",
"timeStamp": 1539072063795
}
But the response variable returns null and enters to catch block throwing null pointer exception.
I want the above JSON in string format to my response variable.
Can someone help?
try {
// ...
} catch (HttpClientErrorException expection) {
response = expection.getResponseBodyAsString();
}
You need to handle HttpClientErrorException (or its parent RestClientResponseException) and extract the response by HttpClientErrorException#getResponseBodyAsString.
You should try like this,
// REST Request
try {
restTemplate.postForObject(requestUrl, postBody, Void.class);
} catch (RestException restException) {
Logger.error(this, "RestException: " + restException.getRestError().toString());
response = restException.getRestError().toString();
}

Categories