I'm trying to use RestTemplate to call POST api like that :
RequestorParam test = new RequestorParam();
test.setScopeMcg("MCG");
test.setSituatedDealIds(situatedDealIds);
String url = "http://localhost:" + serverPort + "/retrieveAttributes";
ResponseEntity<SituatedDeals> response = restTemplate.postForEntity(url, test, SituatedDeals.class);
and the code of the controller is like ;
#PostMapping(value = "/retrieveAttributes", produces = "application/json")
#ResponseBody
#Duration
public SituatedDeals retrieveAttributes(
#RequestParam String scopeMcg,
#RequestBody SituatedDealIds situatedDealIds
) {
log.info("success")
}
i'm getting bad request, can someone help ?
According to your controller code, you are actually not returning any Response Entity of type SituatedDeals, just logging it as success. this might be the reason for the null object in response.
The scopeMcg is a RequestParameter so you should be passing it in a request param format i.e http://localhost:8080/retrieveAttributes?scopeMcg=MCG
Reference:Spring Request Param
Your test Object is the actual payload for your post request which should be of type SituatedDealIds object.
Reference: Rest-Template post for Entity
Related
I am having a piece of code like below for calling one of our service.
MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<>();
parametersMap.add("query", query);
parametersMap.add("locale", "en_US");
parametersMap.add("resultsLimit", Boolean.FALSE.toString());
parametersMap.add("maxResults", maxResults);
parametersMap.add("type", "TTT");
parametersMap.add("ids", commaSeparatedValues(ids));
parametersMap.add("infoTypes", "HHH,JJJ");
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(parametersMap, getHttpHeaders());
MyEntity myEntity = restTemplate.postForEntity("http://example.com", httpEntity, MyEntity.class);
And at the server side the controller code is like
#RequestMapping("my/service")
public MyEntity suggest(#RequestParam(required = true) String query, #RequestParam(required = true) String locale,
#RequestParam(required = false) String resultsLimit, #Valid OtherOptions options)
and the OtherOption class is like
class OtherOptions {
String maxResults;
String type;
String ids;
String infoTypes;
}
Here everything is working fine, but I am confused about somethings like .
Is it a get or post request ?
How is some of the parameter maps content become request params(query params) and some others got mapped to the Object of OtherOptions ?
Which is the actual body of the request ?
Is it a get or post request ?
It is a post request. you are calling restTemplate.postForEntity. But your server side method is not restricted as you didn't specify the method attribute for RequestMapping so same method can handle any http method from the point of server.
How is some of the parameter maps content become request params(query params) and some others got mapped to the Object of OtherOptions?
None of them are query params.
See the spring docs for the meaning of #RequestParam. In your case, it all comes from body and not as query params
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#postForEntity-java.net.URI-java.lang.Object-java.lang.Class-
The body of the entity, or request itself, can be a MultiValueMap to create a multipart request.
Which is the actual body of the request?
parametersMap is the body of the http request.
Note:
Currently your call should fail because you are posting it to http://example.com at client and listening at server side on my/service
I have the below post request and of which below is the controller code
#RestController
#RequestMapping(/flow", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
#Override
#ResponseStatus(HttpStatus.OK)
#PostMapping("{abcCode}/token")
public TokenResponse createToken(#PathVariable("abcCode") String abcCode,
#RequestParam("grant_type") String grantType,
#RequestParam String code,
#RequestParam("redirect_uri") String redirectUri,
#RequestParam String clientId) {
LOG.info(
"Received call for createIdToken for abcCode: {} , clientId: {} , grantType: {} ,code: {} , redirectUri: {}",
abcCode, clientId, grantType, code, redirectUri);
}
Now the problem is that when I test the same above controller through postman by choosing the body type as application form-encoded then it is working fine but when I choose the body type as none in postman and just pass the above request parameters as query one then also it works which ideally it should not please advise how can I overcome from the same
http://localhost:19080/testService/flow/token?grant_type=authorization_code&code=3272&redirect_uri=http://www.abchui.com&clientId=ATS
it should not work for the above URL
From spring sources:
public static final String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded";
According to docs, when using url-form-encoded data pass as query params.
Try to change form mime type.
I am trying to query a server that looks like this:
Server Code
#RequestMapping(value = "/query_user", method = RequestMethod.GET)
public String queryUser(#RequestParam(value="userId", defaultValue="-1") String userId)
{
int id = Integer.parseInt(userId);
User user = this.service.getUser(id);
...
return userJson;
}
This method works when I test with PostMan
Client Code
private synchronized void callServer(int id)
{
final String URI = "http://localhost:8081/query_user";
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, Object> map = new LinkedMultiValueMap();
map.add("userId", id);
restTemplate.getMessageConverters()
.add(new MappingJackson2HttpMessageConverter());
// Modified to use getForEntity but still this is not working.
ResponseEntity<String> response
= restTemplate.getForEntity(URI, String.class, map);
}
How can I fix this? It is important that I receive the userJson from the Server side.
EDIT
After changing to getForEntity() method I keep getting the defaultValue of -1 on the server side. There must be something else wrong with my code. I am definitly sending a userId that is NOT -1.
Your queryUser() method mapped to GET; from client you call POST restTemplate.postForEntity
I was able to solve it by using a UriComponentsBuilder.
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(URI)
.queryParam("userId", id);
Essentially it is appending the parameter to the URI which is what I believe PostMan is doing (that is how I thought about it).
Reference:
https://www.oodlestechnologies.com/blogs/Learn-To-Make-REST-calls-With-RestTemplate-In-Spring-Boot
I'm building a REST API using Java and Spring and I need to handle a POST request in my controller, but I need to extract the body from that request which is a JSON and also the "origin" of that request,
#RequestMapping(value = "/create", method = RequestMethod.POST)
public XXX createMyObject(#RequestBody String data, YYY){
MyObject mo = new MyObject();
mo.setData = data;
mo.setOrigin = yyy;
myRepository.save(mo);
return XXX;
}
I have a few questions: First is how can I obtain the origin of that request( which I guess is an url that travels in the header?), is there a similar annotation as the #RequestBody for that?.
My second question is what is usually the proper object to return in these kind of post methods as a response.
To answer your questions:
If you include HttpServletRequest in your method parameters you will be able to get the origin information from there. eg.
public XXX createMyObject(#Requestbody String data, HttpServletRequest request) {
String origin = request.getHeader(HttpHeaders.ORIGIN);
//rest of code...
}
For rest responses you will need to return a representation of the object (json) or the HttpStatus to notify the clients whether the call wass successful or not. eg
Return ResponseEntity<>(HttpStatus.ok);
You should be able to get headers and uris from HttpServletRequest object
public XXX createMyObject(#RequestBody String data, HttpServletRequest request)
As for response I'd say return String which would be a view name to which you can pass some attributes saying that operation was successful or not, or ModelAndView.
#Autowired
private HttpServletRequest servletRequest;
You can declare request object and then access in method to get Uri
Try this:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public XXX createMyObject(HttpServletRequest request, #RequestBody String body) {
String origin = URI.create(request.getRequestURL().toString()).getHost();
System.out.println("Body: " + body + " Origin:" + origin);
return XXX;
}
private ArrayList<NameValuePair> mParams;
HttpClient client = new DefaultHttpClient();
mParams = new ArrayList<NameValuePair>();
mParams.add(new BasicNameValuePair("testKey", "John"));
mParams.add(new BasicNameValuePair("testSerial", "003-100"));
HttpPost request = new HttpPost("http://localhost:8080/test/getRequiredEnv");
request.setEntity(new UrlEncodedFormEntity(mParams, HTTP.UTF_8));
HttpResponse response = client.execute(request);
// TestController.java
#RestController
public class TestController {
private static final Logger logger = Logger.getLogger(TestController.class);
#RequestMapping(value = "/getRequiredEnv", method = RequestMethod.POST)
public #ResponseBody ResponseInfo getRequiredEnv(
#RequestParam("testKey") String testKey,
#RequestParam("testValue") String testValue,
#RequestHeader HttpHeaders headers) {
logger.info("Test Key [" + testKey + "]");
logger.info("Test Value [" + testValue + "]");
return new TestResponseInfo("0001", "ABC");
}
Can someone please tell me is this the correct way to get data from 'Request.setEntity' in SpringMVC rest controller or I am missing something?
Secondly, in postman "httpPost" request I pass the parameters (testKey & testValue) as headers or as body?
Thirdly, without knowing the parameters in httpPost request can I able to parse the incoming request and extract the parameters from it in Spring controller?
First of all it would be good to know the content-type of the request that is sent.
So I guess you want to get the body of the request. To get all request parameters if you don't know the parameter names beforehand you can use #RequestParam with type Map<String, String> to get all params:
#RequestMapping(value = "/getRequiredEnv", method = RequestMethod.POST)
public #ResponseBody ResponseInfo getRequiredEnv(
#RequestParam Map<String, String> allParams,
#RequestHeader HttpHeaders headers)
But I am not sure if this works because it also depends on the content-type. E.g. for form data (application/x-www-form-urlencoded) have a look at the Spring documentation about #RequestBody which states about one of the default message converters FormHttpMessageConverter:
FormHttpMessageConverter converts form data to/from a MultiValueMap.
So try:
#RequestMapping(value = "/getRequiredEnv", method = RequestMethod.POST)
public #ResponseBody ResponseInfo getRequiredEnv(
#RequestBody MultiValueMap<String, String>,
#RequestHeader HttpHeaders headers)
Alternatively there is also HttpServletRequest.getParameterMap() which gets you a Map. You can get the request by just including HttpServletRequest request as a method argument.
If you know the paramters beforehand, annotating your POJO that resembles the form data with #ModelAttribute should also work like so:
#RequestMapping(value = "/getRequiredEnv", method = RequestMethod.POST)
public #ResponseBody ResponseInfo getRequiredEnv(
##ModelAttribute Test myTestPojo,
#RequestHeader HttpHeaders headers)
Or you could also send data as application/json and when including jackson as a dependency, #Requestbody will map your data to a POJO. Have a look at e.g. Spring JSON request body not mapped to Java POJO.
In regard to your second question httpPost will pass the parameters as body since it is a POST request.