For multipart request, how to use using #ModelAttribute and Hashmap together? - java

First of all, thank you in advance for your support.
My problem;
First I am successfully getting my specific parameters in Employer. However, I also have a constantly changing parameter list in request. I want to get them with Map too.
My dto:
public class Employee {
private String name;
private MultipartFile document;
}
#RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Mono<Employee> saveEmployee(#ModelAttribute Employee employee, Map<String,Object> otherValues) {
System.out.println(otherValues.get("key1").toString());
return employeeService.save(employee);
}
I attached a request example aslo.
NOTE:
I used #RequestParam, #RequestPart before Map<String,Object> otherValues like this;
#RequestParam Map<String,Object> otherValues
#RequestPart Map<String,Object> otherValues
But I still couldn't get the rest of the data.

When you want to get values from form data, you can create a model like a DTO, with field of both entity (employee) and additional data (otherValues). Because #ModelAttribute can bind data to only one named model attribute

This is working for Spring MVC. But When you work with Spring WebFlux for reactive applications, it doesn't work.
#RequestMapping(path = "/employee", method = POST, consumes ={MediaType.MULTIPART_FORM_DATA_VALUE })
public Employee saveEmployee(
#ModelAttribute Employee employee,
#RequestParam Map<Object,Object> otherValues,
#RequestParam("file") MultipartFile file) {
System.out.println(otherValues.get("key1").toString());
return employeeService.save(employee);
}
Main trick is to use Object for key and value;
#RequestParam Map<Object,Object> otherValues

Related

Generate and set self links in nested items

I should migrate some code from jax-rs to spring mvc. We had a controller, which response with an object and set at the same time links in a list :
HateoasResponse.ok(content)
.selfLink(FieldPath.path("categories"), "some_controller_id", "id")
.build()
Did any one know, if there is something similar in spring mvc ?
I have checked spring-hateoas. If I use it , I should modify my models to something supported by this package (CollectionModel, EnitityModel..)
You have to make the response object extend ResourceSupport and then generate the links as follows.
org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(methodOn(YourSpringMvcController.class)
.methodWhichHasMappingTo(param1,param2,paramN))
.withRel("relationOfThisLinkToTheRequestedResource").expand();
This link can then be added to the response object using the resource add method.
for example, let's say you have a controller like the following:
#RestController
public class OrderController {
#GetMapping(value = "/orders/{orderId}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Order> getOrder(#Valid #PathVariable Integer orderId) {
return getOrder(orderId);
}
#DeleteMapping(value = "/orders/{orderId}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Order> deleteOrder(#Valid #PathVariable Integer orderId) {
return orderRepo.deleteOrder(orderId);
}
}
then for a request to GET orders, you would build the response like the following:
Order which is a response entity will extend ResourceSupport
public Order getOrder(int orderId){
Order order = repo.findByOrderId(orderId);
Link deleteLink = ControllerLinkBuilder.linkTo(methodOn(OrderController.class)
.deleteOrder(orderId))
.withRel("delete").expand();
order.add(deleteLink);
Link selfLink = ControllerLinkBuilder.linkTo(methodOn(OrderController.class)
.getOrder(orderId))
.withSelfRel();
order.add(selfLink);
return order;
}
Hope this helps.

How send a Map<String, String> using #PathVariable from Spring MVC

I want to receive a Map<Timestamp, Integer> as PathVariable using Spring MVC. Is this possible?
This is my controller:
#ApiOperation(value = "Some Api", produces = MediaType.APPLICATION_JSON_VALUE)
#PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<RestResult> createApi(#RequestPart (value="image", required = false) MultipartFile banner, SomeRequest request){
RestResult result = new RestResult();
return new ResponseEntity<>(result, HttpStatus.CREATED);
}
This is my request:
#Getter
#Setter
public class SomeRequest implements Serializable {
#NonNull
private MultiValueMap<Timestamp, Integer> someValue;
}
As one of the way you could use Spring's HandlerMethodArgumentResolver and implement its supportsParameter() and resolveArgument() methods. The last one accepts the method parameter and web request, which you can use to get any required data and compose the object whatever you want.
The argument resolver is invoked before the controller method and makes the required argument transformation.
Update:
You have to register the resolver to make it active. If you use spring-boot, you just need to define it as a bean.
Hope it will help.

MissingServletRequestParameterException with PostMapping in Spring MVC

I'm getting this error when I try to create an instance of an Object and store it into a database:
org.springframework.web.bind.MissingServletRequestParameterException
The code for the method:
#PostMapping(path="accounts/add", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public
#ResponseBody
String addAccount(#RequestParam String accountNumber, #RequestParam String accountName ) {
Account account = new Account();
account.setAccountName(accountName);
account.setAccountNumber(accountNumber);
accountRepository.save(account);
return "Saved";
}
When I use PostMan and try to enter the JSON in, it gives me this message. What am I doing wrong?
Since your POSTing (or PUTing?) JSON as the content body, you cannot use #RequestParam to deconstruct it. That is used for query or form parameters. You need to specify a single method parameter with #RequestBody, which is a class that looks something like the following.
public class Account {
public String accountNumber;
public String accountName;
// setters and getters removed for brevity
}
See this answer for more info: #RequestBody and #ResponseBody annotations in Spring

How to provide a list of objects for a REST query in spring-mvc?

I want to create a REST-GET controller in spring-mvc that takes a list of objects, eg 10 ids as follows:
#RestController
public class MyRest {
#RequestMapping(method = RequestMethod.GET)
public Object test(#RequestParam value="id" required=false) List<Integer> ids) {
Sysout(ids);
}
}
Anyway when I call it, I have to repeat the id param multiple times:
localhost:8080/app?id=1&id=2&id=3&...
It is possible to change the param to some kind of list? Eg
app?id=1,2,3,4,5
And if yes, is this advisable? What's better from the client point of view?
Its better to use POST message with JSON or XML as request body.
As you never know how many id's will be passed.
#RestController
public class MyRest {
#RequestMapping(method = RequestMethod.POST)
public Object test(#RequestBody IDRequest request) {
Sysout(ids);
}
public static final class IDRequest {
List<Integer> ids;
<!-- getter/setters--->
}
}
where the request will be some kind of a JSON or XML like this
{"ids":[1,2,3,4,5,6,7,8,9]}
You can provide list of objects to rest service as request param.Here is the example
#RequestMapping(value = "/animals, method = RequestMethod.GET)
public void test(#RequestParam(value="animalsNames[]") String[] animalsNames) {
Sysout(animalsNames);
}
And your request looks like
http://localhost:8080/appname/animals?animalsNames[]=dog,horse
HTTP Method type : GET
Controller :
public #ResponseBody String getInfos(HttpServletRequest request,
#RequestParam #DateTimeFormat( #RequestParam List<Long> ids) {...}
Request :
http://localhost:8080/test/api?ids=1,2,3

Spring restful webservice returning JSON

I just took the tutorial over at Spring.io http://spring.io/guides/gs/rest-service/ and created a simple rest service. But, does anybody know how I can return multiple objects in JSON format? If I for instance have a person class with a name and an id, how can I add three persons to /persons?
You can use the #ResponseBody annotation and just return whatever you want, providing that those objects can be jsonized.
For example, you can have a bean like this:
#Data
public class SomePojo {
private String someProp;
private List<String> someListOfProps;
}
and then in your controller you can have:
#ResponseBody
#RequestMapping("/someRequestMapping")
public List<SomePojo> getSomePojos(){
return Arrays.<String>asList(new SomePojo("someProp", Arrays.<String>asList("prop1", "prop2"));
}
and Spring by default would use its Jackson mapper to do it, so you'd get a response like:
[{"someProp":"someProp", "someListOfProps": ["prop1", "prop2"]}]
The same way, you can bind to some objects, but this time, using the #RequestBody annotation, where jackson would be used this time to pre-convert the json for you.
what you can do is
#RequestMapping("/someOtherRequestMapping")
public void doStuff(#RequestBody List<SomePojo> somePojos) {
//do stuff with the pojos
}
Try returning a list from the method:
#RequestMapping("/greetings")
public #ResponseBody List<Greeting> greetings(
#RequestParam(value="name", required=false, defaultValue="World") String name) {
return Arrays.asList(new Greeting(counter.incrementAndGet(),String.format(template, name)));
}

Categories