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.
Related
My environment
springboot:2.6.4
springdoc-openapi-ui:1.6.6
Probrem
I want to create an API definition to receive requests in x-www-form-urlencoded format.
Using #RequestBody will create a swagger-ui display with no Parameter notation, just the body. However, when receiving a request in x-www-form-urlencoded format, it is necessary to receive it with #RequestParam, and if this is done, the swagger-ui display is created as a query parameter.
#PostMapping(value = "/v1/hoge")
public ResponseEntity<SampleResponse> postProc(
#RequestParam("param1") int param1,
#RequestParam("param2") String param2,
#RequestParam("param3") String param3,
HttpServletRequest request) {
・・・
}
swagger-image
However, since there is no actual query parameter, I do not want to display the Parameter in the same way as when receiving a request with #RequestBody.
The display without parameters is correct, as in POST /user in the following link.
http://158.101.191.70:8081/swagger-ui/4.5.0/index.html#/user/createUser
Is there a solution to this problem?
I might have a solution for you:
#PostMapping(value = "/v1/hoge", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<SampleResponse> postProc(
#RequestPart("param1") int param1,
#RequestPart("param2") String param2,
#RequestPart("param3") String param3,
HttpServletRequest request) {
・・・
}
In a perfect world, you could stick to the #RequestParam but I believe there is currently a bug with springdoc that make it impossible.
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
}
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
}
how to get both values #RequestBody and #RequestParam together??
below the code:
#RequestMapping(value = "/sign-up", method = RequestMethod.POST)
public ResponseEntity<?> addUser(#RequestBody User user,#RequestParam("location") String location,#RequestParam("deviceid") String deviceid) {
System.out.println(location);
System.out.println(deviceid);
it is possible?
for #RequestParam Content-Type application/x-www-form-urlencoded
and for #RequestBody Content-type application/json
i want both value location and deviceid if there is any other way?
#PathVariable is to obtain some placeholder from the uri (Spring
call it an URI Template) — see Spring Reference Chapter 16.3.2.2 URI
Template Patterns
#RequestParam is to obtain an parameter — see Spring Reference Chapter 16.3.3.3 Binding request parameters to method parameters with #RequestParam
If URL http://localhost:8080/MyApp/user/1234/invoices?date=12-05-2013 gets the invoices for user 1234 on December 5th, 2013, the controller method would look like:
#RequestMapping(value="/user/{userId}/invoices", method = RequestMethod.GET)
public List<Invoice> listUsersInvoices(
#PathVariable("userId") int user,
#RequestParam(value = "date", required = false) Date dateOrNull) {
...
}
Also, request parameters can be optional, but path variables cannot--if they were, it would change the URL path hierarchy and introduce request mapping conflicts. For example, would /user/invoices provide the invoices for user null or details about a user with ID "invoices"
My Spring REST API is decorated as follows:
In below, I am confused weather, parameters such as list, operation need to be part of Url as query string or do they need to be part of Request Body as form data (Url encoded).
There are situations where I am sending these parameters in query string and it works fine. But couple of my api's are not working properly on production and they work only if I send the data in request body as Url encoded. Can anyone help me explain this behaviour ?
#RequestMapping(value = "/bulkupdate/{companyId}", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<String> bulkupdateArticle(#RequestParam("list") String documentIdList,
#PathVariable("companyId") String companyId, #RequestParam("operation") String operation){
try{
Looking at the resource I find that it could be better designed in a more REST-ful fashion. I don't like to see POSTed data in the reside in the url.
Next to becoming more Rest-ful it would also make live for you much easier.
I would create a Data Transfer Object and pass it as the body of the POST request to your resource/spring controller.
Going from your data:
public class ArticleToUpdate {
private String list; // list of what ? Maybe design it like List<String> somethingMoreMeaningFull
private String operation;
// .. getters
}
public ResponseEntity<String> bulkupdateArticle(#RequestBody ArticleToUpdate articleToUpdate) {
// .. do whatever you need with the posted data
Now you can post a JSON or XML document in the body which will probably life much easier.
Additionally you could also add validation on the posted data through #Valid support now.