explicitly get post parameter or query parameter in controller method - java

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.

Related

RESTeasy: Pass through all query params

We have a proxy API set up where we accept any path after our proxy (i.e. /proxy/some/path) and then everything after the proxy path should be forwarded on to another API using RESTeasy (so it would call /some/path in my example).
This is necessary for us for several reasons including avoiding CORS issues and it works most of the time for what we need. However, some routes require query parameters some or all of the time, and because we are handling all routes the same, this causes a RESTeasy error today since the URL gets URL encoded to something like /some/path%3ffilter=value.
Our endpoint today looks like:
#Path("proxy/{someUri : .*}")
#GET
public Response proxyGet(
#PathParam("someUri") String someUri,
#HeaderParam(COOKIE) String cookieHeader,
#Context HttpServletRequest request
) {
return prepareProxyResponse(someUri, cookieHeader, request, null);
}
Our RESTeasy interface looks like:
#GET
#Path("/{requestPath}")
Response proxyGet(
#PathParam("requestPath") String requestPath,
#HeaderParam(COOKIE) String sessionCookie,
#HeaderParam(CONTENT_TYPE) String contentType
);
The code that calls this looks like:
return client.proxyGet(fullPath, cookieHeader, contentTypeHeader);
Prior to understanding this issue, we just took the request URI and added the query string to it so the requestPath above looked like some/path?filter=value which gets mangled. Removing the query string avoids that, however, it also means we cannot pass any query params through.
Is there a way to accept any query params and submit them to the other API using RESTeasy? I know we can break these out where needed to manually specify query params with #QueryParam but since there are many (and more getting added regularly) this will be a lot of effort. I think accomplishing what we are trying to do is not possible based on my research in other questions and the docs, but wanted to double-check before we embarked on a long process to convert. Thanks!

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

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

When is #RequestParam annotation not needed in Spring MVC?

I'm looking through some Spring 3 MVC controller code and I see that #RequestParam is used for some parameters and not for others. Example where it is not being used:
#RequestMapping(value = "/experiments", method = RequestMethod.GET)
public String getExperimentsPage(ExperimentSearchCriteria criteria, Map<String, Object> model) {
// method body here
}
When is #RequestParam (or similar parameter-specifying annotation) not needed?
Good question, I have been wondering this too until I found it being mentioned in the doc:
Note that use of #RequestParam is optional, e.g. to set its
attributes. By default any argument that is a simple value type, as
determined by BeanUtils#isSimpleProperty, and is not resolved by any
other argument resolver, is treated as if it was annotated with
#RequestParam.
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestparam
Most of time, I don't specify this unless my method parameter name is different with request parameter, or, if the value is optional, I will need to use required=false.
#RequestParam is used to pass query parameters.
Example: http://localhost:8080/employee/get?status=ACTIVE
Here we can get status with below code
#RequestParam(value="status") String status
We have some properties like required, defaultValue etc. If you provide required=false as mentioned in below line of code, the status parameter is not mandatory in URL
#RequestParam(value="status",required=false)
The URL will be like http://localhost:8080/employee/get
I'm not really sure about your question, but you only need #RequestParam when you want to bind a method argument with a parameter held by the request.
I think this is pretty clear here.

Passing a JSONObject as a parameter on Spring MVC

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}

Categories

Resources