Getting 400 Bad Request for Rest Template Spring Boot - java

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

Related

Spring RestTemplate Post to Salesforce Bad request 400

Still cracking my brain after having made several calls to retrieve Token and Product, posting a Product was almost impossible with restTemplate even though it succeeded using Postman REST client.
public AddProductResponse createProduct(#NonNull AuthenticationTokenResponse authenticationTokenResponse)
{
String url = authenticationTokenResponse.getInstance_url() + "/services/data/v39.0/sobjects/Product2";
HttpHeaders headers = new HttpHeaders();
//headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.set("Authorization", "Bearer " + authenticationTokenResponse.getAccess_token());
headers.setContentType(MediaType.APPLICATION_JSON);
//headers.add("Authorization", "Bearer " + authenticationTokenResponse.getAccess_token());
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("Name", "Product Name");
requestBody.add("product_Reference__c", "SOMERef");
HttpEntity<?> requestEntity = new HttpEntity<>(requestBody, headers);
RestTemplate restTemplate = new RestTemplate();
try
{
ResponseEntity<AddProductResponse> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, AddProductResponse.class);
return response.getBody();
}
catch (Exception e)
{
LOG.debug("Error creating product");
e.printStackTrace();
}
return null;
}
I wonder why my postman call succeeded but not with Spring RestTemplate.
POstman screenshot.
postman body.
{"Name" : "My New Prod ",
"product_Reference__c": "REFAKINTEST3"}

How to pass Headers and request body in POST request?

I am using RestTemplate restTemplate.exchangemethod to POST request to an endpoint. I have OAuth Header and HttpEntity in different file which I want to pass to POST request, in addition to this I also want to pass request to the endpoint.
I was able to successfully pass the headers and request, but not Http entity which contains credentials
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
new HttpEntity<>(request, dataRepo.getHeader()), String.class);
Is there any way I can pass all 3 things
HttpEntity
HttpHeaders
request
Here is my code
#RunWith(MockitoJUnitRunner.class)
#TestPropertySource
public class DataTest {
#Inject
private Oauth oauth;
#Mock
private DataRepo dataRepo;
RestTemplate restTemplate = new RestTemplate();
#Qualifier(OAuth2HttpHeadersBuilder.BEAN_NAME)
NewHttpHeader headersBuilder;
#Test
public void testAddEmployeeSuccess() throws URISyntaxException {
URI uri = new URI(url);
Set<String> mockData = Stream.of("A","B").collect(Collectors.toSet());
String onsString = String.join(",", mockData);
Map<String, String> requestBody = new HashMap<>();
requestBody.put("name", onsString);
JSONObject jsonObject = new JSONObject(requestBody);
HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
new HttpEntity<>(request, dataRepo.getHeader()), String.class);
Assert.assertEquals(201, result.getStatusCodeValue());
}
The below code is in NewHttpHeader.java file which contains
Header and HttpEntity
private HttpEntity<MultiValueMap<String,String>> getHttpEntity() {
MultiValueMap<String, String> store = new LinkedMultiValueMap<>();
store.add( "pas", "password" );
store.add( "name", config.getVaultServiceAccountName() );
return new HttpEntity<>( store, getHeader() );
}
private HttpHeaders getHeader() {
HttpHeaders httpHeaders = headersBuilder.build();
httpHeaders.add( HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType() );
httpHeaders.add( HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.getMimeType() );
return httpHeaders;
}
}
Quoting question:
Is there any way I can pass all 3 things
HttpEntity
HttpHeaders
request
Quoting javadoc of HttpEntity:
Represents an HTTP request or response entity, consisting of headers and body.
So the answer to your question is: Yes, you can pass all 3, since the first is nothing but a combination of the other two.
Just merge your two HttpEntity objects.
Before
HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
new HttpEntity<>(request, dataRepo.getHeader()), String.class);
After
HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), dataRepo.getHeader());
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
request, String.class);

RestTemplate GET method with path variables

I am trying to make rest call using rest template. I have two header parameters and one path variable to set for the API call. Below is my implementation. But I am receiving HttpServerErrorException: 500 null. Am I setting the path variable in the right way?
Target API: drs/v1/{caseId}
String url = configProperties.getCaseCreateUrl();
if(!StringUtils.isEmpty(url)){
url = url.replace(ApplicationConstants.DOMAIN_NAME,currentUser.domainUrl());
url = url+ caseId;
}
HttpHeaders headers = new HttpHeaders();
headers.set(ApplicationConstants.PS_TOKEN_HEADER, currentUser.getToken());
headers.set(ApplicationConstants.WORGROUP_HEADER, currentUser.getWorkgroupId());
headers.set(ApplicationConstants.DOMAIN_HEADER, currentUser.getDomainId());
headers.set(HttpHeaders.CONTENT_TYPE, MediaType.ALL_VALUE);
HttpsTrustManager.allowAllSSL();
RestTemplate restTemplate = new RestTemplate();
HttpEntity<Map<String, String>> requestEntity = new HttpEntity(null, headers);
ResponseEntity<CaseDetailsDTO> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, CaseDetailsDTO.class);
I am providing a code snippet of RestTemplate GET method with path variables example
public ResponseEntity<List<String>> getNames(long id) {
final String url = "https://some/{id}/name";
//with cookies
ResponseEntity<String> cookie = getCookies();
String set_cookie = cookie.getHeaders().getFirst(HttpHeaders.SET_COOKIE);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Cookie", set_cookie);
HttpEntity request = new HttpEntity(headers);
ResponseEntity<List<String>> response = restTemplate.exchange(url, HttpMethod.GET, request,new ParameterizedTypeReference<List<String>>(){},id);
return response;
}

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());

Spring RestTemplate POST Request with URL encoded data

I'm new to Spring and trying to do a rest request with RestTemplate. The Java code should do the same as below curl command:
curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: xyz" "https://someserver.com/api/v3/projects/1/labels"
But the server rejects the RestTemplate with a 400 Bad Request
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("PRIVATE-TOKEN", "xyz");
HttpEntity<String> entity = new HttpEntity<String>("name=feature&color=#5843AD", headers);
ResponseEntity<LabelCreationResponse> response = restTemplate.exchange("https://someserver.com/api/v3/projects/1/labels", HttpMethod.POST, entity, LabelCreationResponse.class);
Can somebody tell me what I'm doing wrong?
I think the problem is that when you try to send data to server didn't set the content type header which should be one of the two: "application/json" or "application/x-www-form-urlencoded" . In your case is: "application/x-www-form-urlencoded" based on your sample params (name and color). This header means "what type of data my client sends to server".
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("PRIVATE-TOKEN", "xyz");
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("name","feature");
map.add("color","#5843AD");
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);
ResponseEntity<LabelCreationResponse> response =
restTemplate.exchange("https://foo/api/v3/projects/1/labels",
HttpMethod.POST,
entity,
LabelCreationResponse.class);
You need to set the Content-Type to application/json. Content-Type has to be set in the request. Below is the modified code to set the Content-Type
final String uri = "https://someserver.com/api/v3/projects/1/labels";
String input = "US";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("PRIVATE-TOKEN", "xyz");
HttpEntity<String> request = new HttpEntity<String>(input, headers);
ResponseEntity<LabelCreationResponse> response = restTemplate.postForObject(uri, request, LabelCreationResponse.class);
Here, HttpEntity is constructed with your input i.e "US" and with headers.
Let me know if this works, if not then please share the exception.
Cheers!
It may be a Header issue check if the header is a Valid header, are u referring to "BasicAuth" header?
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString());
headers.add("Accept", MediaType.APPLICATION_JSON.toString()); //Optional in case server sends back JSON data
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<String, String>();
requestBody.add("name", "feature");
requestBody.add("color", "#5843AD");
HttpEntity formEntity = new HttpEntity<MultiValueMap<String, String>>(requestBody, headers);
ResponseEntity<LabelCreationResponse> response =
restTemplate.exchange("https://example.com/api/request", HttpMethod.POST, formEntity, LabelCreationResponse.class);
my issue, the MessageConverters contains other converters may converts then entity to json (like FastJsonHttpMessageConverter). So i added the FormHttpMessageConverter to ahead and it works well.
<T> JuheResult<T> postForm(final String url, final MultiValueMap<String, Object> body) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
return exchange(url, HttpMethod.POST, requestEntity);
}
<T> JuheResult<T> exchange(final String url, final HttpMethod method, final HttpEntity<?> requestEntity) {
ResponseEntity<JuheResult<T>> response = restTemplate.exchange(url, method, requestEntity,
new JuheResultTypeReference<>());
logger.debug("调用结果 {}", response.getBody());
return response.getBody();
}
public JuheSupplierServiceImpl(RestTemplateBuilder restTemplateBuilder) {
Duration connectTimeout = Duration.ofSeconds(5);
Duration readTimeout = Duration.ofSeconds(5);
restTemplate = restTemplateBuilder.setConnectTimeout(connectTimeout).setReadTimeout(readTimeout)
.additionalInterceptors(interceptor()).build();
restTemplate.getMessageConverters().add(0, new FormHttpMessageConverter());
}
fastjson prevent resttemplate converting other mediaTypes other than json

Categories

Resources