I'm pretty new to both android and RESTful resources (been learning Rails and RoboSpice). I have a rails api setup correctly and for starters I'd like to pass a user name and password to the api and get a user model object back. I've been looking at the docs and examples and it's been pretty confusing. I was hoping someone could give me a quick example or point me at a good tutorial. Just for a test case, could someone walk me through this snippet and how could I adjust it to query?:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAcceptEncoding(ContentCodingType.IDENTITY);
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the String message converter
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
// Make the HTTP GET request, marshaling the response to a String
ResponseEntity<User> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, User.class);
Also, specifically what do the headers do? and how do I set up a class to recieve the response? i.e. User.class to receive a User model. That part confuses me the most >.< It seems disorganized..
thanks for any help!
This is a very simple example:
private static final String TAG = "HTTP CLIENT: ";
public String login(String User,String Pass){
Log.d(TAG, "Login Attempt!!!");
String result = "Empty!!!";
String url = "http://somehost.somedomain.com:8080/login?email="+User+"&password="+Pass;
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
try {
result = restTemplate.getForObject(url, String.class, "");
}catch (Exception e){
result = e.getMessage();
Log.d(TAG, "Exception Message: "+e.getMessage()+" "+e.getCause());
}
Log.d(TAG, "Token: "+result);
return result;
}
in regards to the Headers they are use to set the type of content that you will handle, for example JSON or XML data.
Related
Hi i am trying to search data in elastic search using spring RestTemplate. ElasticSearch have user name and password and i want to search via json.
I wrote code for this but i am not getting any result or exception. I am doing this for the first time in my life so sorry if there is some silly mistake in it.
#Override
protected List<JobPosts> doInBackground(Object[] objects) {
List list = null;
try {
SearchForm searchForms = (SearchForm) objects[0];
String plainCreds = "******:********";
final String url = "*******";
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpEntity<String> request = new HttpEntity<>(searchJson, headers);
Log.d("location", "before exchange");
ResponseEntity<JobPosts[]> response = restTemplate.exchange(url, HttpMethod.GET, request, JobPosts[].class);
JobPosts[] jobPosts = response.getBody();
Log.d("location", "after exchange");
list = Arrays.asList(jobPosts);
} catch (Exception e) {
Log.d("location", e.getMessage());
}
Unlike other Relational Databases, you don't need Spring RestTemplate to query the elastic database. ElasticSearch comes with inbuilt Java API library. You directly use those functions to create your query and get the results.
Checkout this Link. It has the documentation about how to use the API.
Elastic Search Java API 5.1
I would recommend Using the ES Java API as mentioned by Tanay.
Set up your connection like this
//Create the ES clien
org.elasticsearch.client.Client client;
//Setup the connection. Make sure you use port 9300 and not 9200 here.
client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), "9300"));
//Interact with your index, for example getting an object by its ID
GetResponse response = client.prepareGet("index", "type", "id")
.setOperationThreaded(false)
.get();
//Close the connection
client.close();
My users can post a photo of a food stuff and a post of what the food stuff is about to my server.
For example, let say, someone sees something delicious, snaps a picture of it and then writes "Tasty!" underneath the picture. The photo is sent to the server, and the message "Tasty!" including the users name, date, location etc is sent in an object called "Post" to my server using one api call.
I have written the following code on my android side:
final String url = Constants.POST_PICS;
RestTemplate restTemplate = RestClientConfig.getRestTemplate(context, true);
//adding StringHttpMessageConverter, formHttpMessageConverter and MappingJackson2HttpMessageConverter to restTemplate
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
restTemplate.getMessageConverters().add(formHttpMessageConverter);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
//putting both objects into a map
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("image", new FileSystemResource(file));
map.add("post", post);
HttpHeaders imageHeaders = new HttpHeaders();
//setting content type to multipart as the image is a multipart file
imageHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> imageEntity = new HttpEntity<MultiValueMap<String, Object>>(map, imageHeaders);
ResponseEntity<Post> response = restTemplate.exchange(url, HttpMethod.POST, imageEntity, Post.class);
return response.getBody();
This is the code on the Spring side:
#RequestMapping(value = "/uploadpostpic", method = RequestMethod.POST)
public Post uploadPostWithPic(#RequestParam("image") MultipartFile srcFile,
#RequestParam("post") Post post) {
return serviceGateway.uploadPostWithPic(srcFile, post);
}
I'm getting an error:
An exception occurred during request network execution :Could not
write request: no suitable HttpMessageConverter found for request type
[Model.Post]
org.springframework.http.converter.HttpMessageNotWritableException:
Could not write request: no suitable HttpMessageConverter found for
request type [Model.Post]
I suspect it is to do with the content-type being set to MULTIPART_FORM_DATA but I need it set to this as I need to transfer the picture up to the server.
Is it even possible to transfer a multipart file and another object upstream using restTemplate at the same time?
EDIT:
I have looked at these posts:
Resttemplate form/multipart: image + JSON in POST
Sending Multipart File as POST parameters with RestTemplate requests
And tried according to their guidance this code:
final String url = Constants.POST_PIC;
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new ResourceHttpMessageConverter());
FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
formHttpMessageConverter.addPartConverter(new MappingJackson2HttpMessageConverter());
formHttpMessageConverter.addPartConverter(new ResourceHttpMessageConverter()); // This is hope driven programming
formHttpMessageConverter.addPartConverter(new ByteArrayHttpMessageConverter());
restTemplate.getMessageConverters().add(formHttpMessageConverter);
MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();
byte[] bFile = new byte[(int) imageFile.length()];
FileInputStream fileInputStream;
//convert file into array of bytes
fileInputStream = new FileInputStream(imageFile);
fileInputStream.read(bFile);
fileInputStream.close();
ByteArrayResource bytes = new ByteArrayResource(bFile) {
#Override
public String getFilename() {
return "file.jpg";
}
};
//post portion of the multipartRequest
HttpHeaders xHeader = new HttpHeaders();
xHeader.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Post> xPart = new HttpEntity<>(post, xHeader);
multipartRequest.add("post", xPart);
//picture portion of the multipartRequest
HttpHeaders pictureHeader = new HttpHeaders();
pictureHeader.setContentType(MediaType.IMAGE_JPEG);
HttpEntity<ByteArrayResource> picturePart = new HttpEntity<>(bytes, pictureHeader);
multipartRequest.add("srcFile", picturePart);
//adding both the post and picture portion to one httpentity for transmitting to server
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity(multipartRequest, header);
return restTemplate.postForObject(url, requestEntity, Post.class);
On the other side, the post = null and I'm not sure why it is null.
This is all I'm trying to do on the server side:
public Post uploadPostPic(MultipartFile srcFile, Post post) {
Post savedPost = repo.save(post);
}
I'm saving it into my repository and the error is :
java.lang.IllegalArgumentException: Entity must not be null!
Try something like this:
Send jsonString here and later convert it to object using objectwriter.Let me know if you need more explanation.
#RequestMapping(value = "/uploadMultipleFile", method = RequestMethod.POST)
public #ResponseBody
String uploadMultipleFileHandler(#RequestParam("name") String[] names,
#RequestParam("file") MultipartFile[] files) {
if (files.length != names.length)
return "Mandatory information missing";
String message = "";
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
String name = names[i];
try {
byte[] bytes = file.getBytes();
// Creating the directory to store file
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists())
dir.mkdirs();
// Create the file on server
File serverFile = new File(dir.getAbsolutePath()
+ File.separator + name);
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
logger.info("Server File Location="
+ serverFile.getAbsolutePath());
message = message + "You successfully uploaded file=" + name
+ "<br />";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
}
return message;
}
}
EDITED:
Eventually, I had to make use of the jsonString to solve my problem. It is not ideal as the url will end up becoming very long but it is the quickest way to solve my problem:
Please have a look at the advice from mykong on how to transform your object to jsonString and retransform them back into objects:
ObjectMapper mapper = new ObjectMapper();
Staff obj = new Staff();
//Object to JSON in String
String jsonInString = mapper.writeValueAsString(obj);
//JSON from String to Object
Staff obj = mapper.readValue(jsonInString, Staff.class);
http://www.mkyong.com/java/jackson-2-convert-java-object-to-from-json/
I don't see a registered HttpMessageConverter for your Post class. You will probably have to register an HttpMessageConverter for MultiValueMap.
oookay,I faced the same problem few weeks ago. First of all to be clear what multipart/form-data content-type means:
A "multipart/form-data" message contains a series of parts, each
representing a successful control.
A successful control is "valid" for submission. Every successful
control has its control name paired with its current value as part of
the submitted form data set
in simple words, with multipart form-data you can send different content-types of data to server. here is a sample:
POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Length: 554
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="text"
text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------9051914041544843365972754266--
here is a sample of sending three different sets - the first one is binary data the second one is plain text and the third one is html and they are separated by boundary.
now how working Spring's RestTemplate ?
when you set the request header to multipart/form-data , resttemplate will pick up appropriate HttpMessageConverter from registered message converters which for multipart/form-data will be FormHttpMessageConverter see doc here.
But FormHttpMessageConverter have a property of partConverters and they are converters registered for the FormHttpMessageConverter and by default they are (string,bytearray and resource). here is a source code of the constructor ;)
public FormHttpMessageConverter() {
this.supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
this.supportedMediaTypes.add(MediaType.MULTIPART_FORM_DATA);
this.partConverters.add(new ByteArrayHttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
this.partConverters.add(stringHttpMessageConverter);
this.partConverters.add(new ResourceHttpMessageConverter());
}
with simply words, FormHttpMessageConverter cannot find correct message converter to write object Post. If you want Post to be written as JSON you should add MappingJackson2HttpMessageConverter to partConverters.
#Produces
public RestTemplate getRestTemplate() {
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(0,createFormHttpConverter());
return template;
}
private static HttpMessageConverter<?> createFormHttpConverter(){
FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
formHttpMessageConverter.setPartConverters(getPartConverters());
return formHttpMessageConverter;
}
private static List<HttpMessageConverter<?>> getPartConverters(){
RestTemplate template = new RestTemplate();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
List<HttpMessageConverter<?>> messageConverters = template.getMessageConverters();
messageConverters.add(0,converter);
return messageConverters;
}
You need to tell Spring how to map the request parameters to your objects. You could do this by implementing a custom HttpMessageConterter like suggested by Alexander, but I there is a much easier way: Use a command-object (sometimes called form-backing object):
public class PostWithPicCommand() {
public PostWithPic() {}; //Default constructor is required
//name the variables like the request parameters!
private Post post;
private MultipartFile image;
Getter and Setter!
}
#RequestMapping(value = "/uploadpostpic", method = RequestMethod.POST)
public Post uploadPostWithPic(PostWithPicCommand postWithPicCommand
/*no #Param attribte for postWithPicCommand*/) {
....
}
And you need to configure/register springs Multipart Resolver, and need to send the request as an multipart request.
I made something similar using this:
HttpHeaders headers = new HttpHeaders();
headers.add("Accept","application/json");
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("image", new FileSystemResource(file));
map.add("post", post);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headers);
RestTemplate restTemplate = RestClientConfig.getRestTemplate(context, true);
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
ResponseEntity<Post> response = restTemplate.postForObject(url, requestEntity, Post.class);
I am new to work with RestTemplates.In my application i am trying to send request by using post method as follows
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(new MediaType("application","json",Charset.forName("UTF-8")));
requestHeaders.add("username", "sai3");
requestHeaders.add("password", "x");
requestHeaders.add("device_id", device_id);
HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
` restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
ResponseEntity<GetResponseBean> responseEntity1 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, GetResponseBean.class);
obj = responseEntity1.getBody();
Log.v("GetDataResponse", "result message : "+obj);
For the above code i have used "spring-android-core-1.0.1.RELEASE.jar","spring-android-rest-template-1.0.1.RELEASE.jar" and "jackson-all-1.9.8.jar"
If I use ResponseEntity type is String then it is returning fine response but If I change ResponseEntity type GetResponseBean type then i am getting error as follow :
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [com.example.springsxmlposting.GetResponseBean] and content type [text/html]
GetResponseBean class as follows:
public class GetResponseBean {
String result = null;
String message = null;
public void setmResult(String result) {
this.result = result;
}
public String getmResult() {
return result;
}
public void setmMessage(String message) {
this.message = message;
}
public String getmMessage() {
return message;
}
}
How can i get the data into my bean class (GetResponseBean) please any body help me
I think the problem relies in your server. You're sending content-type: application/json but as you can see in your error, it states that the response you get is text/html and not application/json.
My guess is that the response you're getting back is an error html page that states that you don't have a request that returns application/json. You can try and use an external tool for sending the request to the server. Do a POST request with the same headers and I bet you'll get an HTML error page.
I am working with robospice. Now I want to upload file.
I used SpringAndroidSpiceService and write my own request like this :
public class UploadFileRequest extends SpringAndroidSpiceRequest<String>{
private static final String TAG = "UploadFileRequest";
private UploadRequestModel requestModel;
private String link;
public UploadFileRequest(UploadRequestModel model, String link) {
super(String.class);
requestModel = model;
this.link = link;
}
#Override
public String loadDataFromNetwork() throws Exception {
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("file1", new FileSystemResource(requestModel.getFile1()));
parts.add("file2", new FileSystemResource(requestModel.getFile1()));
HttpHeaders headers = new HttpHeaders();
HttpEntity<MultiValueMap<String, Object>> request =
new HttpEntity<MultiValueMap<String, Object>>(parts, headers);
return getRestTemplate().postForObject(link, request, String.class);
}
}
I can send the files now. But I faced a problem.
After the files have sent. My files on disk are almost deleted. It's size is zero.
Do you know why ? and how can I resolve it ?
Thank you very much for any help.
I am on of the authors of RS. The problem you face is not related to RS directly but to Spring Android. I suggest you write to their forum to get an answer. Sorry, but we can't tell you more.
Stéphane
this.message.setApi_key(ConfigurationBean.getTab_id());
this.message.setApi_password(ConfigurationBean.getTab_assword());
this.message.setNursery_id(ConfigurationBean.getNursery_id());
url=ConfigurationBean.getNursery_url()+"/api/v1/installation.php";
try {
list=service.getConfiguration(admin, pass);
} catch (Exception e) {
Log.e("request", ""+e.getMessage());
}
// Add the Jackson and String message converters
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
// Make the HTTP POST request, marshaling the request to JSON, and the response to a String
String response = restTemplate.postForObject(url, message, String.class);
return response;
this is my code,
before i was getting the same problem ,not its working fine u can try this message enter code hereconverter which will help
I am using spring android framework for retrieving json data via Http GET. I am getting following exception for the same :
- Could not read JSON: Can not deserialize instance of com.springandroidjsondemo.beans.LoginBean[] out of START_OBJECT token
The bean (LoginBean) is Following
package com.springandroidjsondemo.beans;
public class LoginBean {
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
The android code is following :
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Collections.singletonList(new MediaType("application", "json")));
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the Jackson message converters
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
// Make the HTTP GET request, marshaling the response from JSON to an array of Events
ResponseEntity<LoginBean[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity,LoginBean[].class); // getting exception here
LoginBean[] loginBean = responseEntity.getBody();
String status = loginBean[0].getStatus();
The json response from the server is following :
{"emp-data":[{"status":"true"}]}
I am not sure if any annotations are required for Jackson Marshalling
Please suggest the solution
Thanks!
this is a Jackson deserialization issue. if you compare the JSON response with your LoginBean, the array of statuses is contained within the element "emp-data". However, your RestTemplate request is expecting JSON which looks like the following.
[{"status":"true"},{"status":"false"}]
You have a couple options. You can create a wrapper object around LoginBean. Or you can try annotating the LoginBean like the following:
#JsonRootName(value = "emp-data")
public class LoginBean {
...
}
In order for this to work, you probably need to configure the Jackson ObjactMapper.
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
MappingJackson2HttpMessageConverter jackson = new MappingJackson2HttpMessageConverter();
jackson.setObjectMapper(objectMapper);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(jackson);