Differentiating URI and request body parameters in same servlet request - java

I would like to imbue my API with the ability to set values on a range of objects in a single call. A seemingly logical solution is for the user to define in the ranges in the URI and set the desired new values in the request body. For example the URI would be:
/api/horses/?color=brown
In the request body, the key/value pair would be
key: color
value: red
This will turn all of our brown horses red.
The problem is that getting parameters from the HttpServletRequest object does not let you determine if the parameters were set in the URI or the body.
Perhaps there are two questions here:
If there is different, generally accepted RESTful way to set values on a range of objects in a single call, what is it?
If using both URI and request body parameters is ok, how do you differentiate between those in the HttpServletRequest object?
Update: The accepted answer addresses how to differentiate (the second of the enumerated questions). To address the general challenge for updating a range of values, I decided that this can be best accomplished by limiting to only one updated field and specifying the field in the path. Like so:
PUT /api/horses/color?from=brown&to=red

So your problem is that you have a name clash between parameters encoded in the request line and parameters encoded in the POST body.
You can always differentiate by calling:
HttpServletRequest.getQueryString()
HttpServletRequest.getInputStream()
obviously you then have to use a URL library for parsing the query string (the encoded/decoder in the JDK is ok) and library for the form data, depending on the encoding (I recall some Apache project called commons-codec for this).
I'd go the simplest route of not having name clashes - for example by prefixing URL parameters with filter- but there's no standard rule for this.

Related

Can I combine multiple parameters in a request to a single argument to the controller?

I need to consume a request which I'm not in control of. When the client posts an array ['a', 'b', 'c'] as x.
What I actually receive is:
?x.0=a&x.1=b&x.2=c
I think the correct encoding of that is ?x=a&x=b&x=c but as mentioned I'm not in control of the request.
Is there some sort of interception I can do to fix up my x.index request into the expected encoding? I've tried writing a Converter but I could only persuade that to map a single parameter into another type.
You could implement your own HandlerMethodArgumentResolver and bind the x parameter from HttpServletRequest object. Take a look at: How to implement custom parameter mapping in Spring MVC.
If it's a single endpoint that handles the strange parameter convention it would be more readable to just have HttpServletRequest as method parameter and do the work there before calling service.
Honestly I'd rather force the client to change the request structure. It doesn't look like a valid syntax for passing array with GET.

Optional parameter in #PathParam annotation

We are facing issue related with making a path parameter optional.
original URL /expire/{token}
What we are trying to do is have the same service work for the URL's below.
1. /expire/{token}
2. /expire
Ex:- #Path("/expire/{token}")
We have already applied other solutions from SO,but no luck so far.
What about adding another method annotated with only:
#Path("/expire")
And let this method pass a null value into the original method.
Logically, it doesn't seem to make sense to have it optional. Your URI should handle the type of request it's supposed to do. But, I came across a post to make the #PathParam to be optional with a small hack using regular expressions.
http://www.nakov.com/blog/2009/07/15/jax-rs-path-pathparam-and-optional-parameters/
I would go with having separate endpoint method in Controller where it can pass the call to your services with optional parameter.
We can use regular expressions,
"#Path("/add/{a:([0-9.]*)}/{b:([0-9.]*)}{p:/?}{c:([0-9.]*)}")"
here path can be
add/2/3
add/2/3/4
my case I am using regular expressions for allowing only numbers

Distinguish empty value from empty string ("") in Url query parameter

How to distinguish URL without value like this /url?var from /url?var="" in Spring MVC?
Method HttpServletRequest::getParameterMap() in controller returns "" in both ways.
I need this to separate commands from queries to specified resource.
One simple way of going about doing what you want to is use the getQueryString() of HttpServletRequest. You would just check and see if the returned String contains the pattern you are looking for.
If you need something like that often (as in many controller methods) you could also easily create a custom HandlerMethodArgumentResolver that will indicate the presence of a String in the URL.
Here is the relevant Javadoc and here is an example
/url?var is a valid URL which states that you have a parameter var which is not initialized.
So by default it is initialized to empty string. That's the framework behavior.
If you don't want to see that parameter coming in HttpServletRequest::getParameterMap(), just don't use it with URL (i.e. /url should be your call)

Overflow protection for numbers jax-rs

With #Path variables it is possible to stop overflow conversions (from string to number).
For example if a parameter is an integer (int) then a path expression like {number : \d{1,5}} is a breaker before doing a number conversion.
What about handling query parameters in a similar fashion? The syntax for path variables isn't usable in the #QueryParam annotation (#QueryParam("big : \d{1,5}") big...).
Introduction: The path parameters guide the request to the correct method, and therefore a big flexibility is needed for that. The request parameters (GET/POST/...) on the other side need to be validated, i.e if a request contain invalid parameter value, you should take care of that.
Solution:
Beginning with JAX-RS 2.0 (published in May 2013 with the reference implementation Jersey 2.0) you have support for validation. Check this examples.
Before JAX-RS 2.0 (probably your situation) you should do the validation manually, e.g by injecting an int or long and checking its limits.

String Compression: Passing Object Through URL

I have two pages, say A and B. User navigates from Page-A to Page-B. Page-B needs to have some values which are passed from the Page-A. Among these values some of them are Objects. Now I have the following ways to pass the parameter to Page-B
Store the Objects in some Scope (say Session, Page-Flow).
Pass the Objects as query string after converting them into String.
The drawbacks of the above two ways are followings respectively:
If User bookmarks the Page-B for later usage and try to access it from different session, it generates Exception. As the Objects are not present in the scope.
There are limitations of the length of the URL, which is 2048 Character (ref). So if I convert it to JSON and try to pass it through URL and if the JSON String is more than the limited characters, I would get JSON Exception from Page-B.
Can I compress the String representation of the Object so that it will not exceed the limitation Character?
How can I solve this issue (by any other means)?
Any solution is greatly appreciated.
Putting serialized objects in the URL is a really bad idea. If you want to access state via URL (GET parameters) then normally the URL should only contain some way of identifying the item in question.
Fortunately if you're using a database back end to persist your objects then the database will usually give them an identity for you, in the form of a primary key. You can then just put the ID in the URL and have Java retrieve the object for that ID whenever it receives a request for it.
If you don't use a database back end then it's up to you to give your objects an identity that they can be located by. The simplest solution would be to store references to the objects in a map and put the map key in the URL.

Categories