Get status response (like 400,500) - spring

I am using the spring Framework which has the header below:
import org.springframework.web.client.RestTemplate;
I want to fetch the status code to write my Logger. How do I get the response from restTemplate?
public boolean performTransition(String transitionId,String jiraId){
JiraID id = new JiraID(transitionId);
JiraTransition transition = new JiraTransition();
transition.setTransition(id);
String transitionUrlFormat = String.format(transitionUrl,jiraId);
RestTemplate template = new RestTemplate();
HttpEntity epicEntityRequest = new HttpEntity(transition,createHttpHeaders());
HttpEntity<String> epicEntityResponse= template.exchange(transitionUrlFormat , HttpMethod.POST, epicEntityRequest, String.class);
//TODO: verify code 204
ResponseEntity<String> responseEntity= (ResponseEntity<String>) epicEntityResponse;
epicEntityResponse.getBody();
//System.out.println("LOG" +responseEntity);
//responseEntity.getStatusCode();
HttpStatus statusCode = responseEntity.getStatusCode();
return true;
}
Also, I want to check for the response code above 400 I want write log.warning().

Question needs more elaboration. Are you meaning something like this:
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request, String.class);
int statusCode = response.getStatusCode().value();
This gives status code as an int, you can do something like:
if(statusCode > 400){
//Log here
}
The class ResponseEntity can give you the entire HTTP response status code, body and headers.
Ofcourse, you need to initialize restTemplate, either using default:
RestTemplate restTemplate = new RestTemplate();
This uses, default: SimpleClientHttpRequestFactory, or if you want something more configurable you can use: HttpComponentsClientHttpRequestFactory which has many configs, like connection pooling etc, read timeout, connection timeout etc.

Related

Sending request with headers to third parts api with WebClient

I really like the solution I have with RestTemplate but soon it will be depreciated with future spring releases. I am trying to send some text to a third party api using WebClient
String text = URLEncoder.encode(text,"UTF-8");
WebClient webClient = WebClient.builder()
.baseUrl(BASE_URL)
.defaultHeader("Key","af999-e99-4456-b556-4ef9947383d")
.defaultHeader("src", srcLang)
.defaultHeader("tgt", tgtLang)
.defaultHeader("text", text)
.build();
Then send a post here:
Mono<String> response = webClient.post().uri("/google/rtv/text")
.retrieve()
.bodyToMono(String.class);
Trying to parse based off of the legacy response:
private String parseJson( Mono<String> response) {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = null;
JsonNode review = null;
//TODO: create an object and map it here. We need to save the original review too.
try {
root = mapper.readTree(response.toString());
review = root.path("message");
} catch (IOException e) {
e.printStackTrace();
}
return review.asText();
}
Later I need to parse the response but right now I am getting an error saying:
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'MonoFlatMap': was expecting ('true', 'false' or 'null')
at [Source: (String)"MonoFlatMap"; line: 1, column: 23]
and later:
java.lang.NullPointerException: null
What I am trying to accomplish is something like I have done with RestTemplate.
Like so:
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString(URL)
.queryParam("src", src)
.queryParam("tgt", tgt)
.queryParam("text", text);
ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, request, String.class);
then set my header for the subscription globally.
private ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add("Key","af999-e99-4456-b556-4ef9947383d");
ClientHttpResponse response = execution.execute(request, body);
return response;
}
#Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Collections.singletonList(this::intercept));
return restTemplate;
}
Advice?
The problem happens here:
root = mapper.readTree(response.toString());
This code snippet is trying to serialize a Mono<String> as a String, when a Mono is a reactive type that can provide that String value eventually.
You could call response.block() and getting the resulting String, but this would be a blocking call and Reactor forbids that if in the middle of a reactive execution. This is done for good reasons, since this will block one of the few threads that your web application is using and can cause it to stop serving other requests.
You could instead have something like:
Mono<String> review = response.map(r -> parseJson(r);
And then reuse that new value down the line.
Note that WebClient natively supports JSON deserialization and you could deserialize the whole payload like so:
Mono<Review> review = webClient.post().uri("/google/rtv/text")
.retrieve()
.bodyToMono(Review.class);

spring boot rest client connection Exception:: org.springframework.web.client.HttpClientErrorException: 400 null

while i am executing below code i am getting error like
"org.springframework.web.client.HttpClientErrorException: 400 null".
but when i use postman to call this "http://localhost:2018/test" it is working.
static final String URL_EMPLOYEES = "http://localhost:2018/test";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(new MediaType[] {
MediaType.APPLICATION_JSON}));
// Request to return XML format
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("replyMsg", "str");
// HttpEntity<Employee[]>: To get result as Employee[].
HttpEntity<String> entity = new HttpEntity<String>(headers);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
// Send request with GET method, and Headers.
ResponseEntity<String> response =
restTemplate.exchange(URL_EMPLOYEES,
HttpMethod.POST, entity,String.class);
HttpStatus statusCode = response.getStatusCode();
// Status Code: 200
if (statusCode == HttpStatus.OK) {
// Response Body Data
msg=response.getBody();
if (msg != null) {
System.out.println(msg);
}
}
//my clint controller class
#RestController
public class TextController {
#RequestMapping(value="/test",method = RequestMethod.POST)
public String myData2(#RequestBody String payload) {
return "done";
}
}
any suggetions?
If you're using Jackson as your JSON parser, you can simply declare your parameter with the type TextNode. This is the Jackson type representing JSON strings.
public String updateName(#PathVariable(MY_ID) String myId, #RequestBody TextNode name) {
You can then use its asText method to retrieve its text value.
Here you are setting headers Content-Type with type JSON and passing the body of type text/String.
headers.setContentType(MediaType.APPLICATION_JSON); //setting your Content type as JSON.
So, First you need to change this to
headers.setContentType(MediaType.TEXT_PLAIN); //setting your Content type as Pure Text String.
and add some code after this line
// HttpEntity<Employee[]>: To get result as Employee[].
HttpEntity<String> entity = new HttpEntity<String>(headers);
add this code
// HttpEntity<Employee[]>: To get result as Employee[].
HttpEntity<String> entity = new HttpEntity<String>(headers);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
// Send request with GET method, and Headers.
String entity_Str = new ObjectMapper().writeValueAsString(entity);
ResponseEntity<String> response =
restTemplate.exchange(URL_EMPLOYEES,
HttpMethod.POST, entity_Str, String.class);
This might work for you.. Thanks :)

RestTemplate call returns 401 Unauthorized

Background
I am trying to consume a REST endpoint hosted on IBM Cloud API from my SpringBoot application using RestTemplate. I am using the following snippet to make the call:
RestTemplate send = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setCacheControl(CacheControl.noCache());
headers.set("x-ibm-client-id", clientId);
headers.set("x-ibm-client-secret", clientSecret);
HttpEntity<BodyEntity> httpEntity = new HttpEntity<>(bodyEntity, headers);
send.exchange(ENDPOINT_URL, HttpMethod.POST, httpEntity, Object.class);
I used the following snippet to configure RestTemplate
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
Problem
Using this snippet, when the call is made I receive 401 Unauthorized. When I made the same call using Postman, I received correct response from server without any problem.
Since I received 401 response code I set to further investigate the request by logging headers and body and other parts of request.
I implemented ClientHttpRequestInterceptor to log outgoing requests to further debug the issue and added this interceptor to my RestTemplate config as follows:
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// new code
builder.interceptors(new LoggingClientHttpRequestInterceptor());
return builder.build();
}
After making the request again, I could see in the log that the outgoing call contained all details as it should e.g. Headers and Body were correct.
After this, I changed the whole thing to use Apache HTTP Client as follows:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(URL);
String reqString = "BODY";
httpPost.setEntity(new StringEntity(reqString, ContentType.APPLICATION_JSON));
httpPost.setHeader("accept", "application/json");
httpPost.setHeader("content-type", "application/json");
httpPost.setHeader("cache-control", "no-cache");
httpPost.setHeader("x-ibm-client-id", clientId);
httpPost.setHeader("x-ibm-client-secret", clientSecret);
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
System.out.println("Response status: " + response.getStatusLine());
HttpEntity entity1 = response.getEntity();
System.out.println("Response :" + entity1.toString());
} finally {
response.close();
}
Using the snippet above, I executed the request and received correct response.
Question
Why RestTemplate call returns and error whereas HttpClient returns correct response?
Do I need to further configure RestTemplate?
What have I missed?

How to send GET request with headers by Spring

It will call another REST API with a GET request.
#RequestMapping(value = "xxxx/{id}", method = RequestMethod.GET)
public #ResponseBody GetObjet GET( #PathVariable("id") String id,
#RequestHeader(value="X-Auth-Token") String Token) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("X-Auth-Token", Token);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<GetObjet> response = restTemplate.exchange(url, HttpMethod.GET, entity, GetObjet.class);
return response.getBody();
}
Always 400 Error. It means that bad request or some errors in the request body. But this is GET so the resquest bodys is always empty. So this way to add header may be not right. Any ideas?
You can obtain the headers including the notation #RequestHeader in your method
public void displayHeaderInfo(#RequestHeader("Accept-Encoding") String encoding,
#RequestHeader("Keep-Alive") long keepAlive) {
}
o
You can read more about the request here
And the other way to abtain the URL is:
#RequestMapping(value = "/restURL")
public String serveRest(#RequestBody String body, #RequestHeader HttpHeaders headers){
//Use headers to get the information about all the request headers
long contentLength = headers.getContentLength();
...
StreamSource source = new StreamSource(new StringReader(body));
YourObject obj = (YourObject) jaxb2Mashaller.unmarshal(source);
...
}
Try using:
RestTemplate.getForEntity(url, GetObject.class);
You have some methods to request data from a rest API, such as getForEntity and getForObject, use the one you needed.

perform a get request with spring rest template and check returned status code is ok

Its just submitting the sitemap to google so far i have
RestTemplate restTemplate = new RestTemplate();
HttpEntity<?> responseEntity = restTemplate.getForEntity("http://www.google.com/webmasters/tools/ping?sitemap={url}", String.class,"http://mySite.com/sitemap.txt);
How do I check the server HTTP status that is returned?
restTemplate.getForEntity(String, Class<T>, String...) returns a ResponseEntity<T> (extends HttpEntity), which has a method for retrieving the status code.
ResponseEntity.getStatusCode()
You should utilize that instead of HttpEntity.
You need to execute request and check response status.
Example code:
//when
ResponseEntity<Void> response = restTemplate.exchange(uri, HttpMethod.GET, HttpEntity.EMPTY, Void.class);
//then
assertEquals(HttpStatus.OK, response.getStatusCode());

Resources