How to use #RequestParam Map<String,String> properly in Swagger UI? - spring-boot

I'm trying to use springfox-swagger-ui for this request:
#GetMapping(value = "")
public String Hello( #RequestParam Map<String, String> params )
When I open Swagger UI and try the request, it shows the parameters like this:
and the request query string will be like:
?params%5BadditionalProp1%5D=string&params%5BadditionalProp2%5D=string&params%5BadditionalProp3%5D=string
I don't want the word "params" to be included in the query string, I want the parameters be like ?additionalProp1=string ....
How can I achieve this?

Add the following #Parameter annotation to your parameter (line breaks added for readability). The style and explode attributes specify that the map parameter should be serialized as ?key1=value1&key2=value2&... without including the parameter name ("params").
#GetMapping(value = "")
public String Hello(
#Parameter(name = "params",
in = ParameterIn.QUERY,
required = true,
schema = #Schema(type = "object", additionalProperties = true),
style = ParameterStyle.FORM,
explode = Explode.TRUE)
#RequestParam Map<String, String> params
)

Related

Spring Boot Controller map request params, path variables and body to a custom object

I have a pretty convoluted method in my controller, with various request params, headers and path variables:
public CompletableFuture<ResponseEntity<?>> retrieveAndCache(
#PathVariable(name = "collection") String collection,
#PathVariable(name = "handler") String handler,
#RequestBody(required = false) JsonNode reqBody,
#RequestHeader(name = "X-Server", required = false) String _server,
#RequestHeader(name = "X-Host", required = false) String host,
#RequestHeader(name = "X-ClearCache", required = false, defaultValue = "false") Boolean clearCache,
#RequestHeader(name = "X-ReturnImmediately", required = false, defaultValue = "false") Boolean returnImmediately,
#RequestHeader(name = "X-JustEcho", required = false, defaultValue = "false") Boolean justEcho,
#RequestParam Map<String, String> requestParams,
#RequestParam(name = "excludedServers", required = false) String... excludedServers)
Looking at it makes me dizzy.
Is it possible to map all of this to a custom object like:
public CompletableFuture<ResponseEntity<?>> retrieveAndCache(Parameters p)...
I know we can use custom converters in spring, but afaik they work to convert a single header or single variable to an object. This way I thought it may be more readable, plus maybe I can move some methods (validation etc.) into Parameters class.

Why can #requestparam get file upload data in SpringMVC?

#requestparam functions like request.getquerystring (). Why does she receive a multipart/form-data type contentType when #requestbody cannot?Please tell me why?
#PostMapping(value = "/uploadFileByUserTrainId", consumes = "multipart/form-data")
#Student({Student.Authority.A, Student.Authority.B, Student.Authority.C})
public WebMessage uploadFileByUserTrainId(
#RequestParam(value = "document", required = false) MultipartFile multipartFile,
#RequestParam(value = "documetnRe", required = false) MultipartFile multipartFileRe,
#RequestParam("id") long id,
#RequestParam(value = "documentFileType", required = false) String fileType,
#RequestParam(value = "documentFileReType", required = false) String fileReType,
HttpServletRequest httpServletRequest) {
// todo
}
It is nothing wrong using #RequestParam with Multipart file.
#RequestParam annotation can also be used to associate the part of a "multipart/form-data" request with a method argument supporting the same method argument types. The main difference is that when the method argument is not a String, #RequestParam relies on type conversion via a registered Converter or PropertyEditor

How can I validate the value of #RequestQuery

I am trying to validate the value of the query param below after the equals sign in the REST URI, does anyone know how to do it with Spring 4.1 please?
I want to validate in the method parameters that 'drive' is the passed param but all I can validate is the operation part
I would like to do something like #RequestParam(value = "drive")
localhost/test?operation=drive
#RequestMapping(value = "/test", method = RequestMethod.PUT)
public ResponseEntity<Void> operation(#RequestParam(value = "operation", required = true) String operation)
`
You could use Bean Validation annotations.
If you want to check if the value is allowed, you can use #Pattern with a regular expression:
#Pattern(regexp = "value1|value2|value3", flags = Pattern.Flag.CASE_INSENSITIVE)
#RequestMapping(value = "/test", method = RequestMethod.PUT)
public ResponseEntity<Void> operation(
#RequestParam(value = "operation", required = true)
#Pattern(regexp = "value1|value2|value3", flags = Pattern.Flag.CASE_INSENSITIVE)
String operation) {
...
}

Spring MVC forward appending request parameter values comma separated when we have same parameter name for topRequest and forward request

Spring MVC forward appending request parameter values comma separated when we have same parameter name for topRequest and forward request
#RequestMapping(path = "/details")
public ModelAndView details(#ModelAttribute final DetailsForm detailsForm){
//DetailsForm contain a parameter called destinationId with value 1234
final ModelAndView mav = new ModelAndView();
//Some logic to get targeted destinationId (7890) using destinationId (1234) from detailForm
mav.setViewName("forward:/search?destinationId=7890");
return mav;
}
#RequestMapping(path = "/search")
public ModelAndView details(#ModelAttribute final SearchForm searchForm){
//Here I tried to get destinationId from model-attribute searchForm
final Integer destinationId = searchForm.getDestinationId();
//Then it returned me 1234,7890
}
Can someone please help me out how to resolve this. I want to get only 7890.
I am interested in the answer also. I also hit this problem hacked it by adding a method:
private String getLastPartFromFormValue(final String value) {
if (value == null)
return null;
String[] parts = value.split(",");
return parts[parts.length -1];
}
Just for sake of knowledge.
If you have a method, and you have a query param named thing and have an object annotated with #ModelAttribute and, in that object you have a field with the same name of your query param, you can expect that behavior.
For example:
#PostMapping(value = "/my-awesome-path")
public String myAwesomeMethod(
#RequestParam(name = "token", required = false) final String token,
#ModelAttribute("formData") final MyFormData formData) {
//class fields and members...
And, in the MyFormData you have this:
public class MyFormData{
private String token;
//other fields, getters and setters...
You will receive the query param token with the value duplicated and comma separated as well as in the MyFormData object.
The alternative is check the casuistic and change the parameter name or redesign if it's necessary.
In the example the query param name is changed like this:
#PostMapping(value = "/my-awesome-path")
public String myAwesomeMethod(
#RequestParam(name = "custom-token", required = false) final String customToken,
#ModelAttribute("formData") final MyFormData formData) {
//class fields and members...
And the values are not more duplicated nor comma separated.
Cheers.

Spring rest: Consuming x-www-form-urlencoded associative array

I am trying to PUT an associative array:
name[en_US]:Administrator
name[es_ES]:Administrador
name[no_NO]:Administrator
How do I configure the rest controller method to consume this data?
I have tried the following without any luck:
#RequestMapping(value = "/{userGroupId}", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.OK)
public void updateUserGroup( #PathVariable Long userGroupId,
#RequestParam(value = "name", required = false) Map<String, String> name)
The data not passed as JSON, but as x-www-form-urlencoded.
EDIT 1:
If I leave out "(value = "name", required = false) from the #RequestParam I can get all request parameters as key value pairs, but isn't there a way to bind it to a Map? If not I would have to do some string manipulation to create that map manually.

Resources