Browse Source

WebFlux docs: Request|ResponseBody + Http|ResponseEntity

Issue: SPR-16040
pull/1645/head
Rossen Stoyanchev 8 years ago
parent
commit
61fc321554
  1. 212
      src/docs/asciidoc/web/webflux.adoc
  2. 196
      src/docs/asciidoc/web/webmvc.adoc

212
src/docs/asciidoc/web/webflux.adoc

@ -1037,12 +1037,11 @@ type. See <<webflux-ann-cookievalue>>. @@ -1037,12 +1037,11 @@ type. See <<webflux-ann-cookievalue>>.
|`@RequestBody`
|For access to the HTTP request body. Body content is converted to the declared method
argument type using ``HttpMessageReader``'s. Supports reactive types.
// TODO: See <<webflux-ann-requestbody>>.
<<webflux-ann-requestbody>>.
|`HttpEntity<B>`
|For access to request headers and body. The body is converted with ``HttpMessageReader``'s.
Supports reactive types.
// TODO: See <<webflux-ann-httpentity>>.
Supports reactive types. See <<webflux-ann-httpentity>>.
|`@RequestPart`
|For access to a part in a "multipart/form-data" request. Supports reactive types.
@ -1061,11 +1060,10 @@ Note that use of `@ModelAttribute` is optional, e.g. to set its attributes. @@ -1061,11 +1060,10 @@ Note that use of `@ModelAttribute` is optional, e.g. to set its attributes.
See "Any other argument" further below in this table.
|`Errors`, `BindingResult`
|For access to errors from the data binding and validation applied to a command object;
this argument must be declared immediately after a command object (i.e.
`@ModelAttribute` argument). If this is not declared in the controller method signature,
errors result in a `BindException`. See <<webflux-ann-modelattrib-method-args>> for more
details.
|For access to errors from validation and data binding for a command object
(i.e. `@ModelAttribute` argument), or errors from the validation of an `@RequestBody` or
`@RequestPart` arguments; an `Errors`, or `BindingResult` argument must be declared
immediately after the validated method argument.
|`SessionStatus` + class-level `@SessionAttributes`
|For marking form processing complete which triggers cleanup of session attributes
@ -1108,12 +1106,12 @@ values. @@ -1108,12 +1106,12 @@ values.
|`@ResponseBody`
|The return value is encoded through ``HttpMessageWriter``s and written to the response.
// TODO: See <<webflux-ann-responsebody>>.
See <<webflux-ann-responsebody>>.
|`HttpEntity<B>`, `ResponseEntity<B>`
|The return value specifies the full response including HTTP headers and body be encoded
through ``HttpMessageWriter``s and written to the response.
// TODO: See <<webflux-ann-httpentity>>.
See <<webflux-ann-responseentity>>.
|`HttpHeaders`
|For returning a response with headers and no body.
@ -1583,6 +1581,200 @@ To access multipart data sequentially, in streaming fashion, use `@RequestBody` @@ -1583,6 +1581,200 @@ To access multipart data sequentially, in streaming fashion, use `@RequestBody`
}
----
`@RequestPart` can be used in combination with `javax.validation.Valid`, or Spring's
`@Validated` annotation, which causes Standard Bean Validation to be applied.
By default validation errors cause a `WebExchangeBindException` which is turned
into a 400 (BAD_REQUEST) response. Alternatively validation errors can be handled locally
within the controller through an `Errors` or `BindingResult` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/")
public String handle(**@Valid** @RequestPart("meta-data") MetaData metadata,
**BindingResult result**) {
// ...
}
----
[[webflux-ann-requestbody]]
==== @RequestBody
[.small]#<<web.adoc#mvc-ann-requestbody,Same in Spring MVC>>#
Use the `@RequestBody` annotation to have the request body read and deserialized into an
Object through an <<webflux-codecs,HttpMessageReader>>.
Below is an example with an `@RequestBody` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// ...
}
----
Unlike Spring MVC, in WebFlux the `@RequestBody` method argument supports reactive types
and fully non-blocking reading and (client-to-server) streaming:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/accounts")
public void handle(@RequestBody Mono<Account> account) {
// ...
}
----
You can use the <<webflux-config-message-codecs>> option of the <<webflux-config>> to
configure or customize message readers.
`@RequestBody` can be used in combination with `javax.validation.Valid`, or Spring's
`@Validated` annotation, which causes Standard Bean Validation to be applied.
By default validation errors cause a `WebExchangeBindException` which is turned
into a 400 (BAD_REQUEST) response. Alternatively validation errors can be handled locally
within the controller through an `Errors` or `BindingResult` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
// ...
}
----
[[webflux-ann-httpentity]]
==== HttpEntity
[.small]#<<web.adoc#mvc-ann-httpentity,Same in Spring MVC>>#
`HttpEntity` is more or less identical to using <<webflux-ann-requestbody>> but based on a
container object that exposes request headers and body. Below is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/accounts")
public void handle(HttpEntity<Account> entity) {
// ...
}
----
[[webflux-ann-responsebody]]
==== @ResponseBody
[.small]#<<web.adoc#mvc-ann-responsebody,Same in Spring MVC>>#
Use the `@ResponseBody` annotation on a method to have the return serialized to the
response body through an <<webflux-codecs,HttpMessageWriter>>. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@GetMapping("/accounts/{id}")
@ResponseBody
public Account handle() {
// ...
}
----
`@ResponseBody` is also supported at the class level in which case it is inherited by
all controller methods. This is the effect of `@RestController` which is nothing more
than a meta-annotation marked with `@Controller` and `@ResponseBody`.
`@ResponseBody` supports reactive types which means you can return Reactor or RxJava
types and have the asynchronous values they produce rendered to the response.
For additional details on JSON rendering see <<webflux-codecs-jackson-json>>.
`@ResponseBody` methods can be combined with JSON serialization views.
See <<mvc-ann-jackson>> for details.
You can use the <<webflux-config-message-codecs>> option of the <<webflux-config>> to
configure or customize message writing.
[[webflux-ann-responseentity]]
==== ResponseEntity
[.small]#<<web.adoc#mvc-ann-responseentity,Same in Spring MVC>>#
`ResponseEntity` is more or less identical to using <<webflux-ann-responsebody>> but based
on a container object that specifies request headers and body. Below is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/something")
public ResponseEntity<String> handle() {
// ...
URI location = ...
return new ResponseEntity.created(location).build();
}
----
[[webflux-ann-jackson]]
==== Jackson JSON
[[webflux-ann-jsonview]]
===== Jackson serialization views
[.small]#<<web.adoc#mvc-ann-jackson,Same in Spring MVC>>#
Spring WebFlux provides built-in support for
http://wiki.fasterxml.com/JacksonJsonViews[Jackson's Serialization Views]
which allows rendering only a subset of all fields in an Object. To use it with
`@ResponseBody` or `ResponseEntity` controller methods, use Jackson's
`@JsonView` annotation to activate a serialization view class:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RestController
public class UserController {
@GetMapping("/user")
@JsonView(User.WithoutPasswordView.class)
public User getUser() {
return new User("eric", "7!jd#h23");
}
}
public class User {
public interface WithoutPasswordView {};
public interface WithPasswordView extends WithoutPasswordView {};
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
@JsonView(WithoutPasswordView.class)
public String getUsername() {
return this.username;
}
@JsonView(WithPasswordView.class)
public String getPassword() {
return this.password;
}
}
----
[NOTE]
====
`@JsonView` allows an array of view classes but you can only specify only one per
controller method. Use a composite interface if you need to activate multiple views.
====
[[webflux-ann-modelattrib-methods]]
=== Model Methods

196
src/docs/asciidoc/web/webmvc.adoc

@ -1623,11 +1623,10 @@ Note that use of `@ModelAttribute` is optional, e.g. to set its attributes. @@ -1623,11 +1623,10 @@ Note that use of `@ModelAttribute` is optional, e.g. to set its attributes.
See "Any other argument" further below in this table.
|`Errors`, `BindingResult`
|For access to errors from the data binding and validation applied to a command object;
this argument must be declared immediately after a command object (i.e.
`@ModelAttribute` argument). If this is not declared in the controller method signature,
errors result in a `BindException`. See <<mvc-ann-modelattrib-method-args>> for more
details.
|For access to errors from validation and data binding for a command object
(i.e. `@ModelAttribute` argument), or errors from the validation of an `@RequestBody` or
`@RequestPart` arguments; an `Errors`, or `BindingResult` argument must be declared
immediately after the validated method argument.
|`SessionStatus` + class-level `@SessionAttributes`
|For marking form processing complete which triggers cleanup of session attributes
@ -1672,7 +1671,8 @@ response. See <<mvc-ann-responsebody>>. @@ -1672,7 +1671,8 @@ response. See <<mvc-ann-responsebody>>.
|`HttpEntity<B>`, `ResponseEntity<B>`
|The return value specifies the full response including HTTP headers and body be converted
through ``HttpMessageConverter``s and written to the response. See <<mvc-ann-httpentity>>.
through ``HttpMessageConverter``s and written to the response.
See <<mvc-ann-responseentity>>.
|`HttpHeaders`
|For returning a response with headers and no body.
@ -2295,146 +2295,121 @@ probably want it deserialized from JSON (similar to `@RequestBody`). Use the @@ -2295,146 +2295,121 @@ probably want it deserialized from JSON (similar to `@RequestBody`). Use the
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/")
public String handle(**@RequestPart("meta-data") MetaData metadata,
@RequestPart("file-data") MultipartFile file**) {
// ...
}
@PostMapping("/")
public String handle(**@RequestPart("meta-data") MetaData metadata,
@RequestPart("file-data") MultipartFile file**) {
// ...
}
----
`@RequestPart` can be used in combination with `javax.validation.Valid`, or Spring's
`@Validated` annotation, which causes Standard Bean Validation to be applied.
By default validation errors cause a `MethodArgumentNotValidException` which is turned
into a 400 (BAD_REQUEST) response. Alternatively validation errors can be handled locally
within the controller through an `Errors` or `BindingResult` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PostMapping("/")
public String handle(**@Valid** @RequestPart("meta-data") MetaData metadata,
**BindingResult result**) {
// ...
}
----
[[mvc-ann-requestbody]]
==== @RequestBody
[.small]#<<web-reactive.adoc#webflux-ann-requestbody,Same in Spring WebFlux>>#
The `@RequestBody` method parameter annotation indicates that a method parameter should
be bound to the value of the HTTP request body. For example:
Use the `@RequestBody` annotation to have the request body read and deserialized into an
Object through an <<integration.adoc#rest-message-conversion,HttpMessageConverter>>.
Below is an example with an `@RequestBody` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@PutMapping("/something")
public void handle(@RequestBody String body, Writer writer) throws IOException {
writer.write(body);
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// ...
}
----
You convert the request body to the method argument by using an
<<integration.adoc#rest-message-conversion,HttpMessageConverter>>.
`HttpMessageConverter` is responsible for converting from the HTTP request message to an
object and converting from an object to the HTTP response body. The
`RequestMappingHandlerAdapter` supports the `@RequestBody` annotation with the following
default `HttpMessageConverters`:
* `ByteArrayHttpMessageConverter` converts byte arrays
* `StringHttpMessageConverter` converts strings
* `FormHttpMessageConverter` converts form data to/from a `MultiValueMap<String, String>`
* `SourceHttpMessageConverter` converts to/from a `javax.xml.transform.Source``
For more information on these converters, see <<integration.adoc#rest-message-conversion,
Message Converters>>. Also note that if using the MVC namespace or the MVC Java config,
a wider range of message converters are registered by default, including default JSON
and XML payload converters (if e.g. Jackson, Gson and/or JAXB2 are present at runtime).
See <<mvc-config-enable>> for more information on MVC setup options.
You can use the <<mvc-config-message-converters>> option of the <<mvc-config>> to
configure or customize message conversion.
For a custom example, if you intend to read and write XML using the `spring-oxm` module,
you need to configure the `MarshallingHttpMessageConverter` with a specific `Marshaller`
implementation from the `org.springframework.oxm` package. The example below shows how to
do that directly in your configuration but if your application is configured through the
MVC namespace or the MVC Java config see <<mvc-config-enable>> instead.
`@RequestBody` can be used in combination with `javax.validation.Valid`, or Spring's
`@Validated` annotation, which causes Standard Bean Validation to be applied.
By default validation errors cause a `MethodArgumentNotValidException` which is turned
into a 400 (BAD_REQUEST) response. Alternatively validation errors can be handled locally
within the controller through an `Errors` or `BindingResult` argument:
[source,xml,indent=0]
[source,java,indent=0]
[subs="verbatim,quotes"]
----
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="stringHttpMessageConverter"/>
<ref bean="marshallingHttpMessageConverter"/>
<list>
</property>
</bean>
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean id="marshallingHttpMessageConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="xstreamMarshaller"/>
</bean>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
// ...
}
----
An `@RequestBody` method parameter can be annotated with `@Valid`, in which case it will
be validated using the configured `Validator` instance. When using the MVC namespace or
the MVC Java config, a JSR-303 validator is configured automatically assuming a JSR-303
implementation is available on the classpath.
Just like with `@ModelAttribute` parameters, an `Errors` argument can be used to examine
the errors. If such an argument is not declared, a `MethodArgumentNotValidException`
will be raised. The exception is handled in the `DefaultHandlerExceptionResolver`, which
sends a `400` error back to the client.
[NOTE]
====
Also see <<mvc-config-enable>> for
information on configuring message converters and a validator through the MVC namespace
or the MVC Java config.
====
[[mvc-ann-httpentity]]
==== HttpEntity
[.small]#<<web-reactive.adoc#webflux-ann-httpentity,Same in Spring WebFlux>>#
`HttpEntity` is similar to `@RequestBody` but also with access to request headers:
`HttpEntity` is more or less identical to using <<mvc-ann-requestbody>> but based on a
container object that exposes request headers and body. Below is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping("/something")
public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException {
String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader");
byte[] requestBody = requestEntity.getBody();
@PostMapping("/accounts")
public void handle(HttpEntity<Account> entity) {
// ...
}
----
The above example gets the value of the `MyRequestHeader` request header, and reads the
body as a byte array. As with `@RequestBody`, Spring uses `HttpMessageConverter` to
convert from and to the request and response streams. For more information on these
converters, see the previous section and <<integration.adoc#rest-message-conversion,
Message Converters>>.
[[mvc-ann-responsebody]]
==== @ResponseBody
[.small]#<<web-reactive.adoc#webflux-ann-responsebody,Same in Spring WebFlux>>#
The `@ResponseBody` annotation is similar to `@RequestBody`. This annotation can be placed
on a method and indicates that the return type should be written straight to the HTTP
response body (and not placed in a Model, or interpreted as a view name). For example:
Use the `@ResponseBody` annotation on a method to have the return serialized to the
response body through an
<<integration.adoc#rest-message-conversion,HttpMessageConverter>>. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@GetMapping("/something")
@GetMapping("/accounts/{id}")
@ResponseBody
public String helloWorld() {
return "Hello World";
public Account handle() {
// ...
}
----
The above example will result in the text `Hello World` being written to the HTTP
response stream.
`@ResponseBody` is also supported at the class level in which case it is inherited by
all controller methods. This is the effect of `@RestController` which is nothing more
than a meta-annotation marked with `@Controller` and `@ResponseBody`.
`@ResponseBody` may be used with reactive types.
See <<mvc-ann-async>> and <<mvc-ann-async-reactive-types>> for more details.
You can use the <<mvc-config-message-converters>> option of the <<mvc-config>> to
configure or customize message conversion.
As with `@RequestBody`, Spring converts the returned object to a response body by using
an <<integration.adoc#rest-message-conversion,HttpMessageConverter>>.
`@ResponseBody` methods can be combined with JSON serialization views.
See <<mvc-ann-jackson>> for details.
[[mvc-ann-responseentity]]
==== ResponseEntity
[.small]#<<web-reactive.adoc#webflux-ann-responseentity,Same in Spring WebFlux>>#
The is similar to `@ResponseBody` but besides providing the response body, `ResponseEntity`
also allows setting response headers:
`ResponseEntity` is more or less identical to using <<mvc-ann-responsebody>> but based
on a container object that specifies request headers and body. Below is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -2442,31 +2417,24 @@ also allows setting response headers: @@ -2442,31 +2417,24 @@ also allows setting response headers:
@PostMapping("/something")
public ResponseEntity<String> handle() {
// ...
URI location = ... ;
URI location = ...
return new ResponseEntity.created(location).build();
}
----
As with `@ResponseBody`, Spring uses
<<integration.adoc#rest-message-conversion,HttpMessageConverter>> to
convert from and to the request and response streams. For more information on these
converters, see the previous section and <<integration.adoc#rest-message-conversion,
Message Converters>>.
[[mvc-ann-jackson]]
==== Jackson JSON
[[mvc-ann-jsonview]]
===== Jackson serialization views
[.small]#<<web-reactive.adoc#webflux-ann-jsonview,Same in Spring WebFlux>>#
It can sometimes be useful to filter contextually the object that will be serialized to the
HTTP response body. In order to provide such capability, Spring MVC has built-in support for
rendering with http://wiki.fasterxml.com/JacksonJsonViews[Jackson's Serialization Views].
To use it with an `@ResponseBody` controller method or controller methods that return
`ResponseEntity`, simply add the `@JsonView` annotation with a class argument specifying
the view class or interface to be used:
Spring MVC provides built-in support for
http://wiki.fasterxml.com/JacksonJsonViews[Jackson's Serialization Views]
which allows rendering only a subset of all fields in an Object. To use it with
`@ResponseBody` or `ResponseEntity` controller methods, use Jackson's
`@JsonView` annotation to activate a serialization view class:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -2511,10 +2479,8 @@ the view class or interface to be used: @@ -2511,10 +2479,8 @@ the view class or interface to be used:
[NOTE]
====
Note that despite `@JsonView` allowing for more than one class to
be specified, the use on a controller method is only supported with
exactly one class argument. Consider the use of a composite interface
if you need to enable multiple views.
`@JsonView` allows an array of view classes but you can only specify only one per
controller method. Use a composite interface if you need to activate multiple views.
====
For controllers relying on view resolution, simply add the serialization view class

Loading…
Cancel
Save