Multipart file and number of form parameters are not converting as ModelAttribute in Rest controller (Spring 4) - spring

I am using Chrome postman client for rest calls, here I am sending 15 form parameters like fname, last name.. so on, and also two files as file type.
I am submitting my request POST method, body type is form data selected and content type header is empty.
In the server side, I am consume this as method
#RequestMapping(value = "/create"
method = RequestMethod.POST,
consumes = {"multipart/form-data"},
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<ResponseTO> create( #ModelAttribute RequestTO updateTripRequestTO, HttpServletRequest request);
public class RequestTO implements Serializable {
private UUID id private Date createdate;
private String createdby;
private String updatedby;
private Date updateddate;
private String visibility;
private String name;
private MultipartFile tripimage;
public class RequestTO implements Serializable {
private UUID id private Date createdate;
private String createdby;
private String updatedby;
private Date updateddate;
private String visibility;
private String name;
private MultipartFile tripimage;
( and Set and get Methods)
When I debug the TO, its giving comma separated values in TO.
If I give fname is "Test", lname "Ltest" in the postman, when I debug the TO its coming fname as "Test,Test" and lname as "Ltest,Ltest " for all form fields. Can some suggest me why like this and any solution please.

Related

Multiple Use of validations in Spring Boot

I have an API with validation on it.
public class ModelVo {
#NotBlank(message = "...")
private String name;
#Pattern(regex="...", message = "...")
private String lastName;
...
}
I use of it
#PostMapping("/path1")
public ResponseEntity<RestResponse<Object>> create(#Valid #RequestBody ModelVo modelvo){
Now I want use of this validation for other method( for instance update API) again but I don't like #Pattern annotation on lastName fild work for second method. Is it possible?
Assuming that for create() you want to validate lastName with #Pattern but for update() you don't want to validate lastName you can achieve this with validation groups.
Your Controller:
#PostMapping("/path1")
public ResponseEntity<RestResponse<Object>> create(#Validated #RequestBody
ModelVo modelvo){
#PutMapping("/path1")
public ResponseEntity<RestResponse<Object>> update(#Validated(BasicInfo.class) #RequestBody
ModelVo modelvo){
Your Model class:
public class ModelVo {
#NotBlank(message = "...", groups = BasicInfo.class)
private String name;
#Pattern(regex="...", message = "...")
private String lastName;
}
You also need to create the BasicInfo class but that has nothing special.
You may get more information from the following links:
https://www.baeldung.com/spring-valid-vs-validated
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/annotation/Validated.html

Spring Framework Responses from POST

What is the standard object design for accepting a POST request from a client, saving the record to the database, and then returning a response back to the client? I'm working with the Spring framework.
Should I be sending back the entity and hiding properties that aren't necessary for the response?
#RestController
public class SomeController {
private final SomeService service;
#PostMapping(value = "/post/new", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomeEntity> post(#RequestBody final SomeEntity someEntity) {
SomeEntity savedEntity = service.save(someEntity);
return ResponseEntity.ok(savedEntity);
}
}
#Entity
#Table(name = "posts")
public class SomeEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "title")
private String title;
#Column(name = "body")
#JsonIgnore
private String body;
#JsonIgnore
#Column(name = "deleted_ind")
private boolean deleted;
#JsonIgnore
#Column(name = "author")
private String author;
#Column(name = "created_at")
private LocalDateTime createdAt;
}
or would I accept some sort of POST request object that I convert to an entity, then re-assemble the entity into a response?
#JsonIgnoreProperties(ignoreUnknown = true)
public class SomePostRequestResource {
private String title;
private String body;
private String createdAt;
}
#RequiredArgsConstructor
#RestController
public class SomeController {
private final SomeService service;
private final SomeResourceAssembler resourceAssembler;
#PostMapping(value = "/post/new", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomePostRequestResource> post(
#RequestBody final SomePostRequestResource someResource
) {
SomeEntity savedEntity = service.convertToEntityAndSave(someResource);
SomePostRequestResource response = resourceAssembler.toResource(savedEntity);
return ResponseEntity.ok(response);
}
}
But then maybe I only want to send back the createdAt, would I hide the other properties in the SomePostRequestResource, or do I need another object to represent the response, which only has the property I want to send back?
I would also appreciate any book or article suggestions related to desigining objects for use with a RESTful API. I have seen articles concerning how to design and name the endpoints, but not so many concerning how to design the objects on the backend.
I would recommend you create a DTO class for the incoming/outgoing data containing the filed that are set/viewable by the client like:
public class SomeEntityIncomingDto {
private String title;
....
}
public class SomeEntityOutgoingDto {
private Long id;
private String title;
....
}
On the other hand, You won't need to map your persistence entities to DTOs and vice versa manually, you can use a library like ModelMapper or MapStruct that handles the conversion automatically.

How to create REST endpoint service consume multipart using Spring 4.x?

I am trying to create a REST service that consumes the "multipart/form-data" with text and attachment objects. For files i can use "org.springframework.web.multipart.MultipartFile", but how do i specify the service method for Text objects?
Below is the expected client call to service.
create Rest endpoint by using this way
public void sendEmail(#RequestParam String to,#RequestParam String from,#RequestParam String cc,#RequestParam String body, #RequestParam(required = false)MultipartFile[] file){
}
or
create pojo class for strings
public class Email{
private String from;
private String to;
private String cc;
private String body;
// getters and setters
}
//email should be json string
public void sendEmail(#RequestParam String email,#RequestParam(required = false) MultipartFile[] file){
ObjectMapper mapper=new ObjectMapper();
Email email_pojo=mapper.readValue(email,Email.class);
}
Just create the controller as specified below:
#RequestMapping(value = "/uploadFiles", headers = ("content-type=multipart/*"), method = RequestMethod.POST)
public AppDTO uploadFile(UploadFiles uploadFiles, HttpServletRequest request) {
Now create a pojo class for what ever things you need to submit along with a multipartfile member where the file will bind to. refer below code for pojo
class UploadFiles
{
private String cc;
private String to;
private String from;
private MultipartFile attachment;
//create getters and setters
}
MultipartFile here used is provided by spring
import org.springframework.web.multipart.MultipartFile;
If you have more than one attachment you can use MultipartFile[] in POJO

Spring Request Mapping post vs put, same method, same logic, but

I have a 2 method:
first one create product:
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> create(#Validated ProductDTO productDTO){
productService.addProduct(productDTO);
return new ResponseEntity<>("Maxsulot ro'yhatga qo'shildi", HttpStatus.OK);
}
another one update product:
#RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<?> update(#Validated ProductDTO productDTO){
productService.update(productDTO);
return new ResponseEntity<>("Maxsulot ma'lumotlari yangilandi", HttpStatus.OK);
}
Now, I am surprized that, if I sent same data post method works fine(screen1), but put(screen2) method return validation error.
screen1(post)
screen2(put)
What the problem is?
MyDTO class:
public class ProductDTO {
private Long id;
private MultipartFile file;
#NotNull
#Size(min = 2, max = 50)
private String productName;
#NotNull
private Long productPrice;
private String productInfo;
#NotNull
private Long categoryId;
private String unitOfMeasurement;
// getters and setters
}
I can see you have #Validated that should validate your request body according to JSR-303.
Seems like it is not consistent when you POST and PUT. It validates/not validating and return an error because your body does not match the validation rules you placed on ProductDTO.
In all the docs I saw you should do something like #Valid #RequestBody instead of just putting #Validated.
Try to change it to the above and see if it now work more consistently.

javax.validation getting ignore from jersey

I am trying to use Jersey to get JSON request from the user to create vendor
#POST
#Produces({APPLICATION_JSON})
#Consumes({APPLICATION_JSON})
#Path("create")
public Response create(VendorTO vendorTO) throws Exception {
But before it converts in vendorTO object I want to validate it with javax.validation
I have added constraints in my pojo like this
{#JsonSerialize(include=Inclusion.NON_NULL)
public class VendorTO {
#NotNull
private Integer userId;
#Size(min = 2)
private String vendorName;
private String address1;
private String address2;
private String city;
private String state;
private String country;
private String email;
private String phone;
}
but it doesnt seems to be working. Can anyone help ?
You need to tell the framework that the parameter should be #Validated:
#POST
#Produces({APPLICATION_JSON})
#Consumes({APPLICATION_JSON})
#Path("create")
public Response create(#Valid VendorTO vendorTO) {
// ...
}
At this point, it appears Jersey does not support JSR 303 natively. You might have to write some ResourceFilters and handle the validation manually.

Resources