Access Post method json RequestBody parameters in webflux reacive programming - spring-boot

How to access RequestBody parameters which is of Mono type. Spring Boot Webflux reactive.
I would like to return a ResponseEntity and not a Mono.
#RequestMapping(value = "/poststudentdata", method = RequestMethod.POST, headers={"content-type=application/json"})
public ResponseEntity<String> poststudentData(#Valid #RequestBody Mono<Student> student, BindingResult bindingResult) {
// How can i access student.getName() etc.... RequestBodt parameters
// Not able to access as have declared Student as Mono.
}

Don't try to return a non-reactive type when your input is provided asynchronously via a reactive type (Mono), because it means you'll likely end up blocking the IO thread on which the request was processed, which assumes non-blocking behavior of Controllers. This brings up the risk of not only blocking the current request's processing, but processing of all other requests in the application.
So change the return type to Mono<ResponseEntity>, rename student to studentMono for clarity and process your student in a map (or possibly flatMap if you have asynchronous transformations to apply):
return studentMono.map(student -> ResponseEntity.ok(student.getName()));

Related

Spring REST - Deserializing object from GET request query

I'm trying to implement an endpoint that takes a serialized object from request parameter and deserializes it into a POJO. Is there an easy way how to do this with Spring?
The example of a query:
http://localhost/routes/departures?trip=%7B%22stopId%22:%22U321Z102%22,%22routeId%22:%22L991D1%22,%22headSign%22:%22Nemocnice+Motol%22%7D
which should translate into this:
trip: {"stopId":"U321Z102","routeId":"L991D1","headSign":"Nemocnice Motol"}
Also, those parameter values may contain spaces and special characters (ěščř...). Will Spring handle this? Alternatively I could send those parameters separately and not serialized, but I'm worried this would be an issue.
You need to send the user by using post request (send a userDTO that has the same type and attributes names than the one in the back end )
your rest controller is going to look like this
#PostMapping("/users")
#PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
public ResponseEntity<User> createUser(#Valid #RequestBody UserDTO userDTO) throws URISyntaxException {
log.debug("REST request to save User : {}", userDTO);

#ModelAttribute vs #RequestBody, #ResponseBody

#ModelAttribute
RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method =
RequestMethod.POST)
public String processSubmit(#ModelAttribute Pet pet) { }
http://.../?name=Something&age=100
public String doSomething(#ModelAttribute User user) { }
#RequestBody
#RequestMapping(value = "/user/savecontact", method = RequestMethod.POST
public String saveContact(#RequestBody Contact contact){ }
{ "name": "Something", "age": "100" } in request body
public String doSomething(#RequestBodyUser user) { }
#ModelAttribute will take a query string. so, all the data are being pass to the server through the url
#RequestBody, all the data will be pass to the server through a full JSON body
Now which one is the best approach ???
If both are for same purpose to bind to the bean..which one is the best practice or widely used as standard practice?
Both handles multi-part file and does it both have equivalent options with one another ?
https://javabeat.net/spring-multipart-file-upload/
How do i upload/stream large images using Spring 3.2 spring-mvc in a restful way
Does any one of them has lesser capabilities then the other one? Like length limitations, method limitations. Drawbacks
Which one is more secured in terms of security ?
As the javadoc suggests, it's the usage that sets them apart, i.e., use #ModelAttribute if you want to bind the object back to the web view, if this is not needed, use #RequestBody
#RequestBody
Usecases : Restful controllers (ex: produce and consume json/xml, processing direct document download requests, searching for stuff, ajax requests )
As the name suggests the if a method argument is annotated with #RequestBody annotation Spring converts the HTTP request body to the Java type of the method argument.
Is only allowed on method parameters (#Target(value={ PARAMETER}))
The body of the request is passed through an HttpMessageConverter to resolve the method argument depending on the content type of the request.
works for Post and not Get method.
#ModelAttribute
Usecases : web app controllers (ex: binding request query parameters, populating web views with options and defaults)
Uses data binders & ConversionService
Is allowed on methods and method params(#Target(value={METHOD, PARAMETER}))
Useful when dealing with model attributes for adding and retrieving model attributes to and from the Srping’s Model object
When used on METHODS, those methods are invoked before the controller methods annotated with #RequestMapping are invoked
binds a method PARAMETER or method return value to a named model attribute & the bound named model attributes are exposed to a web view
binds request query parameters to bean
For more information on Data Binding, and Type Conversion refer: https://docs.spring.io/spring/docs/5.1.x/spring-framework-reference/core.html#validation

What's the reason to use ResponseEntity<?> return type instead of simple ResponseEntity in Spring Controller?

I've seen a lot of examples of Spring Controllers implementation that use ResponseEntity<?> in order to return HTTP response that have a specific status code and optional body.
ResponseEntity<?> notation is present even in official Spring tutorials like the following one: Building REST services with Spring
What's the reason to use ResponseEntity<?> instead of simple ResponseEntity?
It's a little bit related to my previous question: SonarQube complains about using ResponseEntity with a wildcard
There is some explanation in What is a raw type and why shouldn't we use it? thread, but I'd like to pay more attention to ResponseEntity class and it's use in Spring Controllers.
Consider the following snippet of code where somethingService returns an Optional of Something class:
#GetMapping
ResponseEntity<?> getSomething() {
return somethingService.getSomething()
.map(smth -> new ResponseEntity<>(smth, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
Is there any reason to leave a wildcard even if I don't get any profit from compiler checks since ResponseEntity(HttpStatus status) parametrises ResponseEntity with Object class?

Spring automatically wrap rest controller response in ResponseEntity

Here is what I'm trying to achieve :
I have many spring rest reactive controller returning various Object such as Mono, Flux
I would like to wrap all these response in a ResponseEntity and so always return something like :
Mono<ResponseEntity<MyObjects>>
Any suggestion ?
Just use #ResponseBody Annotation on your controllers
When you use the #ResponseBody annotation on a method, Spring converts the return value and writes it to the http response automatically. Each method in the Controller class must be annotated with #ResponseBody.
See the example

5 levels of media type Spring REST

I am trying to apply CQRS principles on my REST API with domain-driven-design principles, using the 5 levels of Media Types, as explained in these articles:
https://www.infoq.com/articles/rest-api-on-cqrs
http://byterot.blogspot.ch/2012/12/5-levels-of-media-type-rest-csds.html
My technical context is Spring REST framework version 3.2.
Basically, i need to be able to map my commands using different "domain-model" media types.
Therefore, i would expect the following mapping to work:
#Controller
#RequestMapping("resources")
public class MyController {
#RequestMapping(value = "{id}", method = RequestMethod.PUT, consumes = "application/json;domain-model=CommandOne")
#ResponseBody
public void commandOne(#PathVariable Long id, #RequestBody CommandOne commandOne) {
LOG.info("Using command {}", commandOne);
}
#RequestMapping(value = "{id}", method = RequestMethod.PUT, consumes = "application/json;domain-model=CommandTwo")
#ResponseBody
public void commandTwo(#PathVariable Long id, #RequestBody CommandTwo commandTwo) {
LOG.info("Using command {}", commandTwo);
}
}
Problem is, I am getting mapping errors when requesting for a PUT:
PUT /resources/123
Content-Type: application/json;domain-model=CommandOne
Error is:
java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path ...
Spring doesn't allow me to map the same uri the different domain-model Media Types. Any idea how could I achieve that? Am I missing something?
Many thanks
:o)
That's because the content-type is still the same application/json. Please look at Content-Type syntax
What you are passing as domain-model=CommandOne is just a parameter and Spring doesn't recognize as a difference to call the different methods.
This is described in more detail on answer
Does HTTP content negotiation respect media type parameters
This was submitted as a BUG to the Spring team but they closed with "Work as designed".
Unfortunately Spring can't treat this case currently.

Resources