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();
}
Related
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?
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 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);
}
}
}
I have a Spring Boot application written in Java that is a REST API. This service (Svc A) calls a REST API service (Svc B) with is also a Spring Boot Application written in Java. Svc B returns a 404 status code when no data was found. I need to change this response to a 200 status code and return an empty response object. I am not sure if or how to do this.
I can catch the error and determine if the 404 is this no data found error. However, I don't know how to change the response to a 200 empty response.
I am using a FeignClient to call the service. This is the error code that catches the 404:
#Component
public class FeignErrorDecoder implements ErrorDecoder {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public Exception decode(String methodKey, Response response) {
Reader reader = null;
String messageText = null;
switch (response.status()){
case 400:
logger.error("Status code " + response.status() + ", methodKey = " + methodKey);
case 404:
{
logger.error("Error took place when using Feign client to send HTTP Request. Status code " + response.status() + ", methodKey = " + methodKey);
try {
reader = response.body().asReader();
//Easy way to read the stream and get a String object
String result = CharStreams.toString(reader);
logger.error("RESPONSE BODY: " + result);
ObjectMapper mapper = new ObjectMapper();
//just in case you missed an attribute in the Pojo
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//init the Pojo
ExceptionMessage exceptionMessage = mapper.readValue(result,
ExceptionMessage.class);
messageText = exceptionMessage.getMessage();
logger.info("message: " + messageText);
} catch(IOException ex) {
logger.error(ex.getMessage());
}
finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseStatusException(HttpStatus.valueOf(200), messageText);
}
default:
return new Exception(response.reason());
}
}
}
I can change the status code to a 200 and it returns a 200 but I need to the response to have an empty response object.
The above code will return this response body of an error response object:
{
"statusCd" : "200",
"message" : "The Location not found for given Location Number and Facility Type Code",
"detailDesc" : "The Location not found for given Location Number and Facility Type Code. Error Timestamp : 2020-01-31 18:19:13"
}
I need it to return a response body like this:
200 - Empty Response
{
"facilityNumber": "923",
"facilityTimeZone": null,
"facilityAbbr": null,
"scheduledOperations": []
}
In case 404 just try
return new ResponseStatusException(HttpStatus.valueOf(200));
For anyone that has to do something this crazy...here is my solution:
Removed the FeignErrorCode file.
Added an exception to ControllerAdvice class like this:
#ExceptionHandler(FeignException.class)
public ResponseEntity<?> handleFeignException(FeignException fe, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), HttpStatus.valueOf(fe.status()), fe.getMessage(), request.getDescription(false));
String response = fe.contentUTF8();
if(response != null) {
ScheduledOperationsViewResponse scheduledOperationsViewResponse = new ScheduledOperationsViewResponse();
if (response.contains("Scheduled") || response.contains("Location")) {
HttpHeaders headers = new HttpHeaders();
scheduledOperationsViewResponse.setFacilityNumber(request.getParameter("facilityNumber"));
return new ResponseEntity<ScheduledOperationsViewResponse>(scheduledOperationsViewResponse, headers, HttpStatus.OK);
}
}
return new ResponseEntity<>(errorDetails, errorDetails.getStatus());
}
Might be a dumb question but how can I retrieve the value of the response given by the RequestBuilder in a JSON format. My code is this:
try {
Request request = builder.sendRequest(json, new RequestCallback() {
public void onError(Request request, Throwable exception) {
System.out.println("CAN'T CONNECT");
// Couldn't connect to server (could be timeout, SOP violation, etc.)
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
System.out.println("SUCCESS");
System.out.println(response.getText());
// Process the response in response.getText()
} else {
System.out.println("ERROR" + response.getStatusCode() + response.getText());
// Handle the error. Can get the status text from response.getStatusText()
}
}
});
} catch (RequestException e) {
System.out.println(e);
}
Currently, the response gives me {faceAmount: 29921}. How do I access the value for faceAmount and store it to a variable? Is the response providing me with a JSON format or just straight up text string?
You can use com.google.gwt.json.client, or use JSNI and overlay types, or better, use JsInterop. You'll find more in the docs: http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSON.html, http://www.gwtproject.org/doc/latest/tutorial/JSON.html, http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJsInterop.html
#JsType(isNative=true)
interface Response {
#JsProperty int getFaceAmount();
}
Response r = (Response) (JavaScriptObject) JsonUtils.parse(json);