Why can #requestparam get file upload data in SpringMVC? - spring

#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

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.

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) {
...
}

Multipartfile parameter order precedence causing error

Basically, I am sending two parameters , one a String and the other a file to my controller in Spring Boot . In the action, when I receive the file first and then the String next, like so
#RequestMapping(value = "/updatemedia", method = RequestMethod.PATCH,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<String> updateMedia(#RequestParam(value ="file") MultipartFile fileToUpload , #RequestParam(value = "keyId") String keyId )
everything is fine and I am able to access the String and the file correctly.
But when I change the order of the parameters , like so
#RequestMapping(value = "/updatemedia", method = RequestMethod.PATCH,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<String> updateMedia( #RequestParam(value = "keyId") String keyId , #RequestParam(value ="file") MultipartFile fileToUpload )
and send the params through Postman, I am hitting the below error
I researched a lot but am not able to understand this behaviour.
Because you send keyId in body while it's declared as #RequestParam
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html .
#RequestParam has nothing to deal with request body, it's passed in request url.
What about your example, the first approach works, because your method expects one #RequestPart, the others are ignored.

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.

Invoking service with #RequestParam and #RequestBody using postman client

Was trying to invoke the service
http://IP:8080/PQRS/LMN/XYZ/runTest/scheduledautomation/1/XYZ
with below JSON String
[ {"paramName":"TEST_TARGET_IDENTIFIER","paramValue":"ETest"},{"paramName":"TEST_SOURCE_ENTRY_IDENTIFIER","paramValue":"com.pack.etest"}]
#ResponseStatus(value = HttpStatus.NO_CONTENT)
#RequestMapping(value = "/runTest/scheduledautomation/{runId}/{testEngine}", method = RequestMethod.POST)
public void runScheduledAutomatedTest(#RequestParam String cronExpresssion,
#RequestParam(required = false) #DateTimeFormat(iso = ISO.DATE_TIME) LocalDateTime endTime,
#PathVariable Integer runId,
#PathVariable TestEngine testEngine,
#RequestBody List<TestEngineParam> testEngineParams) throws Exception { //Some Code }
Response :
Required String parameter 'cronExpresssion' is not present
how to invoke mixed #RequestParam and #RequestBody services on postman client ?
I fear you want a little bit too much: RequestParam, RequestBody AND the whole thing as a REST query. At least two of the three things are mutually exclusive.
I think you could even get Postmaster to do this by modifying the called URL to:
http://IP:8080/PQRS/LMN/XYZ/runTest/scheduledautomation/1/XYZ?cronExpression=your-expression
Of course this would ruin your REST interface, but as I said: your handler method is a little bit "over-ambitious".

Resources