Prevent RestTemplate from reordering parameters - spring

I'm trying to use the RestTemplate to send a request with the following format:
http://host:port/action?loc=x,y&t=z&loc=x1,y1&t=z1...
What's important is that the ordering of parameters matters. In this case the each t refers to location previous loc.
No matter how I try to set the parameters for the RestTemplate the resulting request parameters get reordered. All loc parameters appear before all t like this: http://host:port/action?loc=x,y&loc=x1,y1&loc=...&t=z1&t=z2&t=...
Is there any way to prevent RestTemplate from reordering the request parameters.
Thank you.

If you have multiple parameters with the same name, in your case multiple instances of loc - it is treated as an array, that's why they're all coupled together.

Related

violation : Number of parameters should be limited - spring boot

I'm working in a spring boot application, where i'm getting violation as, "number of parameters should be less than 8"
i,m passing all the parameters through request param
I'm passing exactly 8 parameters all are mandatory
any other way to overcome this ?
In general, it looks like bad API design that you have so many request params. Request params are normally only used for things like filter and sorting options, but not to provide any actual data. Instead, use the request body.
Nevertheless, you can also get all parameters as a HashMap using:
#PostMapping("/api/example")
#ResponseBody
public String examplePost(#RequestParam Map<String,String> allParams) {
return "Parameters are " + allParams.entrySet();
}

Mapping of missing URI variables to Request Mapping

I've developed a Spring API /getFileData, which accepts three URI parameters viz. businessDate/fileName/recordId. It is possible to have any of them can be passed as null. But I still want my API to be working in this case also. How can I achieve this?
I've tried using #GetMapping("getFileData/{businessDate}/{fileName}/{recordId}", "getFileData/{businessDate}//", "getFileData/{businessDate}/{fileName}/")..so on like this for all possible combinations.
#RequestMapping(value = "/getFileData/{businessDate}/{fileName}/{recordId}", method = RequestMethod.GET)
I want this API to be working for all the combination of URI parameters if something get missed out. for example someone requested,
/getFileData///22 or
/getFileData/22Dec2018/ or
/getFileData//treasure/22
You can do that with a #RequestParam of type java.util.Map.
With your design, you will have various #PathVariable params in the controller method as well as the order of path variables /{var1}/{var2}... constructs the url so I don't think it would be possible to skip a path variable in the url and still call the same controller method.

Response.getMetaData().get("location") in jersey: Why does it return a list?

In my service I am executing the following line:
return Response.created("someuri").build();
Then in my client in order to get the location I have to do
response.getMetaData().get("location").get(0);
This is all good and well, but I am wondering why on earth that is returned as a List instead of just a URI. Can a jersey expert help me out here?
Thanks!
getMetaData() returns a map of Headers in the HTTP response, and while we'd expect only one value per key most of the time, the way the HTTP protocol lists Headers line by line, there is no enforcement that header names have to be unique, so the API reflects that in its MultivaluedMap.
Moreover while we'd expect a unique value for "Location", there are valid use cases for having multiple values for other types of headers such as "Set-Cookie".

RESTful URLs: "Impractical" Requests, and Requiring One of Two Request Parameters

I have a RESTful URL that requires either the offset or the prefix request parameter (but not both).
GET /users?offset=0&count=20
GET /users?prefix=J&count=20
What's the best way to enforce this rule? Spring has the #RequestParam annotation with the 'required' property for optional parameters, but I want to enforce an "either-or" rule on these two parameters. I know I could do it in the code, but is there another way to do it?
Also, what's the proper way to handle "impractical" requests? Say I have 100 million users; the following request, although properly RESTful, is not something I want to support:
GET /users <-- Gets all 100 million users, crashes server and browser!
What should I send back?
You can create two methods and choose one of them with #RequestMapping's params attribute:
#RequestMapping(..., params = {"prefix", "!offset"})
public String usersWithPrefix(#RequestParam("prefix") ...) { ... }
#RequestMapping(..., params = {"offset", "!prefix"})
public String usersWithOffset(#RequestParam("offset") ...) { ... }
what's the proper way to handle "impractical" requests?
The lesser-practiced principles of REST include the requirement that resources be "discoverable". If you are asked for a complete list of 800 million users and you don't want to provide it, you might instead consider serving a page that describes in some way how to filter the collection: for example, an XForms document or HTML containing a FORM element with fields for offset/prefix/count, or a URI template with the appropriate parameters
Or you could just send a "413 Entity too large" error - edit: no you can't. Sorry, I misread the description of whath this code is for
If you decide to go down the route of just sending the first page, I think I would send it as an HTTP redirect to /users?offset=0&count=20 so that the client has a better idea they've not got the full collection (and if your response contains a link to access subsequent pages, even better)

Stop URITemplate expansion when using Spring RESTTemplate

I am using the Spring RestTemplate to make calls to a Apache Solr index. I form a request string manually and don't supply any intentional {variable_name} template expansion variables. Part of the query is the term {!lucene q.op=OR}. Unfortunately this gets processed by the URITemplate engine as part of a restTemplate.getForObject call.
Ideally i would like to stop this processing. Is there away of escaping the { } characters so that URITemplate doesn't process them? I have tried encoding the characters but RestTemplate assumes a non-encoded string so they are encoded twice and cause a 400: Bad Request on the backend.
Sample URL:
http://localhost/solr/select?q={!lucene
q.op=OR}se_genbanklocus:*
se_gb_create:* se_gb_update:*
se_clone_name:*
se_sample_tissue:*&facet=true&facet.limit=3&facet.mincount=1&facet.field=se_sample_tissue&facet.field=se_sample_tissue_name&facet.field=se_sample_tissue_code&facet.field=se_sample_tissue_class&facet.field=se_nuc_acid_type&facet.field=ssam_sample_georegion&start=0&rows=10
I've found a work around in which i can use the template to expand one variable which contains the offending {!lucene q.op=OR}
restTemplate.getForObject(solrServer+"select?{query}" , String.class, requestString );
The problem here is that you're using RestTemplate for something it's not designed for. The sample URL you gave is not a REST-style URL, it's just a mass of query parameters, using encoded characters that you're not going to find in a REST scheme, hence the difficulty with unwanted substitutions.
How about using the overloaded method that accepts a URI?

Resources