Im trying to send restTemplate with long and image data. Im following this tutorial code and getting next error:
W/RestTemplate: POST request for "http://192.168.0.250:8081/server/upload" resulted in 400 (Bad Request); invoking error handler
E/ContentValues: 400 Bad Request org.springframework.web.client.HttpClientErrorException: 400 Bad Request
I have made simply restteamplate for Long data, but here I have some trubles.
Here are my Android client:
protected AnotherPostDTO doInBackground(Void... params) {
Resource resource = new ClassPathResource("res/drawable/bbb.png");
formData = new LinkedMultiValueMap<String, Object>();
formData.add("owners_id", "1");
formData.add("file", resource);
try {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(formData, requestHeaders);
ArrayList<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>(Arrays.asList(new MappingJackson2HttpMessageConverter(), new FormHttpMessageConverter()));
RestTemplate restTemplate = new RestTemplate(converters);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
return restTemplate.postForObject(Constants.URLs.UPLOAD_FILE, requestEntity, AnotherPostDTO.class);
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
return post;}
My server controller:
#RequestMapping(value = "postformdata", method = RequestMethod.POST, headers = "Content-Type=multipart/form-data")
public #ResponseBody String handleFormUpload(#RequestParam("description") String description,
#RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
byte[] bytes = null;
try {
bytes = file.getBytes();
} catch (IOException e) {
System.out.println("taski");
}
return "file upload received! Name:[" + description + "] Size:["
+ bytes.length + "]";
} else {
return "file upload failed!";
}
}
and bean:
#Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("128KB");
factory.setMaxRequestSize("128KB");
return factory.createMultipartConfig();
}
Any ideas?
Related
In my Spring Boot project I have set several endpoints (which refer to some GET or POST REST API) in the application-dev.yml file.
spring:
username: xxx
password: acb132
route:
source:
protocol: https://
ip: 10.xxx.y.zz/
root: "swdfr/"
paths: >
- "ofh/ert/hAFG5"
- "ofh/ert/ryt54"
I would like to manage these endpoints within a service class with a single method. Currently I have implemented this solution:
//REST CONTROLLER
#GetMapping("/Multiple_Get")
public void manageGetEndpointsWithRestTemplate() throws Exception{
final String methodName = "manageGetEndpointsWithRestTemplate()";
try {
service.manageGetEndpointsWithRestTemplate();
} catch (final Exception e) {
this.errorLog(methodName, e);
throw e;
}
}
//SERVICE
#ResponseBody
public void manageGetEndpointsWithRestTemplate() {
final String methodName = "manageGetEndpointsWithRestTemplate()";
try {
String urlGet1 = protocol + ip + root + paths.get(0);
String urlGet2 = protocol + ip + root + paths.get(1);
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
HttpEntity request = new HttpEntity(headers);
try {
RestTemplate restTemplate;
if (urlGet1.startsWith("https") || urlGet2.startsWith("https")) {
restTemplate = getRestTemplateForSelfSsl();
} else {
restTemplate = new RestTemplate();
}
// GET1
ResponseEntity<String> response1 = restTemplate.exchange(urlGet1, HttpMethod.GET, request,
String.class);
HttpStatus statusCode1 = response1.getStatusCode();
logger.info("STATUS GET1: " + statusCode1);
// GET2
ResponseEntity<String> response2 = restTemplate.exchange(urlGet2, HttpMethod.GET, request,
String.class);
HttpStatus statusCode2 = response2.getStatusCode();
logger.info("STATUS GET2: " + statusCode2);
} catch (HttpStatusCodeException e) {
logger.error(e.getMessage());
}
} catch (Exception e) {
logger.error(e.getMessage());
}
}
public RestTemplate getRestTemplateForSelfSsl()
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] x509Certificates, String s) -> true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}
I would like to use a single method making it as generalizable as possible especially if I have to manage a large number of endpoints.
Do you have any ideas?
Thanks in advance
You can iterate over all the paths and execute the common code, considering you are doing GET request for all.
#ResponseBody
public void manageGetEndpointsWithRestTemplate() {
final String methodName = "manageGetEndpointsWithRestTemplate()";
try {
paths.forEach(path -> {
String urlGet = protocol + ip + root + path;
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
HttpEntity request = new HttpEntity(headers);
try {
RestTemplate restTemplate = urlGet.startsWith("https") ? getRestTemplateForSelfSsl() : new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(urlGet, HttpMethod.GET, request,
String.class);
HttpStatus statusCode = response.getStatusCode();
logger.info("STATUS GET - {} : {}", urlGet, statusCode);
} catch (HttpStatusCodeException e) {
logger.error(e.getMessage());
}
});
} catch (Exception e) {
logger.error(e.getMessage());
}
}
In case you're gonna use POST or any other HTTP methods, mention in application-dev.yml file along with the paths. Add few extra logic to determine the HTTP.XXX before passing into restTemplate.exchange().
I always get the same error while sending username and password to server. I need to send data as content type:form-data, because server isn't responding on any other type. I tested in postman and it's ok, but when I am trying to send it in code, it's not working. Can someone help me, thanks!!
public class Login extends AsyncTask<String, Void, Void> {
String userName;
String password;
public Login(String user, String pass) {
userName = user;
password = pass;
}
protected void onPreExecute() {
super.onPreExecute();
}
protected Void doInBackground(String... params) {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("user",userName)
.addFormDataPart("pass",password)
.build();
Request request = new Request.Builder()
.url("http://www.autotrack.rs/android_juzna_backa/login.php")
.method("POST", body)
.build();
try {
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
try {
Call call = client.newCall(request);
Response response = call.execute();
System.out.println(response.body().string());
}catch (Exception m)
{
Log.d("Mytag", m.getMessage());
}
if(!response.isSuccessful())
{
try {
throw new IOException("Unexpected: "+response);
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean okhttp3.Response.isSuccessful()' on a null object reference
This code works perfectly fine for me:
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("user","pera")
.addFormDataPart("pass","1111")
.build();
Request request = new Request.Builder()
.url("http://www.autotrack.rs/android_juzna_backa/login.php")
.method("POST", body)
.build();
Response response = client.newCall(request).execute();
In your code I see that you execute the same request twice, maybe this is the issue?
Hi this is the web method to receive JSON and response JSON but the problem is this web method doesn't accept the gzip encoded request so how to make it to gzip acceptable web method?
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
#Path("/pdf2doc")
public RPDOC postDocument(DPDF dpdf){
}
DPDF is the class
public class DPDF{
public String docid;
public String pdfdata;
}
This the client code with gzip Content encoding and throw exeption
String body = "{\"docid\": 1234, \"docdata\": \"test\"}";
HttpEntity httpEntity = EntityBuilder.create().setText(body)
.setContentEncoding("gzip")
.gzipCompress().build();
final String postUrl = serviceURL;
HttpUriRequest request = RequestBuilder.post(postUrl)
.setHeader(HttpHeaders.CONTENT_TYPE,
"application/json")
.setHeader(HttpHeaders.ACCEPT,
"application/json")
.setEntity(httpEntity)
.build();
String sResponse = null;
try (CloseableHttpClient httpclient = HttpClientBuilder.create().build();
CloseableHttpResponse response = httpclient.execute(request))
{
StatusLine sl = response.getStatusLine();
int statusCode = sl.getStatusCode();
System.out.println("HTTP Status: " + statusCode);
HttpEntity entity = response.getEntity();
if (entity != null)
{
sResponse = EntityUtils.toString(entity).trim();
System.out.println("HTTP Body:\n" + sResponse);
EntityUtils.consumeQuietly(entity);
}
}
catch (Exception e)
{
request.abort();
throw e;
}
}
catch (Exception e)
{
e.printStackTrace();
}
I searched a lot, but i don't found any solution. I am trying to post a json object with a image encoded in base64 to a web service via android, using the client Resttemplate.
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
ResponseEntity responseEntity;
try {
HttpHeaders header = createHeadersAthententicated(accessToken);
header.setContentType(new MediaType("application", "json"));
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("base64File", ImageUtil.bitmapToString(user.getProfileImageInBitmap()));
jsonObject.addProperty("filename", "profileImage".concat("_").concat(user.getEmail()));
HttpEntity<JsonObject> requestEntity = new HttpEntity<>(jsonObject, header);
responseEntity = restTemplate.exchange(userUrl, HttpMethod.POST, requestEntity, String.class);
} catch (HttpClientErrorException e) {
Log.e(TAG, e.getMessage(), e);
responseEntity = new ResponseEntity(e.getResponseBodyAsString(), HttpStatus.BAD_REQUEST);
} catch (RestClientException e1) {
Log.e(TAG, e1.getMessage(), e1);
responseEntity = new ResponseEntity(e1.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
public static String bitmapToString(Bitmap bitmap) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String temp = Base64.encodeToString(b, Base64.DEFAULT);
return temp;
} catch (NullPointerException e) {
return null;
} catch (OutOfMemoryError e) {
return null;
}
}
The error that I got:
org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON: JsonObject (through reference chain:
com.google.gson.JsonObject["asBigDecimal"]); nested exception is
com.fasterxml.jackson.databind.JsonMappingException: JsonObject
(through reference chain: com.google.gson.JsonObject["asBigDecimal"])
I don't made progress with Resttemplate, so i changed to OkHttp3
final okhttp3.MediaType JSON = okhttp3.MediaType.parse("application/json");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
Request request = new Request.Builder()
.addHeader("Authorization", "Bearer" + accessToken)
.url(userUrl)
.post(body)
.build();
Works perfect.
Just more one thing when you go convert to base64 you have to use Base64.NO_WRAP, this not put the break line.
in my Spring Rest web service I send a file (even big size) as byte array but when I receive the information, the object is a String so when I make the cast from Object to byte[] I receive the following error:
java.lang.ClassCastException: java.lang.String cannot be cast to [B
The originl file is converted through
Files.readAllBytes(Paths.get(path))
and this byte[] is filled in one object with a field result of Object type.
When the Client retrieve this object and it gets result class with cast to byte[] it appears the above exception, this is the client code
Files.write(Paths.get("test.txt"),((byte[])response.getResult()));
If I use a cast to string and then to bytes the content of the file is different from original file. I don't care the file type, file content, I only have to copy from server to client directory
How can I do?Thanks
server class:
#Override
#RequestMapping(value = "/", method = RequestMethod.GET)
public #ResponseBody Response getAcquisition(#RequestParam(value="path", defaultValue="/home") String path){
try {
byte[] file = matlabClientServices.getFile(path);
if (file!=null){
FileTransfer fileTransfer= new FileTransfer(file, Paths.get(path).getFileName().toString());
return new Response(true, true, fileTransfer, null);
}
else
return new Response(false, false, "File doesn't exist!", null);
} catch (Exception e) {
ErrorResponse errorResponse= ErrorResponseBuilder.buildErrorResponse(e);
LOG.error("Threw exception in MatlabClientControllerImpl::getAcquisition :" + errorResponse.getStacktrace());
return new Response(false, false, "Error during file retrieving!", errorResponse);
}
}
and FileTransfer is:
public class FileTransfer {
private byte[] content;
private String name;
..get and set
client class:
#RequestMapping(value = "/", method = RequestMethod.GET)
public #ResponseBody Response getFile(#RequestParam(value="path", defaultValue="/home") String path){
RestTemplate restTemplate = new RestTemplate();
Response response = restTemplate.getForObject("http://localhost:8086/ATS/client/file/?path={path}", Response.class, path);
if (response.isStatus() && response.isSuccess()){
try {
#SuppressWarnings("unchecked")
LinkedHashMap<String,String> result= (LinkedHashMap<String,String>)response.getResult();
//byte[] parseBase64Binary = DatatypeConverter.parseBase64Binary((String)fileTransfer.getContent());
Files.write(Paths.get(result.get("name")), DatatypeConverter.parseBase64Binary(result.get("content")));
return new Response(true, true, "Your file has been written!", null);
} catch (IOException e) {
return new Response(true, true, "Error writing your file!!", null);
}
}
return response;
}
So the client should be something like this
#RequestMapping(value = "/test/", method = RequestMethod.GET)
public Response getFileTest(#RequestParam(value="path", defaultValue="/home") String path){
RestTemplate restTemplate = new RestTemplate();
Response response = restTemplate.getForObject("http://localhost:8086/ATS/client/file/?path={path}", Response.class, path);
if (response.isStatus() && response.isSuccess()){
try {
byte[] parseBase64Binary = DatatypeConverter.parseBase64Binary((String)response.getResult());
Files.write(Paths.get("test.txt"),parseBase64Binary );
} catch (IOException e) {
}
}
return response;
}
I believe the content-type here is text/plain, therefore the content of the file is a plain text. Simply generate byte array from the response:
Files.write(Paths.get("test.txt"),((String)response.getResult()).getBytes());