Unable to generate access token - spring-boot

I am getting exception while generating an Access Token using feign client. The same payload is working fine in the Postman.
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("grant_type", "client_credentials");
map.add("client_id", "67881e5b-f5d5-4085-8762-c35b7b6aeede");
map.add("client_secret", "D-85Pg3wN63dmznxa-puB_89Po~o5CsKhA");
map.add("scope", "https://graph.microsoft.com/.default");
AccessTokenResponse openIdTokenResponse = graphAPILoginFeignClient.getAccessIdToken("5494cc2e-fb14-4a2d-bb5e-bf164d9141cf",request);
Feignclient code:
#FeignClient(name = "GraphAPILoginFeignClient", url = "${graphApiLoginUrl}")
public interface GraphAPILoginFeignClient {
#PostMapping(value = "/{tenantID}/oauth2/v2.0/token",consumes = MediaType.APPLICATION_JSON_VALUE)
AccessTokenResponse getAccessIdToken(#PathVariable("tenantID") String tenantID,
#RequestBody MultiValueMap<String, Object> request);
}
Exception:
{
"timestamp": "2021-01-27T17:30:34.456+00:00",
"message": "[400 Bad Request] during [POST] to [https://login.microsoftonline.com/5494cc2e-fb14-4a2d-bb5e-bf164d9141cf/oauth2/v2.0/token] [GraphAPILoginFeignClient#getAccessIdToken(String,AuthorizationTokenRequest)]:
[{\"error\":\"invalid_request\",
\"error_description\":\"AADSTS900144: The request body must contain the
following parameter: 'grant_type'.\\r\\n
Trace ID: b8ef5f37-95f7-4427-8f0e-146a34b65000\\r\\n
Correlation ID: ... (503 bytes)]","details": "uri=/accessmanagement/allusers"
}
Same request payload working from Postman:

I had the same problem and the same code.
I was able to successfully execute the code by replacing the class method MultiValueMap::put with MultiValueMap::set.
In the LinkedMultiValueMap class, these methods are implemented differently.

Related

HttpClientErrorException$BadRequest: 400 : [no body] when calling restTemplate.postForObject

I am calling a POST service getOrder3 written in SpringBoot which is working fine (tested in Postman), but getting error when called via restTemplate.postForObject from another service. I tried 2 versions of the client service getOrderClient and getOrderClient2, but both are giving same error :
HttpClientErrorException$BadRequest: 400 : [no body]
Please find the details below. Any help is appreciated.
getOrder3
#PostMapping(value="/getOrder3/{month}",produces="application/json")
public ResponseEntity<OrderResponse> getOrder3(
#PathVariable("month") String month,
#RequestParam String parmRequestSource,
#RequestParam(required=false) String parmAudienceType,
#RequestBody OrderRequestForm orderRequestForm) {
OrderResponse orderResponse = new OrderResponse();
log.info("In getOrder3...parmRequestSource = " + parmRequestSource + " parmAudienceType = " + parmAudienceType);
try {
//validate JSON schema
//orderService.validateMessageAgainstJSONSchema(orderRequestForm);
//process order
orderResponse = orderService.processOrder(orderRequestForm);
orderResponse.setParmRequestSource(parmRequestSource);
orderResponse.setParmAudienceType(parmAudienceType);
orderResponse.setMonth(month);
}catch (Exception e) {
throw new OrderException("101", e.getMessage(), HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(orderResponse,HttpStatus.OK);
}
The service is working fine , tested in postman
Now when I try to call via another microservice via restTemplate.postForObject, I get the error. Tried 2 versions of the client as below, getOrderClient and getOrderClient2
getOrderClient
#PostMapping(value="/getOrderClient/{month}",produces="application/json")
public OrderResponse getOrderClient(
#PathVariable("month") String month,
#RequestParam String parmRequestSource,
#RequestParam String parmAudienceType,
#RequestBody OrderRequestForm orderRequestForm) throws URISyntaxException, JsonProcessingException {
RestTemplate restTemplate = new RestTemplate();
URI uri = new URI("http://localhost:51001/orders/v1/getOrder/"+month+"?parmRequestSource="+parmRequestSource+"&parmAudienceType="+parmAudienceType);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String requestJson = new ObjectMapper().writeValueAsString(orderRequestForm);
HttpEntity<String> httpEntity = new HttpEntity<String>(requestJson,headers);
String response = restTemplate.postForObject(uri, httpEntity, String.class);
return new ObjectMapper().readValue(response, OrderResponse.class);
}
getOrderClient2
#PostMapping(value="/getOrderClient2/{month}",produces="application/json")
public OrderResponse getOrderClient2(
#PathVariable("month") String month,
#RequestParam String parmRequestSource,
#RequestParam String parmAudienceType,
#RequestBody OrderRequestForm orderRequestForm) throws URISyntaxException, JsonProcessingException {
RestTemplate restTemplate = new RestTemplate();
URI uri = new URI("http://localhost:51001/orders/v1/getOrder/"+month+"?parmRequestSource="+parmRequestSource+"&parmAudienceType="+parmAudienceType);
return restTemplate.postForObject(uri, orderRequestForm, OrderResponse.class);
}
Both are giving same error :
HttpClientErrorException$BadRequest: 400 : [no body]
Please suggest.
To improve the visibility of the solution, #astar fixed the issue by annotating the model object's properties with #JsonProperty.

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 :)

How to send body content as raw JSON and not form-data in Spring Boot RestTemplate

I have a spring boot application and trying to invoke a rest service of another company by using RestTemplate.
The remote Rest Service required multiple header and body content as Raw JSON.
Here is the sample required body request :
{
"amount": "10000",
"destinationNumber": "365412"
}
But my request body generate like this :
{
amount= [10000],
destinationNumber= [365412]
}
I've done like this :
String BASE_URI = "http://server.com/sericeX";
RestTemplate template = new RestTemplate();
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Authorization","Some token");
headers.add("Content-Type", "application/json");
MultiValueMap<String, String> bodyParam = new LinkedMultiValueMap<>();
bodyParam.add("amount", request.getAmount());
bodyParam.add("destinationNumber",request.getDestinationNumber());
HttpEntity entity = new HttpEntity(bodyParam,headers);
ResponseEntity<TransferEntity> responseEntity = template.exchange(BASE_URI, HttpMethod.POST, entity,TransferEntity.class);
TransferEntity transferEntity = responseEntity.getBody();
Could you please tell me how can i generate body request as JSON ?
Thanks to #Alex Salauyou based on his comment using HashMap instead of MultiValueMap solved the problem. Here is the changes need to be done:
HashMap<String, String> bodyParam = new HashMap<>();
bodyParam.put("amount", request.getAmount());
bodyParam.put("destinationNumber",request.getDestinationNumber());

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.

Need help on RestTemplate Post Request with Body Parameters?

I have a rest api url and submitted the same as POST request with body (user name, password, other parameters) via Rest Client (restclient-ui-2.4-jar-with-dependencies) and it got worked fine without any issues.
Ex:
URL: https://test.com/cgi-bin/testing/api
Body: username=testuser&password=pass123&id=13002&name=raju
The same is not working fine when i used Spring RestTemplate postForObject(url, varmap, Employee.class) method.
Can someone help me with a simple example where the request is a URL, with body parameters and the response is XML which is mapped with a class?
Sample Code:
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("username", "test");
map.add("password", "test123");
map.add("id", "1234");
MarshallingHttpMessageConverter mc = new MarshallingHttpMessageConverter();
mc.setMarshaller(new Jaxb2Marshaller());
mc.setUnmarshaller(new Jaxb2Marshaller());
list.add(marshallingHttpMessageConverter);
emediateRestTemplate.setMessageConverters(list);
Employee employee = (Employee) restTemplate.postForObject(url, map, Employee.class);
Thanks in advance,
Kathir
The above converters Ex: "MarshallingHttpMessageConverter" are not required.
MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<String, String>();
parametersMap.add("username", "test");
parametersMap.add("password", "test123");
parametersMap.add("id", "1234");
For Post:
restTemplate.postForObject(url, parametersMap, Employee.class);
url is String - rest api URL
parametersMap - MultiValueMap
Employee - object which needs to be converted from the JSON response
For Get:
restTemplate.getForObject(url, class object, variablesMap);
url is : String - rest api URL
variablesMap - Map
class object - object which needs to be converted from the JSON response

Resources