I have method in Spring RestController:
#RequestMapping(value = "/mapping", method = { RequestMethod.POST }, consumes = "multipart/form-data")
public ResponseEntity fileQuery(MyRequest request) {}
And a class, MyRequest:
public class MyRequest{
private String url;
private String method;
private String body;
private MultipartFile file;
// I have tried with MultiValueMap and no result
private Map<String,String> formData;
//getters and setters here
}
I want to create a method that accepts multipart / form-data requests with the following known arguments:
URL,
Method,
Body,
File,
Other String:String type arguments.
My solution is not working. Map is null in this case. How can I achieve something like this?
For better understanding I attached a screenshot from postman:
Related
Prompt, I have a problem uploading files to the database. I need to implement a controller that accepts a number of files from 1 to n with additional parameters.
For example:
public class FilesDTO{
private String name;
private String type;
private MultipartFile file;
get / get
}
further implement the controller, for example:
#RequestMapping(value = "file/{id}", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE,
MediaType.MULTIPART_FORM_DATA_VALUE })
public ResponseEntity<?> addFile(#PathVariable Long id, #ModelAttribute List<FilesDTO> filesRequestList) throws IOException {
// log..
}
how to send a request correctly and in what form to this controller?
If you use postman.
maybe I misunderstood how to implement the controller, tell me how best to do
maybe this should be done not through dto
Use array of multipartfile (you can try to use list instead) and send files by form-data
#RequestMapping(value = "file/{id}", method = RequestMethod.POST)
public ResponseEntity<?> addFile(#PathVariable Long id, #RequestBody MultipartFile[] filesRequestList) throws IOException {
// log..
}
in the below example, i am using POST and GET methods. post is to initialize a varibale and GET is to get this varibale.
I use Postman to make the requests.
i am receiving an error
#RequestBody(value = "val") //cant resolve method value
please let me know how to fix the belwo error so i can use post method for initialization and get methdo to retrieve the value
Controller1
#Controller
#RequestMapping("/call1")
public class Call1 {
public String str = "inti";
#RequestMapping(value = "/intiparam1", method = RequestMethod.POST)
public void intiParam1(#RequestBody(value = "val") String val) {
this.str = val;
}
#RequestMapping(value = "/getparam1", method = RequestMethod.GET)
public String getParam1() {
return this.str;
}
}
Create a class Variable and use other code in controller.
class Variable {
String data= 'val';
}
#RequestMapping(value = "/intiparam1", method = RequestMethod.POST)
public void intiParam1(#RequestBody Variable val) {
this.str = val.data;
}
When making a request pass json as {"data":"12345"}
and then use #RequestBody Variable v in code instead of String as it will serve your purpose of default value and will make the code extensible as you can add different properties to the existing variable in future if needed.
When to use #RequestBody?
You can not use value with it. You can use this when you have multiple field entity which you want to perform the operation. Let's say you want to save the user then you may need to create User Model first and use in a controller #RequestBody.
Model:
public class User
{
#Id
private int id;
private String firstname;
private String lastname;
//Getters-Setters, AllArgConstructor-constructor
}
#RequestMapping(value = "/requestBodyExample", method = RequestMethod.POST)
public String intiParam1(#RequestBody User user) {
return user.getFirstname();
}
Quick Start with Spring Boot
In my Spring boot application, I'm sending the POST data with the following (e.g) params:
data: {
'title': 'title',
'tags': [ 'one', 'two' ],
'latitude': 20,
'longitude': 20,
'files': [ ], // this comes from a file input and shall be handled as multipart file
}
In my #Controller I have:
#RequestMapping(
value = "/new/upload", method = RequestMethod.POST,
produces = BaseController.MIME_JSON, consumes = BaseController.MIME_JSON
)
public #ResponseBody HttpResponse performSpotUpload(final SpotDTO spot) {
// ...
}
where SpotDTO is a non-POJO class with all getters and setters.
public class SpotDTO implements DataTransferObject {
#JsonProperty("title")
private String title;
#JsonProperty("tags")
private String[] tags;
#JsonProperty("latitude")
private double latitude;
#JsonProperty("longitude")
private double longitude;
#JsonProperty("files")
private MultipartFile[] multipartFiles;
// all getters and setters
}
Unfortunately all fields are null when I receive the request. Spring is unable to map the parameters to my DTO object.
I guess I'm missing some configuration but I do not know which one.
Other similar questions are resolved by just setting fields accessors on the DTO class. This does not work for me.
Also I have noticed that if I specify each parameter in the method:
#RequestParam("title") final String title,
the method is not even reached by the request. I can see the incoming request in a LoggingInterceptor preHandle method, but nothing in postHandle. A 404 response is sent back.
I think you're just missing the #RequestBody annotation on your parameter:
#RequestMapping(
value = "/new/upload", method = RequestMethod.POST,
produces = BaseController.MIME_JSON, consumes = BaseController.MIME_JSON
)
public #ResponseBody HttpResponse performSpotUpload(#RequestBody final SpotDTO spot) {
// ...
}
You should add #RequestBody annotation before SpotDTO spot. i.e
#RequestBody SpotDTO spot
public #ResponseBody HttpResponse performSpotUpload(#RequestBody SpotDTO spot) {
// ...
}
I want to send an object to the controller that has several lists with files and several fields with plain text.
public class ContributionNew<T extends MovieInfoDTO> {
private List<T> elementsToAdd;
private Map<Long, T> elementsToUpdate;
private Set<Long> idsToDelete;
private Set<String> sources;
private String comment;
}
public class Photo extends MovieInfoDTO {
private MultipartFile photo;
}
#PostMapping(value = "/{id}/contributions/photos")
#ResponseStatus(HttpStatus.CREATED)
public
ResponseEntity<Void> createPhotoContribution(
#ApiParam(value = "The movie ID", required = true)
#PathVariable("id") final Long id,
#ApiParam(value = "The contribution", required = true)
#RequestBody #Valid final ContributionNew<Photo> contribution
) {
I am sending data using postman. However, he throws me away
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundarywY7ByvgonAjDoaCT;charset=UTF-8' not supported
What should I set the Content-type for this controller so that I can send an object that has fields of plain text and lists with files?
If I set the header in the header
Content-type: multipart/form-data; charset=utf-8
it throws me in the console
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
As said dknight #RequestBody means use of JSON or XML data with maps your DTO bean.
In case of MultipartFile you can't use JSON data so you can't use #RequestBody.
Try with #ModelAttribute annotation.
Working sample :
#PostMapping("/promoters")
#Timed
public ResponseEntity<PromoterDTO> createPromoter(#ModelAttribute PromoterDTO promoterDTO) throws URISyntaxException { ... }
With PromoterDTO like this :
public class PromoterDTO implements Serializable {
private Long id;
private String name;
private String address;
private MultipartFile logo;
}
In Postman, you need to set the body to be of type raw, and from the drop down you can select JSON, I had a similar issue, this fixed my issue.
Instead of #RequestBody, use #RequestParam!
use #ModelAttribute instead of #ResponseBody as this takes up data in key value pairs and the later is used for an object like, json.
While hitting the api simply pass the multipart type and json key value pairs of the object. It works fine!
stack overflow question on this
Instead of #RequestBody, use #ModelAttribute like,
#PostMapping(value = "/{id}/contributions/photos")
#ResponseStatus(HttpStatus.CREATED)
public
ResponseEntity<Void> createPhotoContribution(
#ApiParam(value = "The movie ID", required = true)
#PathVariable("id") final Long id,
#ApiParam(value = "The contribution", required = true)
#ModelAttribute #Valid final ContributionNew<Photo> contribution
) {
import org.springframework.web.bind.annotation.ModelAttribute;
Use #ModelAttribute instead of #RequestBody. It worked for me.
produces = { "application/json" } has to written in the controller instead of consumes = { "application/json" }
Hi Folks simply change : #RequestBody to #ModelAttribute
public ResponseEntity<DTO> exemple(#ModelAttribute Dto dto) throws TechnicalException
Happy coding.
Here's a full code sample written in Kotlin using Spring Boot 2.1.7
Example uses a ProfileRepository that would be something you implement of course.
Kotlin is nice, because the data class implements serializable already.
Take note, that you have to use var not val for the model objects properties otherwise the field values will be null in the log message.
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.multipart.MultipartFile
#RestController
class ExampleController(private val myProfileRepository: ProfileRepository) {
#PostMapping("/api/uploadFile")
fun createProvider(#ModelAttribute request: CreateProfileRequest): Provider {
println("received create request with photo: ${request.photo} for the following person ${request.name}")
return myProfileRepository.save(Provider(name = request.name!!))
}
}
data class CreateProfileRequest(
var name: String? = null,
var photo: MultipartFile? = null
)
I've created a POJO like this.
public class Param(){
#NotNull
private Sring paraA;
#NotNull
private Sring paraB;
//Setter and getter
}
And I want to use JSR303 to check it.
#RequestMapping(value = "/test/{paraA}/{paraB}")
#ResponseBody
public BaseJsonRsp test(#PathVariable #Valid Param param) {
//doSomething
}
But this code it doesn't work and I've got following error
HTTP Status 500 - Missing URI template variable 'value' for method parameter of type PatchValue!
Why? How to fix it? Thanks.
Have a look at the Spring Refererence Docs on #PathVariable:
A #PathVariable argument can be of any simple type such as int, long, Date, etc.
If you want to use your Param type as the controller method argument, you won't be able to do so using #PathVariable.
Alternatively, you can map your parameters to individual String variables (using #PathVariable), and then manually construct your Param after that. Note that #PathVariable assumes that the placeholder in your URL is the same as the variable name by default. If your variable name doesn't match, you'd do something like
#RequestMapping(value = "/test/{paraA}/{paraB}")
#ResponseBody
public BaseJsonRsp test(#PathVariable("paraA") String myParam,
#PathVariable("paraB") String otherParam) {
//doSomething
}
You need to explicity set the variable values from the URL into the Param object.
#RequestMapping(value = "/test/{paraA}/{paraB}")
#ResponseBody
public BaseJsonRsp test(#PathVariable("paraA") String paramA, #PathVariable("paraB") String paramB) {
Param param = new Param(paramA, paramB);
}
#PathVariable assumes that the placeholder in your URL is the same as the variable name by default. You need to do this
#RequestMapping(value = "/test/{paraA}/{paraB}")
#ResponseBody
public BaseJsonRsp test(#PathVariable("paraA") String paramA,
#PathVariable("paraB") String otherparam) {
Param param = new Param(paramA, paramB);
}