Spring #RequestBody annotation in Restful web service - java

Thanks to #RestController I don't need to add annotation #ResposneBody, cause spring knows that it is rest controller, and he will not generate view, but instead it will return json object.
Unfortunately there is one more annotation related to this topic. It is #RequestBody, when controller method accept json object as a parameter. And it will have to be pointed before that parameter.
My question is there a way to get rid of that annotation (#RequestBody).? If my controller is rest controller (#RestController instead of regular #Controller) it should be demanded from spring?

No, you'll have to specify #RequestBody. A Java method can have only a single return value, and so the #ResponseBody is unambiguous, but there are multiple possible ways that mapped controller parameters might be interpreted (in particular, using #ModelAttribute with form encoding is a very common alternative to #RequestBody with JSON), and you'll need to tell Spring how to map the incoming request.

Related

Validation of request body AND request parameter in 1 step?

a question to validation of put calls to a REST endpoint using spring boot and javax.validation (not the spring validation).
You have the following method in the resource:
#PutMapping(...)
public Response getResult(#RequestBody #Valid myBody, #PathVariable #MyIdValidation long id) {
}
When I call the method, myBody gets validated and I get a MethodArgumentNotValidException in my exception handler. But parameter id gets not validated!
Only if myBody is valid, id gets validated as well.
The only solution I found is to not use #Valid, and implement the validation of the body myself.
Are there better solutions?
TIA
Kibu
I don't think its doable by Spring MVC framework itself because framework handles #RequestBody and others like #RequestParam or #PathVariable differently by using different components. Also, both pieces need to be disconnected because you might not like to validate all arguments of a method.
#RequestBody is handled by org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor and validations are called from there & for params or path variable validations are done by org.springframework.validation.beanvalidation.MethodValidationInterceptor.
So in my opinion, method arguments of a controller method are handled one by one by framework & are disconnected in logic so these validations can't be clubbed together.
I've put some effort into this issue and started a project on github
It's possible to validate in one stop, but you need a different approach. Check out the project and test it.
Kibu

Http controller parameter object defined as DTO or other?

RPC in Internet transport layer, use dto is reasonable. Http controller? If all controller are used by front end, parameter defined as VO?
I guess you are asking whether the argument of the rest controller method can be a DTO.
Well it will depend on the framework you use. The http parameters are strings.
If the framework has an utility mechanism (probably an annotation) that lets you map the http params you receive into a DTO you supply as the rest controller method arg, there's no problem in the arg being a DTO.
If the framework doesn't have such utility (it just maps each http param into an string arg of the rest controller method), then you have to build manually the DTO in the rest controller method.
I don't know if Spring has such an utility annotation similar to #PathVariable but for gathering multiple request params into a DTO object.
UPDATE:
Spring #RequestBody annotation deserializes the JSON into the java object argument of the rest controller method. So, the arg annotated with #RequestBody is a DTO.
DDD says nothing about which type must be the params of a rest api. They can be either a DTO or Strings, it doesn't matter. If they where strings, you would have to construct the DTO by yourself. Using #RequestBody, Spring framework does it for you.
In java, an object that is carries between process is named following the camel case notation and having the DTO suffix.
e.g. ServiceMessageDTO
DTO stands for data transfer object.
This applies also to the request body parameters from the rest webmethods.

Spring form validation for plain HTML form

I need to validate some simple forms in my application. In these forms I have one or two input text to validate so I'd like to not create a specific ModelAttribute class for every form. I'd like to use instead plain HTML form and use #RequestParam annotations to handle POST parameters.
Is there a way to use Spring form validation in this situation (without using model attribute) or should I implement a backing-form object and a validator for each form?
Currently it is not possible to use #Valid on individual #RequestParam, #PathVariable etc. to trigger validation. This is the relevant feature request on the Spring Issue Tracker. Let's cross our fingers for Spring 4.1!
In your case, you will either have to use #ModelAttribute, or perform custom validation inside the controller (or maybe a Spring interceptor if you want the same validation to apply to multiple endpoints)
I think you can do this with Annotation. You can specifie for your parameters annotation like :
#Size(min=3, max=5)
#NotNull
#NotEmpty
...
Without a model attribute, Spring form Validation is not possible. Because Spring Form Validation depends on Spring Form Binding, which is a linkage between form elements and Model Attribute. So how small the form may be, create a DTO(Model Attribute), bind it to form and Perform Validations.
Definitely not possible using Spring's validation API (Errors object):
java.lang.IllegalStateException: An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the #RequestBody or the #RequestPart arguments to which they apply
You could instantiate a model object, fill it with the data from the plain form and validate that object programmatically.

Why do I need to add #ResponseBody to my controller action?

According to Spring documentation, this annotation indicates that a method return value should be bound to the web response body. I understand that, and I've been using this for my ajax calls. However, I recently came across code that doesn't use the annotation.
So I guess my question really is why it works without the annotation?
Without the annotation, a different process takes place. Depending on the return type (you can find the defaults in this document) the response will be generated differently.
For example, if your return type is String, then, by default, the return value will be resolved as a View name, a ViewResolver will try to resolve and create a View object, and a RequestDispatcher will forward/include/redirect to it (ex. a jsp) so that the Servlet container can handle generating the response.
The actual interface that handles the return type is HandlerMethodReturnValueHandler and there are many implementations for each type. See here for more information.

Spring MVC - Is it possible to receive a strongly typed request object on a GET?

I have a Spring MVC controller which is servicing GET requests, to perform a search.
These requests have many optional parameters which may be passed on the query string.
For example:
#Data
public class SimpleSearchRequest implements SearchRequest {
private String term;
private List<Status> stati;
#JsonDeserialize(using=DateRangeDeserializer.class)
private Range<DateTime> dateRange;
}
If I were using a POST or PUT for this, I could nicely marshall the inbound request using a #RequestBody. However, because I'm using a GET, this doesn't seem to fit.
Instead, it seems I'm required to list all the possible parameters on the method signature as #RequestParam(required=false).
Aside from leading to ugly method signatures, I'm also losing out on all sorts of OO goodness by not using classes here.
Attempting to use #RequestBody fails (understandably so), and as discussed here and here, using an actual request body on a GET is not desirable.
Is there a way to get Spring MVC to support marshalling multiple #RequestParam's to a strongly typed object on GET requests?
It seems the answer was to simply remove the annotation.
This worked:
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody List<Result> search(SearchRequest request) {}

Categories

Resources