@ -3480,6 +3480,7 @@ configure a `DataSource` in your Spring configuration file and then dependency-i
@@ -3480,6 +3480,7 @@ configure a `DataSource` in your Spring configuration file and then dependency-i
that shared `DataSource` bean into your DAO classes. The `JdbcTemplate` is created in
the setter for the `DataSource`. This leads to DAOs that resemble the following:
@ -3504,6 +3505,7 @@ the setter for the `DataSource`. This leads to DAOs that resemble the following:
@@ -3504,6 +3505,7 @@ the setter for the `DataSource`. This leads to DAOs that resemble the following:
// JDBC-backed implementations of the methods on the CorporateEventDao follow...
}
----
--
The following example shows the corresponding XML configuration:
@ -3540,6 +3542,7 @@ support for dependency injection. In this case, you can annotate the class with
@@ -3540,6 +3542,7 @@ support for dependency injection. In this case, you can annotate the class with
(which makes it a candidate for component-scanning) and annotate the `DataSource` setter
method with `@Autowired`. The following example shows how to do so:
@ -3574,6 +3577,7 @@ method with `@Autowired`. The following example shows how to do so:
@@ -3574,6 +3577,7 @@ method with `@Autowired`. The following example shows how to do so:
<1> Annotate the class with `@Repository`.
<2> Constructor injection of the `DataSource`.
<3> Create a new `JdbcTemplate` with the `DataSource`.
--
The following example shows the corresponding XML configuration:
@ -7077,6 +7081,7 @@ in your Spring configuration file and then dependency-inject
@@ -7077,6 +7081,7 @@ in your Spring configuration file and then dependency-inject
that shared `ConnectionFactory` bean into your DAO classes. The `DatabaseClient` is created in
the setter for the `ConnectionFactory`. This leads to DAOs that resemble the following:
@ -7101,12 +7106,14 @@ the setter for the `ConnectionFactory`. This leads to DAOs that resemble the fol
@@ -7101,12 +7106,14 @@ the setter for the `ConnectionFactory`. This leads to DAOs that resemble the fol
// R2DBC-backed implementations of the methods on the CorporateEventDao follow...
}
----
--
An alternative to explicit configuration is to use component-scanning and annotation
support for dependency injection. In this case, you can annotate the class with `@Component`
(which makes it a candidate for component-scanning) and annotate the `ConnectionFactory` setter
method with `@Autowired`. The following example shows how to do so:
@ -7141,6 +7148,7 @@ method with `@Autowired`. The following example shows how to do so:
@@ -7141,6 +7148,7 @@ method with `@Autowired`. The following example shows how to do so:
<1> Annotate the class with `@Component`.
<2> Constructor injection of the `ConnectionFactory`.
<3> Create a new `DatabaseClient` with the `ConnectionFactory`.
--
Regardless of which of the above template initialization styles you choose to use (or
not), it is seldom necessary to create a new instance of a `DatabaseClient` class each
@ -121,6 +122,7 @@ following example shows:
@@ -121,6 +122,7 @@ following example shows:
}
}
----
--
By default, `@CrossOrigin` allows:
@ -139,6 +141,7 @@ the `allowOriginPatterns` property may be used to match to a dynamic set of orig
@@ -139,6 +141,7 @@ the `allowOriginPatterns` property may be used to match to a dynamic set of orig
`@CrossOrigin` is supported at the class level, too, and inherited by all methods.
The following example specifies a certain domain and sets `maxAge` to an hour:
@ -177,10 +180,12 @@ The following example specifies a certain domain and sets `maxAge` to an hour:
@@ -177,10 +180,12 @@ The following example specifies a certain domain and sets `maxAge` to an hour:
}
}
----
--
You can use `@CrossOrigin` at both the class and the method level,
val helloWorld = HandlerFunction<ServerResponse> { ServerResponse.ok().bodyValue("Hello World") }
----
--
That is convenient, but in an application we need multiple functions, and multiple inline
lambda's can get messy.
@ -335,6 +337,7 @@ Therefore, it is useful to group related handler functions together into a handl
@@ -335,6 +337,7 @@ Therefore, it is useful to group related handler functions together into a handl
has a similar role as `@Controller` in an annotation-based application.
For example, the following class exposes a reactive `Person` repository:
@ -409,6 +412,7 @@ Note that `PersonRepository.savePerson(Person)` is a suspending function with no
@@ -409,6 +412,7 @@ Note that `PersonRepository.savePerson(Person)` is a suspending function with no
<3> `getPerson` is a handler function that returns a single person, identified by the `id` path
variable. We retrieve that `Person` from the repository and create a JSON response, if it is
found. If it is not found, we return a 404 Not Found response.
@ -156,6 +156,7 @@ application deployed as a WAR), you can declare a Spring-managed bean of type
@@ -156,6 +156,7 @@ application deployed as a WAR), you can declare a Spring-managed bean of type
Netty global resources are shut down when the Spring `ApplicationContext` is closed,
@ -225,6 +228,7 @@ instances use shared resources, as the following example shows:
@@ -225,6 +228,7 @@ instances use shared resources, as the following example shows:
<1> Create resources independent of global ones.
<2> Use the `ReactorClientHttpConnector` constructor with resource factory.
<3> Plug the connector into the `WebClient.Builder`.
--
[[webflux-client-builder-reactor-timeout]]
@ -375,6 +379,7 @@ The following example shows how to customize the JDK `HttpClient`:
@@ -375,6 +379,7 @@ The following example shows how to customize the JDK `HttpClient`:
The following example shows how to customize Jetty `HttpClient` settings:
@ -395,6 +400,7 @@ The following example shows how to customize Jetty `HttpClient` settings:
@@ -395,6 +400,7 @@ The following example shows how to customize Jetty `HttpClient` settings:
By default, `HttpClient` creates its own resources (`Executor`, `ByteBufferPool`, `Scheduler`),
which remain active until the process exits or `stop()` is called.
@ -404,6 +410,7 @@ ensure that the resources are shut down when the Spring `ApplicationContext` is
@@ -404,6 +410,7 @@ ensure that the resources are shut down when the Spring `ApplicationContext` is
declaring a Spring-managed bean of type `JettyResourceFactory`, as the following example
@ -1474,6 +1474,7 @@ You can map requests by using glob patterns and wildcards:
@@ -1474,6 +1474,7 @@ You can map requests by using glob patterns and wildcards:
Captured URI variables can be accessed with `@PathVariable`, as the following example shows:
@ -1490,9 +1491,11 @@ Captured URI variables can be accessed with `@PathVariable`, as the following ex
@@ -1490,9 +1491,11 @@ Captured URI variables can be accessed with `@PathVariable`, as the following ex
// ...
}
----
--
You can declare URI variables at the class and method levels, as the following example shows:
@ -1524,6 +1527,7 @@ You can declare URI variables at the class and method levels, as the following e
@@ -1524,6 +1527,7 @@ You can declare URI variables at the class and method levels, as the following e
----
<1> Class-level URI mapping.
<2> Method-level URI mapping.
--
URI variables are automatically converted to the appropriate type or a `TypeMismatchException`
@ -1543,6 +1547,7 @@ The syntax `{varName:regex}` declares a URI variable with a regular expression t
@@ -1543,6 +1547,7 @@ The syntax `{varName:regex}` declares a URI variable with a regular expression t
syntax: `{varName:regex}`. For example, given a URL of `/spring-web-3.0.5.jar`, the following method
@ -1559,6 +1564,7 @@ extracts the name, version, and file extension:
@@ -1559,6 +1564,7 @@ extracts the name, version, and file extension:
// ...
}
----
--
URI path patterns can also have embedded `${...}` placeholders that are resolved on startup
through `PropertySourcesPlaceholderConfigurer` against local, system, environment, and
@ -2660,6 +2666,7 @@ content. The best way to handle a file upload form (for example, from a browser)
@@ -2660,6 +2666,7 @@ content. The best way to handle a file upload form (for example, from a browser)
is through data binding to a <<webflux-ann-modelattrib-method-args, command object>>,
@ -2749,11 +2758,13 @@ You can access individual parts with `@RequestPart`, as the following example sh
@@ -2749,11 +2758,13 @@ You can access individual parts with `@RequestPart`, as the following example sh
----
<1> Using `@RequestPart` to get the metadata.
<2> Using `@RequestPart` to get the file.
--
To deserialize the raw part content (for example, to JSON -- similar to `@RequestBody`),
you can declare a concrete target `Object`, instead of `Part`, as the following example shows:
@ -2773,6 +2784,7 @@ you can declare a concrete target `Object`, instead of `Part`, as the following
@@ -2773,6 +2784,7 @@ you can declare a concrete target `Object`, instead of `Part`, as the following
}
----
<1> Using `@RequestPart` to get the metadata.
--
You can use `@RequestPart` in combination with `jakarta.validation.Valid` or Spring's
`@Validated` annotation, which causes Standard Bean Validation to be applied. Validation
@ -2781,6 +2793,7 @@ The exception contains a `BindingResult` with the error details and can also be
@@ -2781,6 +2793,7 @@ The exception contains a `BindingResult` with the error details and can also be
in the controller method by declaring the argument with an async wrapper and then using
@ -2821,6 +2836,7 @@ as the following example shows:
@@ -2821,6 +2836,7 @@ as the following example shows:
}
----
<1> Using `@RequestBody`.
--
===== `PartEvent`
@ -3347,6 +3363,7 @@ do, except for `@ModelAttribute` (command object) arguments. Typically, they are
@@ -3347,6 +3363,7 @@ do, except for `@ModelAttribute` (command object) arguments. Typically, they are
with a `WebDataBinder` argument, for registrations, and a `void` return value.
The following example uses the `@InitBinder` annotation:
@ -3381,11 +3398,13 @@ The following example uses the `@InitBinder` annotation:
@@ -3381,11 +3398,13 @@ The following example uses the `@InitBinder` annotation:
// ...
}
----
--
Alternatively, when using a `Formatter`-based setup through a shared
`FormattingConversionService`, you could re-use the same approach and register
controller-specific `Formatter` instances, as the following example shows:
@ -3417,6 +3436,8 @@ controller-specific `Formatter` instances, as the following example shows:
@@ -3417,6 +3436,8 @@ controller-specific `Formatter` instances, as the following example shows:
}
----
<1> Adding a custom formatter (a `DateFormatter`, in this case).
--
[[webflux-ann-initbinder-model-design]]
==== Model Design
@ -3823,6 +3844,7 @@ Controllers can add explicit support for HTTP caching. We recommend doing so, si
@@ -3823,6 +3844,7 @@ Controllers can add explicit support for HTTP caching. We recommend doing so, si
against conditional request headers. A controller can add an `ETag` and `Cache-Control`
settings to a `ResponseEntity`, as the following example shows:
@ -3856,6 +3878,7 @@ settings to a `ResponseEntity`, as the following example shows:
@@ -3856,6 +3878,7 @@ settings to a `ResponseEntity`, as the following example shows:
.body(book)
}
----
--
The preceding example sends a 304 (NOT_MODIFIED) response with an empty body if the comparison
to the conditional request headers indicates the content has not changed. Otherwise, the
@ -3864,6 +3887,7 @@ to the conditional request headers indicates the content has not changed. Otherw
@@ -3864,6 +3887,7 @@ to the conditional request headers indicates the content has not changed. Otherw
You can also make the check against conditional request headers in the controller,
@ -290,6 +290,7 @@ allows you to send Strings, or other objects as JSON. For example:
@@ -290,6 +290,7 @@ allows you to send Strings, or other objects as JSON. For example:
We can write a handler function as a lambda, as the following example shows:
val helloWorld: (ServerRequest) -> ServerResponse =
{ ServerResponse.ok().body("Hello World") }
----
--
That is convenient, but in an application we need multiple functions, and multiple inline
lambda's can get messy.
@ -309,6 +311,7 @@ Therefore, it is useful to group related handler functions together into a handl
@@ -309,6 +311,7 @@ Therefore, it is useful to group related handler functions together into a handl
has a similar role as `@Controller` in an annotation-based application.
For example, the following class exposes a reactive `Person` repository:
@ -5144,6 +5144,7 @@ Controllers can add explicit support for HTTP caching. We recommended doing so,
@@ -5144,6 +5144,7 @@ Controllers can add explicit support for HTTP caching. We recommended doing so,
against conditional request headers. A controller can add an `ETag` header and `Cache-Control`
settings to a `ResponseEntity`, as the following example shows:
@ -5176,6 +5177,7 @@ settings to a `ResponseEntity`, as the following example shows:
@@ -5176,6 +5177,7 @@ settings to a `ResponseEntity`, as the following example shows:
.body(book)
}
----
--
The preceding example sends a 304 (NOT_MODIFIED) response with an empty body if the comparison
to the conditional request headers indicates that the content has not changed. Otherwise, the
@ -5184,6 +5186,7 @@ to the conditional request headers indicates that the content has not changed. O
@@ -5184,6 +5186,7 @@ to the conditional request headers indicates that the content has not changed. O
You can also make the check against conditional request headers in the controller,