Pass an Object and a String via RestTemplate - java

My rest endpoint:
#PostMapping("/customerPolicyInfo")
public Map<String, Object> getCustomerPolicyInfo(#RequestParam String policyNumber, #RequestParam Claims authenticatedUserDetails) {
}
How to call this endpoint from another service using RestTemplate? It is a HTTP POST request?
My current code where I am calling this above endpoint looks like this:
Claims authenticatedUserDetails = (Claims) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
// create a map for post parameters
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("policyNumber", policyNumber);
map.add("authenticatedUserDetails", authenticatedUserDetails.toString());
// build the request
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(map, headers);
// send POST request
ResponseEntity<Map> response = null;
try {
response = restTemplate.postForEntity("http://localhost:8081/policy-service/customerPolicyInfo", entity, Map.class);
} catch (RestClientException e) {
e.printStackTrace();
}
return response.getBody();

Related

Getting 400 Bad Request for Rest Template Spring Boot

I have a rest Controller where i am trying to get the Token from a service using the RestTemplate in Spring Boot. The application works fine when i use Postman but from Java Application i get 400 Bad Request.
My Java Sample :
#PostMapping("/service")
private String generateAuthenticationToken() {
HttpHeaders authenticationTokenHeaders = new HttpHeaders();
authenticationTokenHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
JSONObject sfmcBUCredential = new JSONObject();
JSONObject sfmcTokenResponseObject;
sfmcBUCredential.put("grant_type", sfmcConfig.getGrant_type());
sfmcBUCredential.put("client_id", sfmcConfig.getClient_id());
sfmcBUCredential.put("client_secret", sfmcConfig.getClient_secret());
String sfmcBUCredentialString = sfmcBUCredential.toString();
System.out.println("Values before sending to POST Request are :::" + sfmcBUCredentialString);
HttpEntity<String> getTokenEntity = new HttpEntity<>(sfmcBUCredentialString, authenticationTokenHeaders);
System.out.println("Values after sending to POST Request are :::" + getTokenEntity.toString());
System.out.println("URL is :::" + GET_SFMC_ENDPOINT_URL);
//String tokenResponse = restTemplate.postForObject(GET_SFMC_ENDPOINT_URL, getTokenEntity, String.class);
ResponseEntity<String> tokenResponse = restTemplate.exchange(GET_SFMC_ENDPOINT_URL, HttpMethod.POST, getTokenEntity, String.class);
sfmcTokenResponseObject = new JSONObject(tokenResponse.getBody());
System.out.println("tokenResponse::::::::" + sfmcTokenResponseObject.getString("access_token").toString());
return sfmcTokenResponseObject.getString("access_token");
}
Logs :
Values before sending to POST Request are :::{"grant_type":"client_credentials","client_secret":"c1ae4b4a-498e-46a0-a02e-cd2378cb8db6","client_id":"Y43iLAhr4e0SoJ9KkV4vLKnGhNmS1Y3c"}
Values after sending to POST Request are :::<{"grant_type":"client_credentials","client_secret":"c1ae4b4a-498e-46a0-a02e-cd2378cb8db6","client_id":"Y43iLAhr4e0SoJ9KkV4vLKnGhNmS1Y3c"},[Content-Type:"application/x-www-form-urlencoded"]>
URL is :::https://keycloak.lab.hci.aetna.com/auth/realms/master/protocol/openid-connect/token
Try something like this:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", sfmcConfig.getGrant_type());
map.add("client_id", sfmcConfig.getClient_id());
map.add("client_secret", sfmcConfig.getClient_secret());
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);
ResponseEntity<LabelCreationResponse> response =
restTemplate.exchange("url",
HttpMethod.POST,
entity,
String.class);

RestTemplateBuilder: problem sending audio to telegram api

I use RestTemaplteBuilder for send POST request to Telegram Bot API.
There was a problem creating the request to upload the audio file.
According to the documentation - https://core.telegram.org/bots/api#sending-files you need to send a request of type multipart/form-data.
Error: 413 Request Entity Too Large
MultiValueMap<String, Object> request= new LinkedMultiValueMap<String, Object>();
try {
parts.set("chat_id", "id");
parts.set("audio", (Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("name.mp3").toURI()))));
} catch (Exception e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(request, headers);
ResponseEntity<String> responseEntity = restTemplateBuilder.build().postForEntity(requestFormatter(URL_BOT_PREFIX, method), requestEntity, String.class);

Spring Rest Template creating multipart form/data client working like a postman throws non convertable exception

I want to turn this postman client with multipart/form-data header request to a spring template client.
Right now, I have a basic rest controller which works well.
#RestController
#RequestMapping("/api")
public class MainConroller {
private static final Logger log = LoggerFactory.getLogger(MainConroller.class);
#Autowired
private MainService mainService;
public MainConroller(MainService mainService) {
this.mainService = mainService;
}
#PostMapping("/mails/send")
public void send(
#RequestParam("usertoken") String usertoken,
#RequestParam("sendTo") String sendTo,
#RequestParam("subject") String subject,
#RequestParam("content") String content,
#RequestParam(required = false, name = "files") List<MultipartFile> multipartFiles) {
log.debug("{}, {}, {}, {}", usertoken, sendTo, subject, content);
mainService.processMessage(usertoken, sendTo, subject, content, multipartFiles);
}
}
I need to, however, create a rest client so I used a rest template, it right now looks like this:
ArrayList<HttpMessageConverter<?>> converters = new ArrayList<>(
Arrays.asList(new MappingJackson2HttpMessageConverter(), new ResourceHttpMessageConverter(), new FormHttpMessageConverter()));
#Bean
public RestTemplate restTemplate() {
return new RestTemplate(converters);
}
File file = new File("*********");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> fileValueMap = new LinkedMultiValueMap<>();
fileValueMap.add(file.getName(), file);
fileValueMap.add(file.getName(), file);
fileValueMap.add(file.getName(), file);
HttpEntity<MultiValueMap<String, Object>> filesPart = new HttpEntity<>(fileValueMap, httpHeaders);
// String key values part
MultiValueMap<String, String> stringPart = new LinkedMultiValueMap<>();
stringPart.add("usertoken", "test");
stringPart.add("sendTo", "test");
stringPart.add("subject", "test");
stringPart.add("content", "test");
HttpEntity<MultiValueMap<String, String>> objectPart = new HttpEntity<>(stringPart, httpHeaders);
MultiValueMap<String, Object> multiPartRequest = new LinkedMultiValueMap<>();
multiPartRequest.add("ObjectPart", objectPart);
multiPartRequest.add("FilesPart", filesPart);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(multiPartRequest, httpHeaders);
String serverUrl = "****";
restTemplate().postForEntity(serverUrl, requestEntity, String.class);
The problem is when I try to send the post request, It throws
Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [multipart/form-data]
Update
The solution on the client side is very simple, you can just send String values in the object values, which are going to be automatically casted to Strings via generics.
Also, the files cannot be send just as files but you have to create FileSystemResource instead, here is the complete code of the client side:
#Service
public class RestTemplatePost {
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public void prepareMessage() throws Exception {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
form.add("usertoken", "test");
form.add("sendTo", "test");
form.add("subject", "test");
form.add("content", "test");
form.add("files", getTestFile());
form.add("files", getTestFile());
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, httpHeaders);
String serverUrl = "******";
restTemplate().postForEntity(serverUrl, requestEntity, String.class);
}
public static Resource getTestFile() throws IOException {
Path testFile = Paths.get("C****");
System.out.println("Creating and Uploading Test File: " + testFile);
Files.write(testFile, "Hello World !!, This is a test file.".getBytes());
return new FileSystemResource(testFile.toFile());
}
}
You are making things too complex. You should use a single map to hold the form values not a map of maps. Next to that Spring Boot already provides a RestTemplate so you don't need to configure your own again.
File file = new File("*********");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
form.add("files", file);
form.add("files", file);
form.add("files", file);
form.add("usertoken", "test");
form.add("sendTo", "test");
form.add("subject", "test");
form.add("content", "test");
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, httpHeaders);
String serverUrl = "****";
restTemplate().postForEntity(serverUrl, requestEntity, String.class);
The RestTemplate (or actually the FormHttpMessageConverter) will transform it into a correct request.
The default RestTemplate constructor does not include any message converters, you need to add it. For example, you can do it like:
HttpEntity<MultiValueMap<String, Object>> requestEntity = new
HttpEntity<MultiValueMap<String, Object>>(parts, requestHeaders);
RestTemplate restTemplate = getRestTemplate();
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
return restTemplate.postForObject(apiURI, requestEntity, String.class);

RestTemplate POST Request with Request Parameters

I am using Spring's RestTemplate to send a POST request to my RestController with request parameters and a request header.
It fails with this error message: POST request for "[myurl]" resulted in 404 (null); invoking error handler.
Note that "[myurl]" is "http://localhost:8080/test"
This is my code:
RestTemplate rest = new RestTemplate();
MultiValueMap<String, Integer> map = new LinkedMultiValueMap<String, Integer>();
map.add("num1", 1);//request parameters
map.add("num2", 2);
HttpHeaders headers = new HttpHeaders();//request header
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<MultiValueMap<String, Integer>> request = new HttpEntity<MultiValueMap<String, Integer>>(map, headers);
Object obj = rest.postForObject("[myurl]", request, Object.class);
logger.log("Returned object: " + obj.toString());
Maybe try doing something like (if you can get away with MultiValueMap):
RestTemplate rest = new RestTemplate();
Map<String, Integer> map = new HashMap<>();
map.put("num1", 1);//request parameters
map.put("num2", 2);
Object obj = rest.postForObject("[myurl]", map, Object.class);
logger.log("Returned object: " + obj.toString());

How to get Response Header information from Spring RestTemplate GET request

I am triggering a GET request and getting the JSON data successfully via Spring RestTemplate. I also want to get the Response Header information but I am not sure how to get it.
private String getAPIKeySpring() {
RestTemplate restTemplate = new RestTemplate();
String url = baseURL+"/users/apikey";
Map<String, String> vars = new HashMap<String, String>();
vars.put("X-Auth-User", apiUser);
JsonVO jsonVO = restTemplate.getForObject(url, JsonVO.class, vars);
System.out.println(jsonVO);
return null;
}
ResponseEntity<JsonVO> responseEntity = restTemplate.getForEntity(url, JsonVO.class, vars);
JsonVO jsonVO = responseEntity.getBody();
HttpHeaders headers = responseEntity.getHeaders(); //<-- your headers

Categories

Resources