HTTP Status 405 - Method Not Allowed (jax-rs service) - android

Jax-rs service return HTTP Status 405 - Method Not Allowed.
Service:
#GET
#Consumes(MediaType.TEXT_HTML)
#Produces(MediaType.APPLICATION_JSON)
#Path("login")
public User Login(#QueryParam("u") String username, #QueryParam("p") String password) {
return UserDAO.getInstance().getLogin(username,password)
}
Android:
public static Boolean Login(User user) {
String url = "http://myserver.com/AndroidServis/rest/login?u={u}&p={p}";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HashMap<String, String> params = new HashMap<String, String > ();
params.put("u", user.getUsername().toString());
params.put("p", user.getPassword().toString());
HttpEntity entity = new HttpEntity(headers);
restTemplate.getMessageConverters().add(new GsonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpEntity < Korisnici > response = restTemplate.exchange(url, HttpMethod.GET, entity,User.class, params);
}

It doesn't make sense for the server to have a #Consumes annotation on the #GET method, as this is typically only used for PUT or POST requests where the client is sending some content to the server.
Can you remove this?
Then also remove this from the client code.
headers.setContentType(MediaType.APPLICATION_JSON);
and you may need to uncomment the line you have commented out:
headers.set("Accept", "application/json");
This tells the server what content type is expected in the response so must match what the #Produces of the service.

Related

How to get token returned in response body (of authentication web service) using RestTemplate?

im using RestTemplate to call the authenticate web service and POST username and password,i need in return to get the token from response body but i can't find a clear way to do it..Here is my code
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Content-Type","application/json");
requestHeaders.add("Accept", "application/json");
requestHeaders.add("Authorization", auth_token);
final String url = "http://192.168.1.3:18080/api/authenticate";
RestTemplate restTemplate=new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("password",password);
map.add("username",username);
HttpEntity<MultiValueMap<String, String>> entity= new HttpEntity<MultiValueMap<String, String>>(map, requestHeaders);
String response = restTemplate.postForObject(url,entity,String.class);
return response;
and this is the response body that i need to get the token from it:web service response body
You're pretty much there, at the moment your code gets the whole JSON response as a string:
return restTemplate.postForObject(url,entity,String.class);
// {"id_token": "blahblahblah"}
Instead you can either transform to a Map and take the correct value:
Map<String, Object> response3 = restTemplate.postForObject(url, entity, Map.class);
return response3.get("id_token")
// blahblahblah
or create a class:
public class AuthResponse {
#JsonProperty( "id_token" )
private String idToken;
public String getIdToken() {
return idToken;
}
public void setIdToken(String idToken) {
this.idToken = idToken;
}
}
and transform that:
AuthResponse response4 = restTemplate.postForObject(url, entity, AuthResponse.class);
return response4.getIdToken();
// blahblahblah

Spring RestTemplate: post both an image and an object at the same time

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

Querying an api with android spring?

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.

Robospice loadDataFromNetwork() not working

I am using spring android in robospice. I need to place headers with get request so i used exchange() method. The code has no error but does not fetch anything
public MList loadDataFromNetwork() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.add(key,keyValue);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<MList> response=getRestTemplate().exchange(url,HttpMethod.GET,entity,MList.class);
return getRestTemplate().exchange(url, HttpMethod.GET,new HttpEntity<Object> (headers),MList.class).getBody();
}
RestTemplate restTemplate=new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
headers.add(key,keyValue);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<Pojo> response=restTemplate.exchange(url,HttpMethod.GET,entity,Pojo.class);
return response.getBody();
It worked when I edited the code like this.
But I got a null pointer exception when used
RestTemplate restTemplate=getRestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter())

how to get the data into my Bean class with the help of RestTemplate object?

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.

Categories

Resources