HTTP POST using JSON in Spring Rest - spring

I would like to make a simple HTTP POST using Spring RestTemplate.
the Wesb service accept JSON in parameter for example: {"name":"mame","email":"email#gmail.com"}
public static void main(String[] args) {
final String uri = "url";
RestTemplate restTemplate = new RestTemplate();
// Add the Jackson message converter
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
// create request body
String input = "{ \"name\": \"name\", \"email\": \"email#gmail.com\" }";
JsonObject request = new JsonObject();
request.addProperty("model", input);
// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Basic " + "xxxxxxxxxxxx");
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);
// send request and parse result
ResponseEntity<String> response = restTemplate
.exchange(uri, HttpMethod.POST, entity, String.class);
System.out.println(response);
}
When I test this code I got this error:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 400 Bad Request
when I call webservice with Curl I have correct result:
curl -X POST -H "Authorization: Basic xxxxxxxxxx" --header "Content-Type: application/json" --header "Accept: application/json" -d "{ \"name\": \"name\", \"email\": \"email#gmail.com\" } " "url"

try to remove model from the code, as i can see in your curl request you didn't use model attribute and everything works. try this:
public static void main(String[] args) {
final String uri = "url";
RestTemplate restTemplate = new RestTemplate();
// Add the Jackson message converter
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
// create request body
String input = "{\"name\":\"name\",\"email\":\"email#gmail.com\"}";
// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Basic " + "xxxxxxxxxxxx");
HttpEntity<String> entity = new HttpEntity<String>(input, headers);
// send request and parse result
ResponseEntity<String> response = restTemplate
.exchange(uri, HttpMethod.POST, entity, String.class);
System.out.println(response);
}

Related

415 Error when authenticating - Spring boot and RestTemplate

I am working on a third-party REST API and I am going to authenticate with their API by making a POST request to the provided end point. I tested this end point using Postman and it works fine, and now I wanted to do it programmatically.
I am using Spring boot 3.0 for development and RestTemplate as the http client. The code I have implemented is below, it gives me a 415 UNSUPPORTED_MEDIA_TYPE error.
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==");
headers.add("Accept", "application/json");
headers.add("Content-Type","application/x-www-form-urlencoded");
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<String, String>();
requestBody.add("grant_type", "client_credentials");
HttpEntity formEntity = new HttpEntity<MultiValueMap<String, String>>(requestBody, headers);
String serverEndPoint = "https://xxxxxxx.xxx/auth/oauth2/xx/token";
ResponseEntity<String> response = restTemplate.exchange(serverEndPoint, HttpMethod.POST,formEntity, String.class);
System.out.println(response.getStatusCode().value());
Build RestTemplate
#Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
// don't throw
}
});
return restTemplate;
}
But same logic I have implemented using Jersey http client as mentioned below, it gives me successful response with 200 response code.
JacksonJsonProvider jacksonJsonProvider = new JacksonJaxbJsonProvider()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Client client = ClientBuilder.newClient(new ClientConfig(jacksonJsonProvider));
Form form = new Form();
form.param("grant_type", "client_credentials");
String serverEndPoint = "https://xxxxxxx.xxx/auth/oauth2/xx/token";
Response response = client.target(serverEndPoint)
.request("application/json")
.header("Authorization", "Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==")
.post(Entity.entity(form, APPLICATION_FORM_URLENCODED));
System.out.println(response.getStatus());
Kindly help me to resolve this since I need to move forward with the RestTemplate client.
cUrl From Postman
curl --location --request POST 'https://xxxxxxxxxxxxx.xxx/auth/oauth2/xx/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==' \
--header 'Cookie: coolie data bla bla' \
--data-urlencode 'grant_type=client_credentials'
If I inspect what the successful calls (curl and the Jersey HttpClient) send to the server vs what RestTemplate.exchange() sends, the only significant difference is that RestTempate.exchange() appends the charset=utf-8 to the Content-Type header.
I suspect that the sever you are calling is too strict on Content-Type and throws a 415 if it does not match "application/x-www-form-urlencoded" exactly.
To prevent this you need to use RestTempate.postForObject() instead. Try changing your RestTemplate call code as follows:
String serverEndPoint = "https://httpbin.org/post";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<String> entity = new HttpEntity<>("grant_type=client_credentials", headers);
String result = restTemplate.postForObject( serverEndPoint, entity, String.class);
The MediaType is org.springframework.http.MediaType.
Note that I call httpbin.org in the code fragment. I find it extremely useful in researching an issue like this.

How to add file as Form data in Http request in spring boot

I'm writing test cases to a controller in spring boot which takes MultipartFile as RequestParam. In the test case method I'm using TestRestTemplate.exchange() to send the request to the controller. I'm not sure how to make the Headers correctly so that I can send the request.
The Postman curl looks like this:
curl --location --request POST 'localhost:9091/response/upload'
--form 'file=#"/home/adityak/Downloads/ClientLog_NEW.txt"'
For file uploading to any service or endpoint
private String testExchange(File file) {
//add file
LinkedMultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("file", new FileSystemResource(file));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity =
new HttpEntity<>(params, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
"/upload-file",
HttpMethod.POST,
requestEntity,
String.class);
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode == HttpStatus.ACCEPTED) {
result = responseEntity.getBody();
}
return result;
}

How can I pass parameter as post to endpoint using RestTemplate in springboot?

I am using RestTemplate in my project to make a post request to an endpoint. Basically I have lambda function written in nestjs. I am injecting lambda service in my java project. If vehicleName if condition passes, I would like to POST that vehicleName to the url. Is there any suggestions on how I can achieve this? I would be testing my application using this command
curl -X POST "https://gdxdispatcher.dev.awstrp.net/dispatcher/service/api/message" -H "accept: */*" -H "Content-Type: application/json" -d "{\"vehicleType\":\"US Mutual Fund,VIP\",\"source\":\"PCS_DATACACHE_TOPIC\"}"
Here is my code
private void callLambdaService(String vehicleTypesParamValue)
{
final String url = "http://localhost:3000/dispatcher/service/api/message";
final String zMETHOD = "callLambdaService - ";
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange("url", HttpMethod.POST, vehicleName, String.class);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String result = restTemplate.getForObject(url, String.class);
VehicleType vehicleName=null;
String[] vehicleTypes = vehicleTypesParamValue.split(",");
Set<VehicleType> results = new HashSet<>();
try
{
for (String vehicleTypeParam : vehicleTypes)
{
vehicleName =
vehicleTypeFactory.getVehicleTypeByIspName(
vehicleTypeParam);
if (vehicleName == null)
{
LOGGER.warn("No codes for products or vehicle types were supplied");
}
else if (vehicleName.equals("US Mutual Fund"))
{
LOGGER.info(zMETHOD + "Vehicles provided: "
+ vehicleName.getIspName());
}
else
{
LOGGER.warn(
String.format("Unknown vehicle type provided: [%s]",
vehicleName.getIspName()));
}
}
}catch (Exception e) {
LOG.error("Unable to get vehicletype data", e);
}
}
Well, following the instructions:
Create headers which will be a data structure representing HTTP request.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Build a JSONObject from org.json package that is a modifiable set of name/value mappings and put names and values.
JSONObject requestBody = new JSONObject();
requestBody.put("vehicleType", "US Mutual Fund,VIP");
requestBody.put("source", "PCS_DATACACHE_TOPIC");
Create our HttpEntity that represents an HTTP request or response, in this case request consisting of headers and body.
HttpEntity<String> request = new HttpEntity<>(requestBody.toString(), headers);
Create a new resource by posting an object to the given URI template.
It returns the result as automatically converted to the type specified in the responseType parameter.
Then we define a ObjectNode as our resource and response type as our result.
ObjectNode result = restTemplate.postForObject("https://gdxdispatcher.dev.awstrp.net/dispatcher/service/api/message",
request, ObjectNode.class);

RestTemplate authentication while setting userName and password

I have a curl command but I want to pass this information with userName and password while calling the rest API, every thing I have tried doesn't work.
curl -u E-BOARD:HVRid992Xl740NnWOkjk -X GET --header 'Accept: application/json' 'https://XXXXXX.fr/AAAAAA/BBBBB/v1/details?abc=hsdfh&zyx=asdfsdf
My rest API looks something like this
String url = new StringBuilder(urlConfigService.getProfiles().getBaseUrl()).append(relativeUrl).toString();
**String hiddenAccess = "ASHGHGHJ:HVRid992Xl740NnWOkjk";**
// #formatter:off
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("refEboard", refEboard)
.queryParam("idLangue", "FR");
// #formatter:on
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
requestHeaders.add("Authorization", hiddenAccess);
HttpEntity<?> httpEntity = new HttpEntity<String>(requestHeaders);
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
String result =
restTemplate.exchange(builder.build().toUri(), HttpMethod.GET, httpEntity, String.class).getBody();
return (T) new Gson().fromJson(result, type.getClass());
It seems to me that you are trying to send basic authentication credentials. To do this you have to encode username and password in Base64 and set request header like this:
Basic (username:password Base64 Encoded)
This is how you do it:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders header = new HttpHeaders();
String auth = username + ":" + password;
byte [] authentication = auth.getBytes();
byte[] base64Authentication = Base64Utils.encode(authentication);
String baseCredential = new String(base64Authentication);
header.add(HttpHeaders.AUTHORIZATION, "Basic " + baseCredential);
header.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN));
HttpEntity<String> request = new HttpEntity<String>(header);
restTemplate.exchange(builder.build().toUri(), HttpMethod.GET, request, String.class);

curl ok, RestTemplate fails

This works:
curl --verbose -H "Content-Type: application/json" --data "{\"parm1\":\"1\", \"parm2\":\"1\"}" http://server:8080/service/meth
and returns:
{"success":true,"errorMessage":null}
This fails:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("parm1", "1");
map.add("parm2", "1");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
String response = (String) restTemplate.postForObject("http://server:8080/service/meth",
request,
String.class);
with 500 Internal Server Error
I'm using springframework-boot 1.3.3.RELEASE and java 1.8 and am at a loss as to what's wrong. The server side log shows no errors other than 500
Has anyone been faced with a Spring RestTemplate call that mysteriously failed? How did you approach diagnosing the problem?

Resources