how to capture some parameters using #RequestParam using spring mvc? - spring

Suppose a hyperlink is clicked and an url is fired with the following parameter list myparam1=myValue1&myparam2=myValue2&myparam3=myValue3 . Now how can I capture some of the parameters using #RequestParam in spring mvc?
My requirement is I have to capture some of the params and build the request to server. can I make all the request params as optional and used when required?
Suppose I want to use first two params and want to ignore the third.
For eg. http://localhost:8080/api?myparam1=myValue1&myparam2=myValue2 and just not giving 3rd parameter in request.
In the next scenario, I want to use second and third and want to ignore the first parameter.
For eg. http://localhost:8080/api?myparam2=myValue2&myparam3=myValue3 and just not giving 1st parameter in request.
In another scenario, I don't want to use any of the request param.
For eg. http://localhost:8080/api and just not giving any parameters in request.
is there any way I could achieve this? Please help...!

You can capture all the params in a Map (the key is the name of the param) like this :
public void requestAllParams(#RequestParam Map<String, String> params)
You can also capture optional param using Optional like this :
public void requestParamOptional(#RequestParam(required=false) Optional<String> param)

A parameter with #RequestParam is by default required. It can be marked as not required:
#GetMapping
public ResponseEntity<Object> aMapping(#RequestParam String myparam1, #RequestParam String myparam2, #RequestParam(required = false) String myparam3) {
// response
}

Related

Spring throw Bad Request if the request param not available in Controller method

I want to restrict the list of allowed request parameters in my controller, so that if I get a request with an undefined parameter in the controller, it should return a bad request, but it returns 200 OK.
I think that this one should be fixed on the framework level, but not in the controller layer.
I am confused about it, and could not find anything on the internet
For e.g I have the following controller definition:
#GetMapping("/Client")
public ResponseEntity<List<Client>> getAllClients(HttpServletRequest httpServletRequest,
#RequestParam(value = McsConstants.PAGE_HEADER, required = false) Integer page,
#RequestParam(value = McsConstants.SIZE_HEADER, required = false) Integer size) {...}
And the valid request would be
GET .../Client
GET .../Client?page=1
GET .../Client?size=10
GET .../Client?page=1&size=10
How can I validate the case when I have an undefined request param like below?
GET .../Client?someUndefinedParam=1
Let me know please for any ideas or links
Thanks!
One way to handle this can be using #RequestParam annotation on a Map or MultiValueMap argument.
The map is populated with all the request parameters, therein you can write your logic to validate and reject unidentified query params.
EDIT: Following is an example for the same-
#RequestMapping(value = "/test", method = RequestMethod.GET)
public void testMethod(#RequestParam Map<String, String> allRequestParams) {
if (!isValidParams(allRequestParams)) {
// isValidParams() will validate the map with a reference map containing all the expected params
// throw BadRequestException here
}
}
Hope this helps!
let me share my knowledge it may helpful for some other scenarios
If the requestparam and variable is same name you no need to mention the value #RequestParam .
below i have mentioned with code example. Please share ur feedback
#GetMapping("/Client")
public ResponseEntity<List<Client>> getAllClients(HttpServletRequest httpServletRequest,
#RequestParam <Optional>Integer page,
#RequestParam <Optional>Integer size) {
//you can do ur logics
}

REST API design - optional request parameters

I've written this request mapping to access a ticket by it's id:
#GetMapping(path = "/tickets/{ticketId}")
#ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<List<TicketResponse>> getTicketsById(#PathVariable("ticketId") final Long ticketId
I'm planning to add multiple query parameters to support filtering such as ticketType, ticketStatus. REST API users should have options to filter on any or all of the query parameters.
What are the REST API design principles to achieve this ? Should I add new request parameters to support the filtering like below ? :
#GetMapping(path = "/tickets/{ticketId}")
#ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<List<TicketResponse>> getTicketsById(#PathVariable("ticketId") final Long ticketId, #RequestParam("ticketType") final String ticketType, #RequestParam("ticketStatus") final String ticketStatus)
Is there a Spring design pattern for this scenario ? The Java builder pattern could be used where parameter an attribute of a QueryParameter object ?
You basically have two options:
Either you put all your RequestParams as method parameters, but with required=false, like #AmitKumar wrote. Example: #RequestParam(name="ticketType", required = false) String ticketType
Put all these parameters into a, let's say FilterDTO and have that as a parameter (FilterDTO filter). Spring will make sure to populate its fields with your RequestParams . Just put your ticketType and other parameters into the DTO as fields, and they will be optional. Example: public ResponseEntity<List<TicketResponse>> getTicketsById(#PathVariable("ticketId") ong ticketId, FilterDto filter){}
If you want to make parameter as an optional. you need to add required=false.
public ResponseEntity<List<TicketResponse>> getTicketsById(#PathVariable("ticketId") final Long ticketId, #RequestParam(name="ticketType", required=false) final String ticketType, #RequestParam(name="ticketStatus",required=false) final String ticketStatus)

Issue with Spring Rest #RequestMapping when negating params

I have two spring controller methods :
#RequestMapping(value="/requestotp",method = RequestMethod.POST,params = "!applicationId") //new customer
public OTPResponseDTO requestOTP( #RequestBody CustomerDTO customerDTO){
return customerService.requestOTP(customerDTO);
}
#RequestMapping(value="/requestotp",method = RequestMethod.POST,params = {"idNumber","applicationId"}) //existing customer
public String requestOTP( #RequestParam(value="idNumber") String idNumber , #RequestParam(value="applicationId") String applicationId) {
return customerService.requestOTP(idNumber, applicationId);
}
using "!applicationId" , I am expecting that when I call the url with applicationId parameter there that the second method will be called , but actually when I pass a request like this :
{"idNumber":"345","applicationId":"64536"}
The first method gets called
This is the part of the params paremeters documentation that I rely on :
Finally, "!myParam" style expressions indicate that the specified
parameter is not supposed to be present in the request.
Can't you just simply delete first request params?
#RequestMapping(value="/requestotp",method = RequestMethod.POST) //new customer
public OTPResponseDTO requestOTP( #RequestBody CustomerDTO customerDTO){
return customerService.requestOTP(customerDTO);
}
The issue actually wasn't with negating the parameter, the issue was that I was sending {"idNumber":"345","applicationId":"64536"} in the POST body and I was expecting the variables to be mapped to the method parameters annotated with #RequestParam ... this is not correct ... #RequestParam only map URL parameters .... so the controller was trying to find the best match so it was using the first method as it contained #RequestBody

#RequestHeader mapped value contains header twice

We are facing a super strange problem: in our endpoint:
#PostMapping(value = "/send_event_to_payment_process")
#Async
public void sendEvent(#Valid #RequestBody final SendEventRequestDto dto, #RequestHeader(value = TENANT) String foo) {
the mapped #RequestHeader variable foo contains the vaue twice joined with a ',' ("test,test"). If we read the header programmatically using the request context:
public void sendEvent(#Valid #RequestBody final SendEventRequestDto dto, #Context final HttpServletRequest request) {
final String tenant = request.getHeader(TENANT);
we receive the proper value (only once: "test").
Any clues what the problem might be?!
Thank you!
You are comparing different things.
The HttpServletRequest.getHeader method always returns a single value, even if there are multiple values for the header. It will return the first (see the javadoc of the method).
Spring uses the HttpServletRequest::getHeaders method to get all the values. Which retrieves all header values and, depending on the value, return the String[] or creates a single concatenated String.
To compare the same things you also should use the getHeaders method and then you will have the same result. Which means your request contains 2 header values for the given header.

Spring MVC form parameters and query parameters

In Spring 4 MVC, I'm trying to figure out how to accept both form parameters and query parameters posted to my rest endpoint and also trigger validation, but am struggling to figure out how to get this to work.
Ideally, my controller would look something like this:
#RequestMapping(value="/someurl", method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public someMethod(#Valid #ModelAttribute Order order, #RequestParam String parm1, #RequestParam String parm2) {
}
I need to post the form parameters to the controller URL along with some query parameters and a Content-Type = application/x-www-form-urlencoded
Any ideas on how to get this to work?
Suppose the Order class has the order_id and order_x attributes, with the following endpoint:
#RequestMapping(value="/someurl", method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public someMethod(#Valid #ModelAttribute Order order, BindingResult validation, #RequestParam String parm1, #RequestParam String parm2) {
}
If a client sends a POST request with application/x-www-form-urlencoded content type with following request body:
order_id=1&order_x=something&parm1=foo&parm2=bar
then an Order instance with {order_id=1, order_x=something} will be instantiated. In addition, parm1 and parm2 will contain foo and bar, respectively. BindingResult contains validation results for a preceding command or form object (the immediately preceding method argument).
See this discussion about Query Parameters in POST requests. Also Forms Spec is a good reference.

Resources