Postman: Create complex MULTIPART_FORM_DATA request - spring

I need to create a request using postman. The spring boot endpoint is:
#RequestMapping(
value = "/group",
method = RequestMethod.POST,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public ResponseEntity<String> group(
#RequestPart("items") List<ItemType> items,
#RequestPart("group") GroupType group);
where:
public class ItemType {
private String description;
private String security;
private Date bestdate;
private MultipartFile content;
}
public class GroupType {
private String description;
private String security;
private String metadata;
}
As you can see, ItemType contains an MultiPartFile.
I mean, what do I need to write on "items" and "group" parts:

There is a option in Postman to provide the form data, where you can pass both the text and file.
The json part of the body should also be set as "File" rather then "Text", and put your json data in a json file for example "a.json".
Check below , Hope this will help.

Related

How to send model attribute to spring controller using Postman

I want to test my controller using postman but don't know how to send a model attribute using postman.
I tried to send all attributes in row json fornamt and x-www-form-urlencoded in body but it is not working for me, I didn't understand where i'm getting wrong
My controller class looks like :
#RestController
public class DemoController {
#Autowired
private DemoService demoService;
#RequestMapping(value = "/userDetail", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON })
public String testme(
ModelMap model,
#ModelAttribute("inputParameter") InputParameter inputParameter,
BindingResult result) {
return demoService.getDetail(inputParameter);
}
}
Model Class :
public class InputParameter {
private String id;
private String name;
private String number;
private String address;
private String pass;
}

How use Valid and NotBlank for swagger object?

In my project I have a controller and dto which the same controller accepts. It was decided to use swagger-codegen as more appropriate. And then there were questions with validation, which I applied to my dto, but I can't apply to the object that swagger creates.
#Data
public class MyCustomDto {
#NotBlank(message = ".... ")
private String a;
#NotBlank(message = ".... ")
private String b;
}
Using MyCustomDto with #Valid annotation in the controller, I could validate the data and the request would not work if one of these fields is empty.
#javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.JavaClientCodegen", date = "2021-05-23T15:23:40.775555+04:00[Asia/Baku]")
public class MySwaggerDto{
#JsonProperty("a")
private String a= null;
#JsonProperty("b")
private String b= null;
}
my yaml file part for those fields
a:
type: string
description: sfdsfsdfdsf
example: hh
b:
type: string
description: asdsadas
example: kjhgjgj
Can swaggerdto be made to work similarly to custom dto? I have a #ControllerAdvice class with a handleMethodArgumentNotValid method that I use to respond to a request with incorrect input parameters.
#ControllerAdvice
#Slf4j
public class MyExceptionsHandler extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
//my some code
return ResponseEntityBuilder.build(err);
}
}

Springboot restinvokation with an non existing field

Suppose I have a model UserInfo which I used in my post service as #RequestBody and when I invoke the service with UserInfo payload it is working.
Class UserInfo {
Private String firstName;
Private String lastName
}
How do I restrict the post call if someone sends some additional fields in the payload which is not exists in UserInfo model (e.g. age)?
In this case, are you using this?
#Autowired
ServiceInterface serviceInterface;
#PostMapping(value = "/userSave")
#RequestBody
public RequestEntity saveUserInfo(**#ModelAttribute** UserInfo userInfo){
return new ResponseEntity(serviceInterface.saveUser(userInfo),HttpStatus.OK);
}
when we are using #ModelAttribute annotation this gets only attribute values in UeserInfo DTO (DATA TRANSFER OBJECT). Also, you can use validations in the UserInfo DTO Class. Like
Class UserInfo {
#NotNull
private String firstName;
#NotNull
private String lastName;
}
But However when using #RequestBody whatever user sends additional data that save only UserInfo Attribute data.
Try to add a property to application.properties:
spring.jackson.deserialization.fail-on-unknown-properties=true
Or create a component:
#Component
public class Jackson2ObjectMapperBuilderCustomizerImpl implements Jackson2ObjectMapperBuilderCustomizer {
#Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.featuresToEnable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
}

Spring Boot - How can I pass custom values in HTTP Post api?

I'm new with Spring Boot and I have difficult to understand how can I pass data. For example:
I want pass those data to my server:
{
"code", 1,
"name": "C01"
}
So I have create always a custom Object with code and name as attributes to have this http post api?
#RequestMapping(value = "/new/", method = RequestMethod.POST)
public ResponseEntity<?> createOrder(#RequestBody CustomObject customObject){
...
}
Another solution I see that can be this but I can't pass numbers (int code), right?
#RequestMapping(value = "/new/{code}/{name}", method = RequestMethod.POST)
public ResponseEntity<?> createOrder(#PathVariable("code") int code, #PathVariable("name") String name) {
...
}
Kind regards :)
You can pass code and name as PathVariables just like in your example:
#RequestMapping(value = "/new/{code}/{name}")
public ResponseEntity<?> createOrder(#PathVariable("code") int code, #PathVariable("name") String name) {
...
}
A PathVariable can be an int or a String or a long or a Date, according to the docs:
A #PathVariable argument can be of any simple type such as int, long, Date, etc. Spring automatically converts to the appropriate type or throws a TypeMismatchException if it fails to do so.
You could also define a PathVariable of type Map<String, Object> like this:
#RequestMapping(value = "/new/{code}/{name}")
public ResponseEntity<?> createOrder(#PathVariable("map") Map<String, Object> map) {
Integer code = (Integer) map.get("code");
String name = (String) map.get("name");
...
}
You could even use #RequestParam and supply the data in the form of URL query parameters.
So, there are numerous ways in which data can be passed to a Spring MVC controller (more details in the docs) but I think the convention for posting complex data (by "complex" I mean more than a single piece of state) is to define a request body which contains a serialised form of that complex state i.e. what you showed in the first example in your queston:
#RequestMapping(value = "/new/", method = RequestMethod.POST)
public ResponseEntity<?> createOrder(#RequestBody CustomObject customObject){
...
}
If this question is about RESTful best practice, since you are developing webservice for creating an Order object, this is how I would design it
Order.java
public class Order {
private Integer code;
private String name;
public Integer getCode() {
return code;
}
public void setCode(final Integer code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
Controller
#RequestMapping(value = "/orders", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<Order> createOrder(#Valid #RequestBody Order order){
...
}
Technically, you can do many things to achieve the same thing, but that will not be a RESTful service, it will be an RPC at best.

Spring Boot request body semi-required fields

In our application user can write a message based on user id or screen name.
class Message {
public final Long userId;
public final String screenName;
public final String text;
#JsonCreator
public Message(#JsonProperty(value = "user_id", required = ???) Long userId,
#JsonProperty(value = "screen_name", required = ???) String screenName,
#JsonProperty(value = "text", required = true) String text) {
this.userId = userId;
this.screenName = screenName;
this.text = text;
}
}
Fields userId and screenName can't be optional at same time, one should be provided.
How in Spring Boot to mark that they are semi-required?
This seems like more of a validation concern rather than deserialization.
Create a Validator then put #Valid within the #RequestMapping on the controller.
See more here:
Spring REST Validation Example
From jenkov tutorials:
#JsonValue
The Jackson annotation #JsonValue tells Jackson that Jackson should
not attempt to serialize the object itself, but rather call a method
on the object which serializes the object to a JSON string. Note that
Jackson will escape any quotation marks inside the String returned by
the custom serialization, so you cannot return e.g. a full JSON
object. For that you should use #JsonRawValue instead (see previous
section).
The #JsonValue annotation is added to the method that Jackson is to
call to serialize the object into a JSON string. Here is an example
showing how to use the #JsonValue annotation:
public class PersonValue {
public long personId = 0;
public String name = null;
#JsonValue
public String toJson(){
return this.personId + "," + this.name;
}
}
The output you would get from asking Jackson to serialize a
PersonValue object is this:
"0,null"
So you can use #JsonValue and put your code either to ignore or not from some fields when you try to convert into JSON
#JsonValue
public String toJson(){
//ignore fields or include them here
}
Just throw an IllegalArgumentException. The best case would be to deserialize, then run through a validator though so you separate the concerns of serialization, and domain validation.
class Message {
public final Long userId;
public final String screenName;
public final String text;
#JsonCreator
public Message(#JsonProperty(value = "user_id", required = false) Long userId,
#JsonProperty(value = "screen_name", required = false) String screenName,
#JsonProperty(value = "text", required = true) String text) {
if(userId == null && screenName == null) {
throw new IllegalArgumentException("userId or screenName must be provided.");
}
this.userId = userId;
this.screenName = screenName;
this.text = text;
}
}

Resources