Passing a JSONObject as a parameter on Spring MVC - java

I wish to implement a REST service using Spring MVC where I pass in the following object at the URL "/url/lookup/{jsonparm}":
{"url":"http://bubba.com/foo/bar", "max_hops":3}
I tried the following:
#RequestMapping(value = "/url/lookup/{jsonparam}", method = RequestMethod.GET)
#ResponseBody
public String urlLookup(#PathVariable("jsonparam") String jsonparam) {
// just to see if I can get the parms
logger.debug("urlLookup get request : " + jsonparam.toString());
JSONObject resp = new JSONObject();
return resp.toString(); // return an empty JSONObject for now
}
So I invoke this by calling
http://localhost:8080/v1/wsp/url/lookup/%7B%22max_hops%22%3A3%2C%22url%22%3A%22http%3A%2F%2Fbubba.com%2Ffoo%2Fbar%22%7D
No luck see the following in my Jetty log:
WARNING: No mapping found for HTTP request with URI [/v1/wsp/url/lookup/{"max_hops":3,"url":"http://bubba.com/foo/bar"}] in DispatcherServlet with name 'rest'
Notes:
the url prefix localhost:8080/v1/wsp/ is correct and my Servlet and Request Mapping are also correct
I have updated the question to use a #PathVariable as one of the responders suggested
Thanks.

You're confusing GET and POST methods.
Either:
Use POST method and actually post the JSON contents to the controller. You can debug this using any REST client, eg. Advanced Rest Client for Chrome.
Use GET method (as you are currently). But you have to pass the JSON value as an actual parameter called jsonparam. So, your example should change to:
http://localhost:8080/v1/wsp/url/lookup/jsonparam=%7B%22max_hops%22%3A3%2C%22url%22%3A%22http%3A%2F%2Fbubba.com%2Ffoo%2Fbar%22%7D
The latter is less common.
Edit:
On second look at your URL, I suspect you're confusing two Spring annotations:
#PathVariable("jsonparam") and:
#RequestParam("jsonparam")
You're using #RequestParam while your URL indicates need for #PathVariable.
Edit2:
However, as can be read here: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates the path variable can be passed a value of any simple type. I believe JSON isn't one of them, hence your problems.
I would strongly recommend using POST for interchanging JSON values. However, if that is not an option, I would recommend sticking with GET method, #RequestParam for accessing parameter value, and passing the JSON value like in the corrected example above.

You should use #PathVariable instead of #RequestParam:
public String urlLookup(#PathVariable("jsonparam") String jsonparam){
}
because you have #RequestMapping(value = "/url/lookup/{jasonparam}"
And you have a typo in your #RequestMapping value. It should be /url/lookup/{jsonparam} instead of {jasonparam}

Related

Spring Boot Controller Multiple parameters (<List> and multipart file) object

Hello i am looking if i can handle with only one RestController method multiple params...
with controllers method it could be done... but i couldnt find project with 2 like that.
#PostMapping(value ="upload")
public upload(#RequestParam MultipartFile file,#RequestParam List<String> myParams ){
some code here ....
return;
}
I am just wondering if is also a good practise ... having two deferent type of objects in same controller and if its possible,,, any idea????
Simple answer: Yes, that's possible.
But as you asked for good practice, here's some context:
It is very helpful to understand how HTTP actually transports data.
If your request uses GET as request method, parameters are added to the URL as a query string. That could look like this: http://example.com/index?param1=value1&param2=value2
In this case, Spring maps the key-value pairs from the query string to your method arguments. But this will only work for text.
If you're using POST, the data is sent inside the request body. How that is encoded depends on the media type of your data. For example, the default media type application/x-www-form-urlencoded would encode the data to the same query string as above.
If you want to upload mixed-type form data like a file/blob along with some textual parameters, your data should be encoded with multipart/form-data.
As long as the request body contains a key-value format, Spring Boot will still be able to distinguish and map the parameters via #RequestParam (If the keys don't differ from your attribute names, you don't even need to assign a name to the value attribute).
I highly recommend you to take a look at the #RequestBody and #RequestPart annotations as i think it often is best practice to use a model class (DTO) for the whole request body (or rather the form, semantically), especially if there are a lot of parameters to process.
You will need to specify the names of the variables.
#PostMapping(value ="upload")
public upload(
#RequestParam(value = "file") MultipartFile file,
#RequestParam(value = "myParams") List<String> myParams
){
some code here ....
return;
}

How can send multiple params on a get request

First of all, give thanks for reading my question and try to help me and apologize for my English.
I'm new with Spring and I have this message:
A servlet request to the URI
http://localhost:8080/backend/v1/streetviewer/search-street?url=backend2?busqueda=name%20street&idioma=es-es%26cantidad=10
contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
My backend send a request to backend2 with one parameter (url), but that url contains 3 parameters. I understand that is reason why say that.
But I was reading that #FormParam is used for POST requests and I'm using #QueryParam.
#GET
#Path(ApiPath.PATH_BACKEND2)
public String getDataFromProdServer(#QueryParam(ApiParam.PARAM_URL) final String externalUrl ) {
return mapService.ServerRequest(externalUrl);
}
How can solve it??
To be said you are actually using JAX-RS Implementation, from backend2 I asume it is a separate service so I suggest you to use Spring Implementations for consuming the API. #RequestMapping/#GetMapping and so..
Coming to the question (With Spring Implementation)
#GetMapping(ApiPath.PATH_BACKEND2)
public String getDataFromProdServer(#RequestParam(ApiParam.PARAM_UR) final String externalUrl) {
return mapService.serverRequest(externalUrl);
}

explicitly get post parameter or query parameter in controller method

I am using the #RequestParam annotation to instruct Spring MVC to inject a "web request parameter" (as the Javadoc calls them) into a method call in my code:
#RequestMapping(path="/signup-submit", method=RequestMethod.POST)
public String signupSubmit(#RequestParam(value="originURL", required=true) String originURL ...) {
...
I am bothered by the fact that this annotation apparently works both for POST parameters and for URL query parameters. I.e. looking at the above code it is not possible to say whether the originURL is a POST body parameter or is a URL query parameter. Is there an annotation I can use to explicitly get it from either one or the other?
This is why I also place "web request parameter" in quotation marks as I don't think this is a technical term and I guess it is used in the loose sense of "some parameter either passed in the POST method body or as a query parameter in the URL".
Contrary to what cularis said there can be both in the parameter map.
The best way I see is to proxy the parameterMap and for each parameter retrieval check if queryString contains "&?=".
Note that parameterName needs to be URL encoded before this check can be made, as Qerub pointed out.
That saves you the parsing and still gives you only URL parameters.
The way can be getting query string..
public List<Topic> getTopics(HttpServletRequest req) {
String queryString = req.getQueryString();
.....
About "Web-Request-Parameter" (#RequestHeader), you are right as it consists of both params i.e. either are part of query or a part of request body.
Not the exact solution to your problem. But seems like there's an easy hack for it. You can use #RequestBody. This only looks for request body. If param is not found in request body, you can be sure that it is from request param.

Pass an URL as param in RESTful WebServices

I'm defining a RESTful WebService in Java.
It takes as input:
an username (for instance, jdoe);
an URL (for instance: https://blablablabla.io/sample?boh=mah).
By using GET method of the HTTP protocol, it should produce a JSON file.
Which is the best way to pass these params?
In this particular case, is there a best practice to follow in order to properly pass an URL as param?
You must first encode it, you can use
URLEncoder.encode("url");
If you want to define an http GET method, then the only way to pass parameters to it is through the URI query string (ie. ?x=y&...).
This is because GET calls can not take in a message body.
If you want to pass in more complicated information, you will need to use POST, PUT, or some other method. Though, if you are actually just getting information (semantically), then you shouldn't use anything but GET.
Also you can use Path parameters
This is example
#Path("/users")
public class UserResorce {
#GET
#Path("/{username}")
#Produces(MediaType.APPLICATION_JSON)
public String getUser(#PathParam("username") String username)){
}
}
The url is http://domain_name/your_application_path/users/username

POSTing JSON to Spring MVC Controller Returns 400 Bad Request

I'd like to POST JSON and have Jackson convert it to a POJO, but for now I can't even POST a simple String parameter.
I'm using Jackson 2.3.2 (jackson-core and jackson-databaind)
I'm using Spring 3.2.8.RELEASE (spring-context, spring-webmvc)
My Controller looks like this:
#RequestMapping(value="add-name", method=RequestMethod.POST, headers = "Accept=application/json")
public String addName(#RequestParam(value = "name", required = false) String name) {
LOG.info(String.format("name: %s", name));
return "name";
}
I POST to this Controller with data like this:
{ "name" : "my_name" }
The response I receive is 400 Bad Request
Note: I'm submitting the POST via jQuery.post(), but to remove that as a variable, I'm also submitting POST via FF Poster add-on specifying the URL, Content Type (application/json), and data as above.
Edit: I think the issue may be that the Jackson library isn't even being called. I took it out of the dependencies and nothing changes, no different error/exception, I still simply get a 400 Bad Request response.
Edit 2: Even if I take out the parameter to addName completely and post an empty body {} I still get a 400 Bad Request
You are posting raw data in the body, but your controller is looking for a parameter named name. Either post with a parameter name whose value is my_name, or use #RequestBody in the handler to pass in the JSON object.
I downgraded to Spring 3.1.1.RELEASE and Jackson 1.9.9 and it works now. Seems like a hack. I thought Spring 3.2 and Jackson 2 were compatible.

Categories

Resources