If I have a method that has like 10 request parameters and I may not always need all of them
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#RequestParam String optionalRequestParam1,
#RequestParam String optionalRequestParam2,
...
#RequestParam String optionalRequestParam10)
So in this header I'd like something that is like
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#RequestParam RequestParamBuilder requestParamBuilder)
and then it would just build an object for me with all valid parameters sent through filled out and the rest being null or something
You can have multiple parameters without defining their names by just using a Map:
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#RequestParam Map<String, Object> params) {
log.info("Params: {}", params.entrySet();
}
How to make the call:
curl --location --request GET 'http://localhost:8080/whatever?integer=45&string="some text"&boolean=true'
Output:
Params: [integer=45, string="some text", boolean=true]
If you wanted the parameters to be passed into an object, you can use a POJO as you were but remove the #RequestParam notation:
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(RequestParamBuilder requestParamBuilder)
Then create a class for RequestParamBuilder. You can mark the fields inside the POJO as #NotNull etc to handle validation and build out the object with only the params that were included in the request, but the POJO must be annotated with #Valid if you wish for spring to validate it this way:
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#Valid RequestParamBuilder requestParamBuilder)
I need to call a 3rd party rest service from my Java application with a formatted URI:
.../rest/v1/search?filter[first_name]=john&filter[last_name]=smith
The reason for this format is, that there are several query fields (20+) and I can't create a #QueryParam parameter for every fieldname.
#POST
#Path("/rest/v1/search")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
Response searchCustomer(#QueryParam("filter") Map<String, String> filter);
My example with a map results in
/rest/v1/search?filter={first_name=John,+last_name=Smith}
How do I achieve the URI form with square brackets?
You can use #Context UriInfo to get a map of all the query params instead of hardcoding every param
example:
#POST
#Path("/rest/v1/search")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response searchCustomer(#Context UriInfo info){
//here are some different ways you can use the uriinfo
MultivaluedMap<String,String> map = info.getQueryParameters();
String firstName = map.getFirst("filter");
String lastName = map.getFirst("lastName");
}
I have service(WildFly 10.1) which looks like that :
#GET
#Path("/retrieve")
public Response getModels(#BeanParam ModelQueryParams queryParams) {
return getModels();
}
With ModelQueryParams:
public class ModelQueryParams{
#QueryParam("offset")
private Long offset;
#QueryParam("limit")
private Long limit;
}
So the user can call endpoint like:
/retrieve?offset=100&limit=4
But how can I validate case when user pass into the query wrong parameter?
/retrieve?offset=100&limit=4&WRONG_PARAMETER=55
Is there the way to validate it somehow?
if you don't have any field or method parameters annotated with #QueryParam, then those extra parameters are not your problem and it's best to deal with only parameters you expect for your resource.
If you still need access to all query parameters, then inject UriInfo with #Context and call it's getQueryParameters() to get a MultivaluedMap of request parameters
I am developing some restful services with Spring. I have trouble with passing/getting string array or large string as parameters to my service controller. My code examples are like below;
Controller:
#RequestMapping(value="/getLocationInformations/{pointList}", method=RequestMethod.GET)
#ResponseBody
public LocationInfoObject getLocationInformations(#PathVariable("pointList") String pointList)
{
// code block
}
Sample point list:
String pointList = "37.0433;35.2663,37.0431;35.2663,37.0429;35.2664,37.0428;35.2664,37.0426;35.2665,37.0424;35.2667,37.0422;35.2669,37.042;35.2671,37.0419;35.2673,37.0417;35.2674,37.0415;35.2674,37.0412;35.2672,37.0408;35.267,37.04;35.2667,37.0396;35.2665,37.0391;35.2663,37.0388;35.2662,37.0384;35.266,37.0381;35.2659,37.0379;35.2658,37.0377;35.2657,37.0404;35.2668,37.0377;35.2656,37.0378;35.2652,37.0378;35.2652,37.0381;35.2646,37.0382;35.264,37.0381;35.2635,37.038;35.263,37.0379;35.2627,37.0378;35.2626,37.0376;35.2626,37.0372;35.2627,37.0367;35.2628,37.0363;35.2628,37.036;35.2629,37.0357;35.2629,37.0356;35.2628,37.0356;35.2628,37.0355;35.2626";
Web service client code:
Map<String, String> vars = new HashMap<String, String>();
vars.put("pointList", pointList);
String apiUrl = "http://api.website.com/service/getLocationInformations/{pointList}";
RestTemplate restTemplate = new RestTemplate();
LocationInfoObject result = restTemplate.getForObject(apiUrl, LocationInfoObject.class, vars);
When I run client side application, it throws a HttpClientErrorException: 400 Bad Request, I think long location information string causes to this problem. So, how can I solve this issue? Or is it possible posting long string value as parameter to web service?
Thx all
List or other type of objects can post with RestTemplate's postForObject method. My solution is like below:
controller:
#RequestMapping(value="/getLocationInformations", method=RequestMethod.POST)
#ResponseBody
public LocationInfoObject getLocationInformations(#RequestBody RequestObject requestObject)
{
// code block
}
Create a request object for posting to service:
public class RequestObject implements Serializable
{
public List<Point> pointList = null;
}
public class Point
{
public Float latitude = null;
public Float longitude = null;
}
Create a response object to get values from service:
public class ResponseObject implements Serializable
{
public Boolean success = false;
public Integer statusCode = null;
public String status = null;
public LocationInfoObject locationInfo = null;
}
Post point list with request object and get response object from service:
String apiUrl = "http://api.website.com/service/getLocationInformations";
RequestObject requestObject = new RequestObject();
// create pointList and add to requestObject
requestObject.setPointList(pointList);
RestTemplate restTemplate = new RestTemplate();
ResponseObject response = restTemplate.postForObject(apiUrl, requestObject, ResponseObject.class);
// response.getSuccess(), response.getStatusCode(), response.getStatus(), response.getLocationInfo() can be used
The question is related to GET resource, not POST. Because of that I think that "accepted answer" is not the correct one.
So for other googlers like me that finds this, Ill add what helps me:
GET resources can receive a string list via #PathVariable or #RequestParam and even correctly bind it to a List<String> if you do pass the list separated by ,.
Your API can be:
#RequestMapping(value="/getLocationInformations/{pointList}", method=RequestMethod.GET)
#ResponseBody
public LocationInfoObject getLocationInformations(#PathVariable("pointList") List<String> pointList) {
// code block
}
And your call would be:
List<String> listOfPoints = ...;
String points = String.join(",", listOfPoints);
String apiUrl = "http://api.website.com/service/getLocationInformations/{pointList}";
LocationInfoObject result = restTemplate.getForObject(apiUrl, LocationInfoObject.class, points);
Note that you must send lists to API using , as separator, otherwise the API cannot recognize it as a list. Also you cannot just add your list directly as a parameter, because depending on how it's mashalled the generated string may not be compatible.
Firstly you've passed a map as parameters but your controller expects these as a path variable. All you need to do is make the 'pointlist' value part of the URL (without the curly bracket placeholders). e.g.:-
http://api.website.com/service/getLocationInformations/pointList
Next you need to ensure you have message converters set up so that your LocationInfoObject is marshalled into an appropriate representation (suggest JSON) and unmarshalled the same way.
For the Rest template:
restTemplate.setMessageConverters(...Google MappingJackson2HttpMessageConverter...);
For the server you just need to add Jackson to the classpath (if you want multiple representations you'd need to configure each one manually - Google will be your friend here aswell.
I'm going over few pieces of code and came across something like this
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({ MediaType.APPLICATION_JSON , MediaType.APPLICATION_XML })
public Response getMedia(
#HeaderParam("X-META") String metaToken,
#QueryParam("provider") String provider, MultivaluedMap<String, String> formContext ,
#Context UriInfo uriInfo) {
Map<String, String> context = APIUtils.buildContext(formContext);
return getMediaInternal(metaToken, provider, context, uriInfo);
}
I know that Annotated vars are injected by jersey but I'm clueless as how the formContext is being injected. It's not annotated. What all values are put in here by jersey ? All the post parameters ? Whats a general rule to deduce whats being populated when not annotated ? Any pointers to reference material or a brief description of whats happening here is helpful
According to the Jersey User Guide, it seems like jersey will inject the MultiValuedMap<> type on a #POST request because form parameters are part of the message entity. This is the example:
Example 3.13. Obtaining general map of form parameters
#POST
#Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}