POST x-www-form-urlencoded - java

I've been reading the following and trying to send a POST request with Spring Boot, using RestTemplate.
HttpHeaders headers = new HttpHeaders();
headers.add("content-type", "application/x-www-form-urlencoded");
final String body = "clipmessage={ bridgeId: \"" + user.getBridgeId() + "\", clipCommand: { url: \"" + setLightState("3") + "\", method: \"PUT\", body: { \"on\": " + state.isOn() + " } } }";
final String url = API_ADDRESS + user.getAccessToken();
HttpEntity<String> entity = new HttpEntity<>(body, headers);
restTemplate.postForEntity(url, entity, String.class);
If I log the URL and the body and send the exact same in Postman, it succeeds. However, not when I send it from my Spring Boot application.
I'm guessing that special body has to be sent in some special way which that I am not aware off?
Anyone has any tips on what to try here next?
UPDATE 1:
I tried the MultiValueMap as suggested, but did not get that to work either.
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
final String body = "{ bridgeId: \"" + user.getBridgeId() + "\", clipCommand: { url: \"" + setLightState("3") + "\", method: \"PUT\", body: { \"on\": " + state.isOn() + " } } }";
map.add("clipmessage", body);
HttpEntity<String> entity = new HttpEntity<>(body, headers);

I have the same scenario. solved after using the following code :
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
FormHttpMessageConverter formMessageConverter = new FormHttpMessageConverter();
messageConverters.add(formMessageConverter);
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
Parameters and headerpart
...
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("signature", "signature");
//other parameters
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(parameters, headers);
ResponseEntity<ResponseMessage> responseEntity = restTemplate.postForEntity(url, requestEntity, ResponseMessage.class);
ResponseMessage respMsg =responseEntity.getBody();
logMsg.append(",HTTP STATUS=").append(responseEntity.getStatusCode()).append(", RES:").append(marshal(respMsg));

Related

Trying to create a Keycloak user with spring rest client

Here's the error message:
400 Bad Request: [Unrecognized field "rep" (class org.keycloak.representations.idm.UserRepresentation), not marked as ignorable]
Here's some code:
public String createUser2() throws UnsupportedEncodingException, JSONException {
String adminToken = getAccessToken();
System.out.println("token: " + adminToken);
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("Authorization", "Bearer " + adminToken);
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setFirstName("some");
userRepresentation.setLastName("user");
userRepresentation.setUsername("Some.User#somewhere.com");
userRepresentation.setEmail("Some.User#somewhere.com");
// Gson gson = new Gson();
// String jsonString = gson.toJson(userRepresentation);
MultiValueMap<String, UserRepresentation> map = new LinkedMultiValueMap<String, UserRepresentation>();
map.add("rep", userRepresentation);
HttpEntity<MultiValueMap<String, UserRepresentation>> request = new HttpEntity<>(map, headers);
String uri = "http://10.127.2.46:31680/auth/admin/realms/12xDemo/users";
System.out.println("URI: " + uri);
UserRepresentation response = (new RestTemplate()).postForObject(uri, request, UserRepresentation.class);
//JSONObject obj = new JSONObject(response);
return (new Gson()).toJson(response);
}
Looks like you should send HttpEntity<UserRepresentation>as a request. Cause your server code waits for this type and receives "rep": "UserRepresentation", tries to map it on actual UserRepresentation.class

Why can't I send or POST a file with RestTemplate to the server?

File fileJson = new File("answer.json");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
**body.add("answer", fileJson);**
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String urlFinal = "url";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(urlFinal, requestEntity, String.class);
System.out.println(response);
The server returns me a 400 error saying that the file was not sent in the body. I was wondering if the problem is with my code or with the server.
The file is a JSON, which must be sent in Multipart-Form-data.
I left the urlFinal string with just "url" to put as an example, but there is a valid url, as I've already done tests.
You need add filename and BAOS to MultiValueMap body, add this:
File fileJson = new File("answer.json");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("filename", fileJson.getName());
body.add("file", new ByteArrayResource(Files.readAllBytes(fileJson.toPath()));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String urlFinal = "url";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(urlFinal, requestEntity, String.class);
System.out.println(response);
But is not the best mode, because you can change your code for use this method:
#Service
public class FileUploadService {
private RestTemplate restTemplate;
#Autowired
public FileUploadService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
public void postFile(String filename, byte[] someByteArray) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
// This nested HttpEntiy is important to create the correct
// Content-Disposition entry with metadata "name" and "filename"
MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
ContentDisposition contentDisposition = ContentDisposition
.builder("form-data")
.name("file")
.filename(filename)
.build();
fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
HttpEntity<byte[]> fileEntity = new HttpEntity<>(someByteArray, fileMap);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", fileEntity);
HttpEntity<MultiValueMap<String, Object>> requestEntity =
new HttpEntity<>(body, headers);
try {
ResponseEntity<String> response = restTemplate.exchange(
"/urlToPostTo",
HttpMethod.POST,
requestEntity,
String.class);
} catch (HttpClientErrorException e) {
e.printStackTrace();
}
}
}

Token missing in the request

Here I'm trying to send the generated token from header to an API along with the data, but I'm getting an error:
Token missing in the request
Not sure what's wrong with my code, can someone please guide me resolve this, thanks in advance.
String url = "API_TO_GENERATE_TOKEN";
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Content-Type", "application/json");
httpHeaders.set("CLIENT_ID", "VALUE_OF_CLIENTID");
httpHeaders.set("CLIENT_SECRET", "VALUE_OF_CLIENT_SECRET");
JSONObject json = new JSONObject();
HttpEntity <String> httpEntity = new HttpEntity <String> (json.toString(), httpHeaders);
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.postForObject(url, httpEntity, String.class);
JSONObject jsonObj = new JSONObject(response);
System.out.println("Json Obj is:"+jsonObj);
/*String balance = jsonObj.get("data").toString();
System.out.println("Response is:"+response);*/
JSONObject jsonObj1 = jsonObj.getJSONObject("data");
String token = jsonObj1.getString("token");
System.out.println("Token is " + token);
String url1=API_TO_ADD_USER";
HttpHeaders httpHeaders1=new HttpHeaders();
httpHeaders1.set("CLIENT_ID", "VALUE_OF_CLIENT_ID");
httpHeaders1.set("CLIENT_SECRET", "VALUE_OF_CLIENT_SECRET");
httpHeaders1.set("Content-Type","application/json");
httpHeaders1.set("Authorization","Bearer"+token);
// JSONObject json1 = new JSONObject();
Filter u= new Filter();
u.setName("my_name");
u.setPhone("123456789");
u.setVendorId("P1234");
u.setAddress1("my_address1");
u.setAddress2("my_address2");
u.setCity("my_city");
u.setState("my_state");
u.setEmail("myemail#abc.com");
HttpEntity<Filter> httpEntity1 = new HttpEntity<>(u, httpHeaders1);
RestTemplate restTemplate1 = new RestTemplate();
//String response1 = restTemplate1.postForObject(url1, httpEntity1, String.class);
ResponseEntity<String> response1 = restTemplate.postForEntity(url1, httpEntity1, String.class);
// JSONObject jsonObj2 = new JSONObject(response1);
System.out.println("Json Obj111 is:"+response1);
I have faced a similar issue while using RestClient by not separating "Bearer" & Token with space, so I would go httpHeaders1.set("Authorization","Bearer "+token) and you should be fine.

Authorization for Google Drive Push Notifications for Java

I am trying to get push notifications from a resource on Google Drive to my server. I have been looking at this example:
https://developers.google.com/drive/v3/web/push
And I have tried translating that to Java into something like this:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("id", "36d00d08-000d-4723-91bc-a1a6ec302e59");
map.add("type", "web_hook");
map.add("address", "https://mydomain.appspot.com/rest/drive");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
I have previously been using Googles libs for Drive to access files. In those cases I didn't need to create the request in such a "manual" way. I have used the class GoogleAuthorizationCodeFlow with a token to authorize my requests. I'm not sure how I should do that with RestTemplate. I am guessing that I need to do something like:
headers.set("Authorization", X);
What should X be here? Is that even the right way to approach authorization?
Edit:
Here is my attempt by reading a secret. The result is HTTP 401:
#Override
public String startListening() throws IOException {
final String fileId = "omitted";
String uri = "https://www.googleapis.com/drive/v3/files/" + fileId + "/watch";
HttpHeaders headers = getHeaders(getSecret());
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(getProperties(), headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
return response.getStatusCode() + " " + response.getBody() + " " + response.getHeaders();
}
private static HttpHeaders getHeaders(String theString) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + theString);
return headers;
}
private static MultiValueMap<String, String> getProperties() {
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("id", "some uid");
map.add("type", "web_hook");
map.add("address", "https://mydomain.appspot.com/rest/drive");
return map;
}
private static String getSecret() throws IOException {
InputStream in =
ConcreteDriveListenerFactory.class.getResourceAsStream("/drive_secret.json");
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer, "UTF-8");
return writer.toString();
}
As #DalmTo has mentioned, X is for token. With regard to sample POST request for Drive API try this code snippet from this SO thread. It also uses a POST method.
public static void main(String argv[]) throws Exception {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.googleapis.com/drive/v2/files");
post.addHeader("Content-Type", "application/json");
post.addHeader("Authorization",
"Bearer XXXXXXXXXXXXXXXXXXXXXXXXX");
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("title", "Test folder");
jsonObject
.addProperty("mimeType", "application/vnd.google-apps.folder");
post.setEntity(new StringEntity(jsonObject.toString()));
httpClient.execute(post);
}

Restful Spring postForObject missing all property values

I try to simulate restful server:
private void btnPostActionPerformed(java.awt.event.ActionEvent evt) {
RestTemplate restTemplate = new RestTemplate();
Issuer issuer = new Issuer();
issuer.setCountry("Teacher 1");
issuer.setIssuerName("Department 1");
String url = txtHost.getText()+txtGet.getText();
restTemplate.postForObject(url, issuer, Issuer.class) ;
}
Controller code:
#RequestMapping(value = "/issuer/addIssuer", method = RequestMethod.POST)
#ResponseBody
public Issuer addIssuer(#ModelAttribute("issuer") Issuer issuer) {
if (issuer != null) {
logger.info("Inside addIssuer, adding: " + issuer.toString());
} else {
logger.info("Inside addIssuer...");
}
issuers.put(issuer.getTicker(), issuer);
return issuer;
}
I have fill some attributes, but when I debug the server, all values is null.
INFO : com.avaldes.tutorial.RestController - Inside addIssuer, adding: [null, null, null, null]
IssuerName and country is null too..
What is wrong with my code?
You are using #ModelAttribute in your controller. In that case you'll need to send your data as application/x-www-form-urlencoded:
MultiValueMap<String, Object> variables = new LinkedMultiValueMap<>();
variables.add("country", "Teacher 1");
variables.add("issuerName", "Department 1");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(variables, requestHeaders);
String url = txtHost.getText()+txtGet.getText();
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Issuer.class);

Categories

Resources