I have more then 1 http call in try-catch block, exmaple:
try {
HttpHeaders httpHeaders = new HttpHeaders();
ResponseEntity<String> sendGet = http.sendGet(someUrl1, httpHeaders);
ResponseEntity<String> sendPost = http.sendPost(someUrl2, httpHeaders);
}catch(HttpClientErrorException e) {
//print call url here someUrl1/someUrl2
printException(e);
}
catch (Exception e) {
printException(e);
//general e
}
//Print exception
public void printException(Exception e){
//log URL here
}
I want to print the failed URL when I catch the exception but I did not find HttpClientErrorException or RestClientException property that I can use.
EDIT for general case:
I don't think you should use HttpClientErrorException for getting url, you know the URL before calling each request, so my suggestion:
Create a generic send method which receive post method, URL and headers parameters
Call your method for each request and it will also handle exceptions based on current URL
For simple case describe in question:
You can split to 2 try and catch blocks for each request
Or add a boolean ( or currentUrl String variable)
boolean isFirstRequestFinished = false;
Set it to true after first request and check in catch block
if (isFirstRequestFinished) {
Related
I made a helper funtion to hit another rest service.
public BaseResponse doPostService(String url, Object body) throws Exception {
RestTemplate rest = new RestTemplate();
try {
ResponseEntity<BaseResponse> r = rest.postForEntity(url, body, BaseResponse.class);
return r.getBody();
} catch (RestClientResponseException e) {
ObjectMapper mapper = new ObjectMapper();
// I want to return the Response body caught here
return mapper.readValue(e.getResponseBodyAsString(), BaseResponse.class);
} catch (ResourceAccessException e) {
e.printStackTrace();
throw new Exception(e.getMessage());
}
}
However, I got issue when the result of e.getResponseBodyAsString() can't be parsed to that class. Is there any possible trick to get it work without the need of creating new method?
I Use the Supplier in my code to call restTemplate and make the custom Message when have exception..
But, im my message, i need get information by my requestCall, But when i cast the request the java thow error
...
My code:
public void execute() {
HttpHeaders headers = buildDefaultHeaders();
UriBuilder uri = UriBuilder.fromUri(wdd3dGatewayEndpoint + API_URL);
HttpEntity request = new HttpEntity(headers);
this.executeRequest(() -> restTemplate.exchange(uri.build(), HttpMethod.DELETE, request, Void.class));
}
My Supplier
protected ResponseEntity executeRequest(Supplier<ResponseEntity> request) {
try {
ResponseEntity response = request.get();
updateSessionToken(response);
return response;
} catch (HttpClientErrorException | HttpServerErrorException e) {
String msg = "WDD3D-Error in service communication<br>" + e.getResponseBodyAsString();
throw new MaestroException(msg);
}
}
Now, i try cast to get URL...
protected ResponseEntity executeRequest(Supplier<ResponseEntity> request) {
try {
ResponseEntity response = request.get();
updateSessionToken(response);
return response;
} catch (HttpClientErrorException | HttpServerErrorException e) {
//THROW EXEPTION HERE... PLEASE HELP...
RequestEntity requestEntity = (RequestEntity) request;
String url = requestEntity.getUrl().toString();
String msg = "WDD3D-Error in service communication<br>" + e.getResponseBodyAsString();
throw new MaestroException(msg);
}
}]
You should use the get() method of the Supplier, see more in the docs.
RequestEntity requestEntity = (RequestEntity) request;
You are trying to cast a Supplier<ResponseEntity> to a RequestEntity.
These are two very different classes and such a cast will never work.
Maybe you want to call request.get() and get the URL from the ResponseEntity that you have.
Tell me if it works for you in the comments or we need to debug further ?
The only thing you are trying to get from the RequestEntity is the URL, which you can't get from the Supplier<ResponseEntity> since it is not a RequestEntity, so why not just pass the URL as another parameter to executeRequest? Then it would have the additional information it needs to log the error.
I'm sending API and receiving status code 400 with body I need to parse
When working with RestTemplate I failed to parse response:
try {
ResponseEntity<ResponseVO> response = restTemplate.exchange(uri, HttpMethod.POST, request, ResponseVO.class);
} catch(HttpStatusCodeException e){
// not catch
String errorpayload = e.getResponseBodyAsString();
} catch (RestClientException e) {
// catch without body
}
Also With adding error handlers (default and specific) suggested I always get a ResourceAccessException which isn't catch by HttpClientErrorException and doesn't include body/headers data
How can I still get body/headers in that case? must I use alternatives to RestTemplate ?
Moreover, how can I return to context of request when I'm in caught exception inside handleError:
public void handleError(ClientHttpResponse response) throws IOException {
The issue I was using interceptor which read my body already,
Changed RestTemplate to using BufferingClientHttpRequestFactory I can now re-read my body
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory()));
Using this wrapper allows for multiple reads of the response body.
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();
}
I am new to Spring Boot, and I am trying to test a connection using HTTP OPTIONS.
My design is that I have a Service class that contains the logics for the testing. I also have an API Controller class that implements the method from Service.
My currently understanding is that the controller can be used to respond back different HTTP statuses using exceptions.
This is the method I wrote inside the controller for this purpose:
#PostMapping(path = "/test")
public ResponseEntity<Void> testConnection(#RequestBody URL url) {
try {
ControllerService.testConnection(url);
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null);
} catch (CredentialsException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
} catch (URLException | URISyntaxException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
} catch (UnknownException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
}
The way exceptions are triggered and the method testConnection() are inside the service class:
public static void testConnection(URL url)
throws URISyntaxException, CredentialsException, URLException, UnknownException {
String authHeaderValue = "Basic " + Base64.getEncoder().encodeToString(("user" + ':' + "password").getBytes());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Authorization", authHeaderValue);
RestTemplate rest = new RestTemplate();
final ResponseEntity<Object> optionsResponse = rest.exchange(url.toURI(), HttpMethod.OPTIONS, new HttpEntity<>(requestHeaders), Object.class);
int code = optionsResponse.getStatusCodeValue();
if (code == 403) {
throw new InvalidCredentialsException();
} else if (code == 404) {
throw new InvalidURLException();
} else if (code == 500) {
throw new UnknownErrorException();
} else if (code == 200){
String message = "Test connection successful";
LOGGER.info(message);
}
}
I have created those custom exception classes.
Is this the proper way to trigger the right HTTP response inside the controller method or does Spring Boot has some other design? If so, is my list of exceptions comprehensive enough or do I need to add more to the testConnection() method in the service class?
You can write ExceptionHandler for each of the Exception type, so you don't have to repeat the code or use try/ catch block at all. Just let your testConnection and other methods to throw the exception.
import org.springframework.web.bind.annotation.ExceptionHandler;
#ExceptionHandler(CredentialsException.class)
public void credentialsExceptionHandler(CredentialsException e, HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.FORBIDDEN.value(), e.getMessage());
}
There are different ways to define and use the ExceptionHandler method. But conceptually same.