#HystrixCommand(commandKey = "MyHystrixCommand", fallbackMethod = "myHystrixFallback", threadPoolKey = "ThreadPoolKey")
public ResponseEntity<String> getServiceCallResponse(String serviceUrl, HttpEntity<?> entity) {
ResponseEntity<String> resp = null;
try {
resp = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, String.class)
.getBody();
}
catch(Exception e) {
handleExceptionForHystrix("getServiceCallResponse", e);
}
return resp;
}
Getting error when setting resp saying it's a mismatch. Unable to understand why it's going on. What can be the alternative.
Related
I just started to use the Spring Framework and making some tests. I'm trying to reach ResponseEntity. But if the HTTP status code is not equal to 200, the ResponseEntity object is always null. Therefore I cannot reach the status code or headers.
Is there any way to reach ResponseEntity if the HTTP status code is not equal to 200?
public static String checkPatientExistence(String pNo, String eNo) throws RestClientException, NullPointerException {
String result = null;
RestTemplate restTemplate = createRestTemplate();
final String uri = apiURL + "GetInstance";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(uri)
.queryParam("pNo", pNo)
.queryParam("eNo", eNo);
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> responseEntity = null;
try {
responseEntity = restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
requestEntity,
String.class
);
} catch (RestClientException restClientException) {
System.out.println(restClientException.getMessage());
System.out.println(Arrays.toString(restClientException.getStackTrace()));
}
if (responseEntity != null) {
if (responseEntity.getStatusCode() == HttpStatus.OK) {
result = "true";
} else if (responseEntity.getStatusCode() == HttpStatus.BAD_REQUEST) {
System.out.println(responseEntity.getStatusCode().toString());
System.out.println(responseEntity.getBody());
result = "false";
} else if (responseEntity.getStatusCode() == HttpStatus.NO_CONTENT) {
System.out.println(responseEntity.getStatusCode().toString());
System.out.println(responseEntity.getBody());
result = "noContent";
}
} else if (responseEntity == null) {
System.out.println("responseEntity is null");
result = "false";
}
return result;
}
Here is the output of the method:
400 Bad Request: [{"Message":"error message"}]
[org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:101),
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:170),
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:112),
org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63),
org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:782),
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:740),
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674),
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:583),
com.xxx.xxx.App.checkPatientExistence(App.java:269), com.xxx.xxx.App.main(App.java:43)]
responseEntity is null
false
RestClientException doesn't have methods like getStatusCode() or getResponseBodyAsString(). Because of that I couldn't reach them in the catch block.
Therefore, I added another catch block for HttpsStatusCodeException and reversed the order of catch blocks.
The HttpStatusCodeException
extends RestClientResponseException
and the RestClientResponseException
extends RestClientException
Here is the sample methods we can use.
} catch (HttpStatusCodeException httpStatusCodeException) {
System.out.println(httpStatusCodeException.getStatusCode());
System.out.println(httpStatusCodeException.getResponseBodyAsString());
System.out.println(httpStatusCodeException.getStatusText());
System.out.println(httpStatusCodeException.getRawStatusCode());
System.out.println(httpStatusCodeException.getMessage());
} catch (RestClientException restClientException) {
// catch
}
You already have your response for status codes other than 200 in catch block. Define your ResponseEntity object inside catch block.
catch (HttpStatusCodeException exception) {
//Add data to responseEntity
}
I am trying to use OAuth2RestOperations to call an api like below and getting "java.lang.IllegalArgumentException: URI is not absolute" exception. What am I missing?
public void sendSMS(String message, String destination) {
String messageUrl = "http://baseurl/uri"
System.out.println("Message url: " + messageUrl);
JSONObject messageObject = new JSONObject()
.put("message", message)
.put("destination", destination);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
headers.add("Accept", "application/json");
HttpEntity<Object> request = new HttpEntity<>(messageObject, headers);
try {
ResponseEntity<String> exchange = restTemplate
.exchange(URI.create(messageUrl), HttpMethod.POST, request, String.class);
System.out.println("Response is: " + exchange.getBody());
} catch (Exception e) {
e.printStackTrace();
}
Found the issue. While configuring the OAuthTemplate I missed to provide the full url.
#Bean
public OAuth2ProtectedResourceDetails clientCredentialsResourceDetails() {
ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri(
"http://baseurl/token") resource.setGrantType("client_credentials");
resource.setClientId(sapProperties.getAppKey());
resource.setClientSecret(sapProperties.getAppSecret());
return resource;
}
I have this method
public HTTPResult post(String url, String requestBody) throws Exception {
return HTTPPostPut(url, requestBody, HttpMethod.POST);
}
public HTTPResult HTTPPostPut(String url, String requestBody,HttpMethod httpMethod) throws Exception {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("content-type","application/json");
HttpEntity requestEntity = new HttpEntity(requestBody,headers);
try {
ResponseEntity<String> response = this.restTemplate.exchange(url, httpMethod, requestEntity, String.class);
return new HTTPResult((String) response.getBody(), response.getStatusCode().value());
} catch (ResourceAccessException var8) {
String responseBody = var8.getCause().getMessage();
JSONObject obj = new JSONObject(responseBody);
return new HTTPResult(obj.getString("responseBody"), Integer.parseInt(obj.getString("statusCode")));
}
}
Which I created for it mock and getting null pointer exception:
public void testPost() throws Exception{
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("content-type","application/json");
HttpEntity requestEntity = new HttpEntity("{blbl}",headers);
ResponseEntity<String> response = new ResponseEntity("{blbl}", HttpStatus.OK);
RestTemplate mockRestTemplate = mock(RestTemplate.class);
when(mockRestTemplate.exchange(baseUrl, HttpMethod.POST, requestEntity, String.class)).thenReturn(response);
RestAPI api = new RestAPI(mockRestTemplate);
HTTPResult res = null;
try {
res = api.post(baseUrl,"{blbl}");
} catch (IOException e) {
e.printStackTrace();
}
assertEquals(res.getResponseBody(), "{blbl}");
assertEquals(res.getStatusCode(), HttpStatus.OK.value());
}
I am getting null pointer exception when calling:
res = api.post(baseUrl,"{blbl}");
This is because the response is null.
Use an argument matcher when arranging the mock as the instance being passed to the mocked dependency is different to what is passed when the test is exercised.
This will cause the mock to return null response as expected instances do not match
Refactor the test
public void testPost() throws Exception {
//Arrange
String expected = "{blbl}";
ResponseEntity<String> response = new ResponseEntity(expected, HttpStatus.OK);
RestTemplate mockRestTemplate = mock(RestTemplate.class);
when(mockRestTemplate.exchange(eq(baseUrl), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class)))
.thenReturn(response);
RestAPI api = new RestAPI(mockRestTemplate);
//Act
HTTPResult res = api.post(baseUrl, expected);
//Assert
assertEquals(res.getResponseBody(), expected);
assertEquals(res.getStatusCode(), HttpStatus.OK.value());
}
Note the use of the any(HttpEntity.class) matcher which will allow the passed HttpEntity to be matched when invoked.
Since the use of argument matches is none or all, the eq() matcher is used for the remaining constant arguments.
I try to develop a global webservice method in my spring boot project and I want to return my response body type according to request body type. Whatever I do, all response return json type.
#RestController
#RequestMapping(value = "/virtual/**", produces = {"application/json", "application/xml", "text/xml"}, consumes = MediaType.ALL_VALUE)
public class VirtualServiceGateway {
private IVirtualDocumentService virtualService = UtilsForSpring.getSingleBeanOfType(IVirtualDocumentService.class);
#RequestMapping(method = RequestMethod.GET)
public Response requestGET(HttpServletRequest request, HttpServletResponse response) {
IVirtualDocumentService docService = UtilsForSpring.getSingleBeanOfType(IVirtualDocumentService.class);
docService.findDocumentByVirtualUrl(request.getRequestURL().toString());
if (docService == null) {
return Response.status(404).type(request.getContentType()).entity("There is no anything").build();
}
return Response.status(200).type(request.getContentType()).entity("ok!").build();
}
I didn't find something what I want. But I found ResponseEntity, and we can use it like below. In there I can return entity type according to request/response headers.
It works for me, may be useful for somebody
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity requestTEST(HttpServletRequest request, HttpServletResponse response) {
// HttpGet httpGet = new HttpGet("http://www.webservicex.net/country.asmx/GetCountries"); // xml output format
HttpGet httpGet = new HttpGet("http://services.groupkt.com/country/get/all");//json output format
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse res = null;
StringBuilder resEntity = null;
try {
res = httpClient.execute(httpGet);
resEntity = new StringBuilder();
BufferedReader bf = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
List<String> lines = IOUtils.readLines(bf);
for (String line : lines) {
resEntity.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
for (Header h : res.getAllHeaders()) {
headers.add(h.getName(), h.getValue());
}
return new ResponseEntity(resEntity, headers, HttpStatus.valueOf(res.getStatusLine().getStatusCode()));
}
My rest server is generating response when I called it with rest client software. When I call it with resttemplate code mentioned above, then server generates response(print logs) but resttemplate does nothing(no next line executes after call) and prints internal error.
This is the method in my server
#ResponseBody
public ResponseEntity<Map<String, Object>> name(){......
...
return new ResponseEntity<Map<String, Object>>(messagebody, HttpStatus.OK);
}
This is the way I am calling it through restTemplate
ResponseEntity<Map> response1 = restTemplate.getForEntity(finalUrl.toString(), Map.class);
Try to use ParameterizedTypeReference instead of wildcarded Map.
It should looks like this.
ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
ResponseEntity<Map<String, Object>> response = restTemplate.exchange(finalUrl.toString(), HttpMethod.GET, null, typeRef);
this is a example that works for me
#RequestMapping(value = "/getParametros/{instancia}", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> getParametros(#PathVariable String instancia)
{
LOG.debug("REST. Obteniendo parametros del servidor " + instancia);
Map<String, String> mapa = parametrosService.getProperties(instancia);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json; charset=UTF-8");
headers.add("X-Fsl-Location", "/");
headers.add("X-Fsl-Response-Code", "302");
ObjectMapper mapper = new ObjectMapper();
String s = "";
try
{
s = mapper.writeValueAsString(mapa);
} catch (JsonProcessingException e)
{
LOG.error("NO SE PUEDE MAPEAR A JSON");
}
if (mapa == null)
return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<String>(s, headers, HttpStatus.OK);
}
you can Catch the HttpStatusCodeException from which you can get response in String .
below code works for me.
restTemplate.postForObject( url, jsonRequest, ResponseData.class );
catch( HttpStatusCodeException codeException )
{
String payload = codeException.getResponseBodyAsString();
System.out.println( payload );
}