I need to send post request to external service with data. How can I achieve that in Springboot.
For example - need to connect and send a request to endpoint a 10.20.30.111:30 with some data. Then that data will be tested and send back test result as response.
I am new to java and did some research but did not get any success.
You can check HttpClient
URI uri = URI.create("10.20.30.111:30/endpoint");
HttpRequest req = HttpRequest.newBuilder().uri(uri).build();
HttpResponse<String> response = httpClient.send(req,HttpResponse.BodyHandlers.ofString());
String body = response.body();
If the response is json, you can convert the String response body to a custom object using JSONB.
Jsonb jsonb = JsonBuilder.create();
MyDataClass myDataObject = jsonb.fromJson(body, MyDataClass.class);
Check the Feign Client:
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html
Your POST request will be implemented by an Interface like:
#FeignClient("stores")
public interface StoreClient {
#RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(#PathVariable("storeId") Long storeId, Store store);
}
Related
this is my feign client code
#RequestLine("PUT /merchants/{merchantId}")
#Headers("Content-Type: application/json")
MerchantDTO updateMerchant(#Param("merchantId") Long merchantId, PutMerchantDTO putMerchantDTO);
which is called in some requestFactory class.
And this one is my controller code
#PutMapping(value = "/merchants/{merchantId}")
ResponseEntity<MerchantDTO> updateMerchant(#RequestBody #NotEmpty PutMerchantDTO updateMerchantRequest, #PathVariable("merchantId") final Long merchantId) {
return ResponseEntity.ok(merchantUpdateMapper.toDtoMerchant(merchantUpdateService.processUpdate(merchantUpdateMapper.toDomain(updateMerchantRequest, merchantId))));
}
Can somebody Please tell me why I'm getting 415 when doing the put request with this feign Client to my controller?
remove #Headers
and in #PutMapping add consumes = "application/json"
#PutMapping(value = "/merchants/{merchantId}") you write the same line like you specified in feign client
and change #Param("merchantId") to #PathVariable("merchantId")
I have an REST client:
import org.restlet.representation.ObjectRepresentation;
import org.restlet.data.MediaType;
ObjectRepresentation<ApprovalResponse> objectRepresentation = (ObjectRepresentation<ApprovalResponse>) cr.post(approvalRequest, MediaType.APPLICATION_JAVA_OBJECT);
And a Spring Boot Service RESTful api:
import org.springframework.http.MediaType;
#PostMapping(value = "/rest/approvals-submit")
public #ResponseBody ApprovalResponse submit(#RequestHeader(name="Authorization") String token, #RequestBody ApprovalRequest approvalRequest) {
System.out.println("jwt token: "+token);
System.out.println(approvalRequest.getMessageToEvaluator());
ApprovalResponse approvalResponse = new ApprovalResponse();
approvalResponse.setApprovalId("Test approvalResponse from micro service");
return approvalResponse;
}
The client calls the API successfully. i.e. the System.out.println(approvalRequest.getMessageToEvaluator()); is printed out successfully.
Problem
My issue is that the response object is not getting back to the REST client.
Error Messages
Rest client
org.restlet.resource.ResourceException: Not Acceptable (406) - The
resource identified by the request is only capable of generating
response entities which have content characteristics not acceptable
according to the accept headers sent in the request
Server/Api
Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException:
Could not find acceptable representation]
Question
So I think these errors are because the MediaTypes are not defined correctly. Do you know what they should be defined as?
Update after having a direct chat
We added on the rest endpoint, on the postMapping annotation the following:
#PostMapping(value = "/rest/approvals-submit")
public #ResponseBody ApprovalResponse submit(#RequestHeader(name="Authorization") String token, #RequestBody ApprovalRequest approvalRequest, produces={MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE},consumes = MediaType.APPLICATION_JSON_VALUE) {
System.out.println("jwt token: "+token);
System.out.println(approvalRequest.getMessageToEvaluator());
ApprovalResponse approvalResponse = new ApprovalResponse();
approvalResponse.setApprovalId("Test approvalResponse from micro service");
return approvalResponse;
}
This added on the #PostMapping annotation produces={MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE},consumes = MediaType.APPLICATION_JSON_VALUE.
On client side, we change the response type to Representation, and we were able to get the json response:
ClientResource cr = new ClientResource(endpointUrl);
ChallengeResponse challengeResponse = new ChallengeResponse(ChallengeScheme.HTTP_OAUTH_BEARER);
challengeResponse.setRawValue(token);
cr.setChallengeResponse(challengeResponse);
Request req = cr.getRequest();
Representation representation = cr.post(approvalRequest);
System.out.println(representation.getText());
Finally, using Jackson Object Mapper the response could be mapped into the Approval response object:
// now convert the response to java
ObjectMapper objectMapper = new ObjectMapper();
ApprovalResponse approvalResponse = objectMapper.readValue(json, ApprovalResponse.class);
System.out.println(approvalResponse);
System.out.println(approvalResponse.getApprovalId());
It was a content negotiation issue. The content negotiation it's done via the Content-Type header, for better understanding of it, you could read this blog entry
I'm working with Facebook messenger app (chatbot) and I want to see what GET request I'm receiving from it. I'm using Spring Framework to start http server and ngrok to make it visible for facebook.
Facebook sending webhooks to me and i receive them, but i don't understand how to extract data from this request. Here what i get when I try HttpRequest to receive GET request. ngrok screenshot (error 500).
When I tried without HttpRequest, i had response 200 (ok).
What do i need to put to parameters of my find method to see GET request data?
My code:
#RestController
public class botAnswer {
#RequestMapping(method= RequestMethod.GET)
public String find(HttpRequest request) {
System.out.println(request.getURI());
String aaa = "222";
return aaa;
}
}
I guess HttpRequest will not help you here. For simplicity, just change HttpRequest to HttpServletRequest. You can access all query string parameters from it using request.getParameter("..."). Something like the following should work:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String handleMyGetRequest(HttpServletRequest request) {
// Reading the value of one specific parameter ...
String value = request.getParameter("myParam");
// or all parameters
Map<String, String[]> params = request.getParameterMap();
...
}
This blog post shows how to use the #RequestParam annotation as an alternative to reading the parameters from HttpServletRequest directly.
I have written a REST Request mapper:
#RequestMapping(value = "/resttest", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> receiveBody(#RequestBody String bodymsg,HttpServletRequest request) {
String header_value = request.getHeader("h_key");
return new ResponseEntity<String>(HttpStatus.OK);
}
I would like to send a POST method to this like that:
public static void sendpost() {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("h_key","this is the value you need");
HttpEntity<String> entity = new HttpEntity<String>("text body", headers);
ResponseEntity<JSONObject> response = restTemplate
.exchange("http://localhost:9800/resttest", HttpMethod.POST, entity,JSONObject.class);
}
But I get this error:
Unsupported Media Type
What is the problem with my sending method?
You set server side to accept plan text only, but your request sets content_type to "application/json"... means you are telling server side that you are sending JSON format, so that server side says "I don't support this media type" ( http error code 415 )
For what you said
I tried with REST GUI client sending data to controller and worked fine.
if you specify "content-type" in the REST GUI as "text/plain", probably you will get an same error code.
For
If I change the Controller consumes part to: ALL_VALUE it works fine.
, that's because now you are telling to server side code to take all the media type (Content-Type), so whatever value you set up in client side request, it doesn't matter anymore.
I am trying to send a JSON string as a request to my application. This is my code:
#RequestMapping(
value = "/mylink/upload",
method = RequestMethod.POST,
consumes ="application/json",
produces = "application/json")
public
#ResponseBody
List<Upload> upload(
#RequestParam(value = "hdfsLocation") String hdfsLocation
) throws Exception {
return S3HdfsTransfer.uploadFromHDFS(hdfsLocation);
}
I am trying to send a request with Postman. The method I use is POST, the header contains: Accept "application/json",Content-Type "application/json", the request body is the following:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
This is the response I get. If I put the parameter in the URL, it works.
{
"httpStatus": 500,
"appErrorId": 0,
"message": "Required String parameter 'hdfsLocation' is not present",
"trackingId": "8c6d45fd-2da5-47ea-a213-3d4ea5764681"
}
Any idea what I am doing wrong?
Thanks,
Serban
Looks like you have confused #RequestBody with #RequestParam. Do either of following :
Pass the request param as a request param(not as a body). Like, (encoded)
http://example.com?hdfsLocation=http%3A%2F%2Fexample.com%3FhdfsLocation%3Dhdfs%3A%2F%2F145.160.10.10%3A8020
Replace the #RequestParam with #RequestBody. If you are sending a body, don't send it along with request param. Those are two different things.
I guess you over looked :)
Shouldn't it be #RequestBody instead of #RequestParam?
Also, even after using #RequestBody, the whole of the JSON string:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
will be the value of String hdfsLocation and not just the hdfs url. Hence, you'll have to JSON parse that JSON by yourself to get just the hdfs url.