Consistent use of tabs for sample code in the reference documentation
This commit is contained in:
parent
08c78554b9
commit
6f24c0de17
|
|
@ -4,6 +4,7 @@
|
||||||
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
This part of the reference documentation covers all of those technologies that are
|
This part of the reference documentation covers all of those technologies that are
|
||||||
|
|
|
||||||
|
|
@ -3822,7 +3822,6 @@ Find below the custom `BeanPostProcessor` implementation class definition:
|
||||||
package scripting;
|
package scripting;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
|
|
||||||
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
|
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
[[databuffers]]
|
[[databuffers]]
|
||||||
= Data Buffers and Codecs
|
= Data Buffers and Codecs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
== Introduction
|
== Introduction
|
||||||
|
|
||||||
The `DataBuffer` interface defines an abstraction over byte buffers.
|
The `DataBuffer` interface defines an abstraction over byte buffers.
|
||||||
|
|
@ -9,6 +12,9 @@ Netty does not use `ByteBuffer`, but instead offers `ByteBuf` as an alternative.
|
||||||
Spring's `DataBuffer` is a simple abstraction over `ByteBuf` that can also be used on non-Netty
|
Spring's `DataBuffer` is a simple abstraction over `ByteBuf` that can also be used on non-Netty
|
||||||
platforms (i.e. Servlet 3.1+).
|
platforms (i.e. Servlet 3.1+).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
== `DataBufferFactory`
|
== `DataBufferFactory`
|
||||||
|
|
||||||
The `DataBufferFactory` offers functionality to allocate new data buffers, as well as to wrap
|
The `DataBufferFactory` offers functionality to allocate new data buffers, as well as to wrap
|
||||||
|
|
@ -25,6 +31,9 @@ to be used on Netty platforms, such as Reactor Netty.
|
||||||
The other implementation, the `DefaultDataBufferFactory`, is used on other platforms, such as
|
The other implementation, the `DefaultDataBufferFactory`, is used on other platforms, such as
|
||||||
Servlet 3.1+ servers.
|
Servlet 3.1+ servers.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
== The `DataBuffer` interface
|
== The `DataBuffer` interface
|
||||||
|
|
||||||
The `DataBuffer` interface is similar to `ByteBuffer`, but offers a number of advantages.
|
The `DataBuffer` interface is similar to `ByteBuffer`, but offers a number of advantages.
|
||||||
|
|
@ -54,6 +63,8 @@ Netty platforms, such as Reactor Netty.
|
||||||
The other implementation, the `DefaultDataBuffer`, is used on other platforms, such as Servlet 3.1+
|
The other implementation, the `DefaultDataBuffer`, is used on other platforms, such as Servlet 3.1+
|
||||||
servers.
|
servers.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=== `PooledDataBuffer`
|
=== `PooledDataBuffer`
|
||||||
|
|
||||||
The `PooledDataBuffer` is an extension to `DataBuffer` that adds methods for reference counting.
|
The `PooledDataBuffer` is an extension to `DataBuffer` that adds methods for reference counting.
|
||||||
|
|
@ -67,6 +78,7 @@ buffers.
|
||||||
These methods take a plain `DataBuffer` as parameter, but only call `retain` or `release` if the
|
These methods take a plain `DataBuffer` as parameter, but only call `retain` or `release` if the
|
||||||
passed data buffer is an instance of `PooledDataBuffer`.
|
passed data buffer is an instance of `PooledDataBuffer`.
|
||||||
|
|
||||||
|
|
||||||
[[databuffer-reference-counting]]
|
[[databuffer-reference-counting]]
|
||||||
==== Reference Counting
|
==== Reference Counting
|
||||||
|
|
||||||
|
|
@ -102,7 +114,8 @@ try {
|
||||||
writeDataToBuffer(buffer); <3>
|
writeDataToBuffer(buffer); <3>
|
||||||
putBufferInHttpBody(buffer);
|
putBufferInHttpBody(buffer);
|
||||||
release = false; <4>
|
release = false; <4>
|
||||||
} finally {
|
}
|
||||||
|
finally {
|
||||||
if (release) {
|
if (release) {
|
||||||
DataBufferUtils.release(buffer); <5>
|
DataBufferUtils.release(buffer); <5>
|
||||||
}
|
}
|
||||||
|
|
@ -112,6 +125,7 @@ private void writeDataToBuffer(DataBuffer buffer) throws IOException { <3>
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
<1> A new buffer is allocated.
|
<1> A new buffer is allocated.
|
||||||
<2> A boolean flag indicates whether the allocated buffer should be released.
|
<2> A boolean flag indicates whether the allocated buffer should be released.
|
||||||
<3> This example method loads data into the buffer. Note that the method can throw an `IOException`,
|
<3> This example method loads data into the buffer. Note that the method can throw an `IOException`,
|
||||||
|
|
@ -121,6 +135,8 @@ released as part of sending the HTTP body across the wire.
|
||||||
<5> If an exception did occur, the flag is still set to `true`, and the buffer will be released
|
<5> If an exception did occur, the flag is still set to `true`, and the buffer will be released
|
||||||
here.
|
here.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=== DataBufferUtils
|
=== DataBufferUtils
|
||||||
|
|
||||||
`DataBufferUtils` contains various utility methods that operate on data buffers.
|
`DataBufferUtils` contains various utility methods that operate on data buffers.
|
||||||
|
|
@ -129,6 +145,9 @@ It contains methods for reading a `Flux` of `DataBuffer` objects from an `InputS
|
||||||
`DataBufferUtils` also exposes `retain` and `release` methods that operate on plain `DataBuffer`
|
`DataBufferUtils` also exposes `retain` and `release` methods that operate on plain `DataBuffer`
|
||||||
instances (so that casting to a `PooledDataBuffer` is not required).
|
instances (so that casting to a `PooledDataBuffer` is not required).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[codecs]
|
[codecs]
|
||||||
== Codecs
|
== Codecs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
This part of the reference documentation is concerned with data access and the
|
This part of the reference documentation is concerned with data access and the
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
:doc-spring-gemfire: {doc-root}/spring-gemfire/docs/current/reference
|
:doc-spring-gemfire: {doc-root}/spring-gemfire/docs/current/reference
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
This part of the reference documentation covers the Spring Framework's integration with
|
This part of the reference documentation covers the Spring Framework's integration with
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
[[lanugages]]
|
[[languages]]
|
||||||
= Language Support
|
= Language Support
|
||||||
:doc-root: https://docs.spring.io
|
:doc-root: https://docs.spring.io
|
||||||
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,14 +58,14 @@ for their APIs, thus giving a better Kotlin development experience overall.
|
||||||
|
|
||||||
To retrieve a list of `Foo` objects in Java, one would normally write:
|
To retrieve a list of `Foo` objects in Java, one would normally write:
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
Flux<User> users = client.get().retrieve().bodyToFlux(User.class)
|
Flux<User> users = client.get().retrieve().bodyToFlux(User.class)
|
||||||
----
|
----
|
||||||
|
|
||||||
Whilst with Kotlin and Spring Framework extensions, one is able to write:
|
Whilst with Kotlin and Spring Framework extensions, one is able to write:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
val users = client.get().retrieve().bodyToFlux<User>()
|
val users = client.get().retrieve().bodyToFlux<User>()
|
||||||
// or (both are equivalent)
|
// or (both are equivalent)
|
||||||
|
|
@ -172,19 +172,18 @@ This mechanism is very efficient as it does not require any reflection or CGLIB
|
||||||
|
|
||||||
In Java, one may for example write:
|
In Java, one may for example write:
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
GenericApplicationContext context = new GenericApplicationContext();
|
GenericApplicationContext context = new GenericApplicationContext();
|
||||||
context.registerBean(Foo.class);
|
context.registerBean(Foo.class);
|
||||||
context.registerBean(Bar.class, () -> new
|
context.registerBean(Bar.class, () -> new Bar(context.getBean(Foo.class))
|
||||||
Bar(context.getBean(Foo.class))
|
|
||||||
);
|
);
|
||||||
----
|
----
|
||||||
|
|
||||||
Whilst in Kotlin with reified type parameters and `GenericApplicationContext`
|
Whilst in Kotlin with reified type parameters and `GenericApplicationContext`
|
||||||
Kotlin extensions one can instead simply write:
|
Kotlin extensions one can instead simply write:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
val context = GenericApplicationContext().apply {
|
val context = GenericApplicationContext().apply {
|
||||||
registerBean<Foo>()
|
registerBean<Foo>()
|
||||||
|
|
@ -198,7 +197,7 @@ It declares an `ApplicationContextInitializer` via a clean declarative API
|
||||||
which enables one to deal with profiles and `Environment` for customizing
|
which enables one to deal with profiles and `Environment` for customizing
|
||||||
how beans are registered.
|
how beans are registered.
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
fun beans() = beans {
|
fun beans() = beans {
|
||||||
bean<UserHandler>()
|
bean<UserHandler>()
|
||||||
|
|
@ -235,7 +234,7 @@ is a shortcut for `applicationContext.getBean(Routes::class.java)`.
|
||||||
|
|
||||||
This `beans()` function can then be used to register beans on the application context.
|
This `beans()` function can then be used to register beans on the application context.
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
val context = GenericApplicationContext().apply {
|
val context = GenericApplicationContext().apply {
|
||||||
beans().initialize(this)
|
beans().initialize(this)
|
||||||
|
|
@ -276,7 +275,7 @@ Spring Framework now comes with a
|
||||||
that allows one to leverage the <<web-reactive#webflux-fn,WebFlux functional
|
that allows one to leverage the <<web-reactive#webflux-fn,WebFlux functional
|
||||||
API>> for writing clean and idiomatic Kotlin code:
|
API>> for writing clean and idiomatic Kotlin code:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
router {
|
router {
|
||||||
accept(TEXT_HTML).nest {
|
accept(TEXT_HTML).nest {
|
||||||
|
|
@ -326,7 +325,7 @@ https://github.com/Kotlin/kotlinx.html[kotlinx.html] DSL or simply using Kotlin
|
||||||
This can allow one to write Kotlin templates with full autocompletion and
|
This can allow one to write Kotlin templates with full autocompletion and
|
||||||
refactoring support in a supported IDE:
|
refactoring support in a supported IDE:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
import io.spring.demo.*
|
import io.spring.demo.*
|
||||||
|
|
||||||
|
|
@ -394,7 +393,7 @@ you will be able to write your Kotlin beans without any additional `open` keywor
|
||||||
In Kotlin, it is very convenient and considered best practice to declare read-only properties
|
In Kotlin, it is very convenient and considered best practice to declare read-only properties
|
||||||
within the primary constructor, as in the following example:
|
within the primary constructor, as in the following example:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
class Person(val name: String, val age: Int)
|
class Person(val name: String, val age: Int)
|
||||||
----
|
----
|
||||||
|
|
@ -410,7 +409,7 @@ in the primary constructor:
|
||||||
|
|
||||||
This allows for easy changes to individual properties even if `Person` properties are read-only:
|
This allows for easy changes to individual properties even if `Person` properties are read-only:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
data class Person(val name: String, val age: Int)
|
data class Person(val name: String, val age: Int)
|
||||||
|
|
||||||
|
|
@ -442,7 +441,7 @@ mappings (like with MongoDB, Redis, Cassandra, etc).
|
||||||
Our recommendation is to try and favor constructor injection with `val` read-only (and non-nullable when possible)
|
Our recommendation is to try and favor constructor injection with `val` read-only (and non-nullable when possible)
|
||||||
https://kotlinlang.org/docs/reference/properties.html[properties].
|
https://kotlinlang.org/docs/reference/properties.html[properties].
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
@Component
|
@Component
|
||||||
class YourBean(
|
class YourBean(
|
||||||
|
|
@ -461,7 +460,7 @@ explicit `@Autowired constructor` in the example shown above.
|
||||||
If one really needs to use field injection, use the `lateinit var` construct,
|
If one really needs to use field injection, use the `lateinit var` construct,
|
||||||
i.e.,
|
i.e.,
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
@Component
|
@Component
|
||||||
class YourBean {
|
class YourBean {
|
||||||
|
|
@ -487,7 +486,7 @@ character will need to be escaped by writing `@Value("\${property}")`.
|
||||||
As an alternative, it is possible to customize the properties placeholder prefix by declaring
|
As an alternative, it is possible to customize the properties placeholder prefix by declaring
|
||||||
the following configuration beans:
|
the following configuration beans:
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
@Bean
|
@Bean
|
||||||
fun propertyConfigurer() = PropertySourcesPlaceholderConfigurer().apply {
|
fun propertyConfigurer() = PropertySourcesPlaceholderConfigurer().apply {
|
||||||
|
|
@ -495,11 +494,10 @@ fun propertyConfigurer() = PropertySourcesPlaceholderConfigurer().apply {
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
Existing code (like Spring Boot actuators or `@LocalServerPort`) that
|
Existing code (like Spring Boot actuators or `@LocalServerPort`) that uses the `${...}` syntax,
|
||||||
uses the `${...}` syntax, can be customised with configuration beans, like
|
can be customised with configuration beans, like as follows:
|
||||||
this:
|
|
||||||
|
|
||||||
[source,kotlin]
|
[source,kotlin,indent=0]
|
||||||
----
|
----
|
||||||
@Bean
|
@Bean
|
||||||
fun kotlinPropertyConfigurer() = PropertySourcesPlaceholderConfigurer().apply {
|
fun kotlinPropertyConfigurer() = PropertySourcesPlaceholderConfigurer().apply {
|
||||||
|
|
@ -535,7 +533,7 @@ attribute it is specified as a `vararg` parameter.
|
||||||
To understand what that means, let's take `@RequestMapping`, which is one
|
To understand what that means, let's take `@RequestMapping`, which is one
|
||||||
of the most widely used Spring annotations as an example. This Java annotation is declared as:
|
of the most widely used Spring annotations as an example. This Java annotation is declared as:
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
public @interface RequestMapping {
|
public @interface RequestMapping {
|
||||||
|
|
||||||
|
|
@ -568,8 +566,8 @@ use a shortcut annotation such as `@GetMapping` or `@PostMapping`, etc.
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
Remininder: if the `@RequestMapping` `method` attribute is not specified, all HTTP methods will be matched,
|
Reminder: If the `@RequestMapping` `method` attribute is not specified,
|
||||||
not only the `GET` methods.
|
all HTTP methods will be matched, not only the `GET` methods.
|
||||||
====
|
====
|
||||||
|
|
||||||
Improving the syntax and consistency of Kotlin annotation array attributes is discussed in
|
Improving the syntax and consistency of Kotlin annotation array attributes is discussed in
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
|
[[overview]]
|
||||||
|
= Spring Framework Overview
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 1
|
:toclevels: 1
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
[[overview]]
|
|
||||||
= Spring Framework Overview
|
|
||||||
|
|
||||||
Spring makes it easy to create Java enterprise applications. It provides everything you
|
Spring makes it easy to create Java enterprise applications. It provides everything you
|
||||||
need to embrace the Java language in an enterprise environment, with support for Groovy
|
need to embrace the Java language in an enterprise environment, with support for Groovy
|
||||||
and Kotlin as alternative languages on the JVM, and with the flexibility to create many
|
and Kotlin as alternative languages on the JVM, and with the flexibility to create many
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ some subset of it:
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
client = WebTestClient.bindToApplicationContext(context).build(); // <3>
|
client = WebTestClient.bindToApplicationContext(context).build(); // <3>
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
:doc-spring-boot: {doc-root}/spring-boot/docs/current/reference
|
:doc-spring-boot: {doc-root}/spring-boot/docs/current/reference
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
The adoption of the test-driven-development (TDD) approach to software
|
The adoption of the test-driven-development (TDD) approach to software
|
||||||
|
|
@ -4297,7 +4298,6 @@ class ExampleTests {
|
||||||
.andExpect(content().contentType("application/json"))
|
.andExpect(content().contentType("application/json"))
|
||||||
.andExpect(jsonPath("$.name").value("Lee"));
|
.andExpect(jsonPath("$.name").value("Lee"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4761,7 +4761,7 @@ paging through all messages. How would you go about testing it?
|
||||||
|
|
||||||
With Spring MVC Test, we can easily test if we are able to create a `Message`.
|
With Spring MVC Test, we can easily test if we are able to create a `Message`.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
MockHttpServletRequestBuilder createMessage = post("/messages/")
|
MockHttpServletRequestBuilder createMessage = post("/messages/")
|
||||||
.param("summary", "Spring Rocks")
|
.param("summary", "Spring Rocks")
|
||||||
|
|
@ -4775,7 +4775,7 @@ mockMvc.perform(createMessage)
|
||||||
What if we want to test our form view that allows us to create the message? For example,
|
What if we want to test our form view that allows us to create the message? For example,
|
||||||
assume our form looks like the following snippet:
|
assume our form looks like the following snippet:
|
||||||
|
|
||||||
[source,xml]
|
[source,xml,indent=0]
|
||||||
----
|
----
|
||||||
<form id="messageForm" action="/messages/" method="post">
|
<form id="messageForm" action="/messages/" method="post">
|
||||||
<div class="pull-right"><a href="/messages/">Messages</a></div>
|
<div class="pull-right"><a href="/messages/">Messages</a></div>
|
||||||
|
|
@ -4795,7 +4795,7 @@ assume our form looks like the following snippet:
|
||||||
How do we ensure that our form will produce the correct request to create a new message? A
|
How do we ensure that our form will produce the correct request to create a new message? A
|
||||||
naive attempt would look like this:
|
naive attempt would look like this:
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
mockMvc.perform(get("/messages/form"))
|
mockMvc.perform(get("/messages/form"))
|
||||||
.andExpect(xpath("//input[@name='summary']").exists())
|
.andExpect(xpath("//input[@name='summary']").exists())
|
||||||
|
|
@ -4807,7 +4807,7 @@ This test has some obvious drawbacks. If we update our controller to use the par
|
||||||
form is out of synch with the controller. To resolve this we can combine our two tests.
|
form is out of synch with the controller. To resolve this we can combine our two tests.
|
||||||
|
|
||||||
[[spring-mvc-test-server-htmlunit-mock-mvc-test]]
|
[[spring-mvc-test-server-htmlunit-mock-mvc-test]]
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
String summaryParamName = "summary";
|
String summaryParamName = "summary";
|
||||||
String textParamName = "text";
|
String textParamName = "text";
|
||||||
|
|
@ -4908,7 +4908,7 @@ In order to use HtmlUnit with Apache HttpComponents 4.5+, you will need to use H
|
||||||
We can easily create an HtmlUnit `WebClient` that integrates with `MockMvc` using the
|
We can easily create an HtmlUnit `WebClient` that integrates with `MockMvc` using the
|
||||||
`MockMvcWebClientBuilder` as follows.
|
`MockMvcWebClientBuilder` as follows.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
@Autowired
|
@Autowired
|
||||||
WebApplicationContext context;
|
WebApplicationContext context;
|
||||||
|
|
@ -4941,7 +4941,7 @@ Now we can use HtmlUnit as we normally would, but without the need to deploy our
|
||||||
application to a Servlet container. For example, we can request the view to create
|
application to a Servlet container. For example, we can request the view to create
|
||||||
a message with the following.
|
a message with the following.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form");
|
HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form");
|
||||||
----
|
----
|
||||||
|
|
@ -4955,7 +4955,7 @@ illustrated in <<Advanced MockMvcWebClientBuilder>>.
|
||||||
Once we have a reference to the `HtmlPage`, we can then fill out the form and submit
|
Once we have a reference to the `HtmlPage`, we can then fill out the form and submit
|
||||||
it to create a message.
|
it to create a message.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm");
|
HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm");
|
||||||
HtmlTextInput summaryInput = createMsgFormPage.getHtmlElementById("summary");
|
HtmlTextInput summaryInput = createMsgFormPage.getHtmlElementById("summary");
|
||||||
|
|
@ -4969,7 +4969,7 @@ HtmlPage newMessagePage = submit.click();
|
||||||
Finally, we can verify that a new message was created successfully. The following
|
Finally, we can verify that a new message was created successfully. The following
|
||||||
assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] library.
|
assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] library.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123");
|
assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123");
|
||||||
String id = newMessagePage.getHtmlElementById("id").getTextContent();
|
String id = newMessagePage.getHtmlElementById("id").getTextContent();
|
||||||
|
|
@ -4999,7 +4999,7 @@ In the examples so far, we have used `MockMvcWebClientBuilder` in the simplest w
|
||||||
by building a `WebClient` based on the `WebApplicationContext` loaded for us by the Spring
|
by building a `WebClient` based on the `WebApplicationContext` loaded for us by the Spring
|
||||||
TestContext Framework. This approach is repeated here.
|
TestContext Framework. This approach is repeated here.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
@Autowired
|
@Autowired
|
||||||
WebApplicationContext context;
|
WebApplicationContext context;
|
||||||
|
|
@ -5016,7 +5016,7 @@ public void setup() {
|
||||||
|
|
||||||
We can also specify additional configuration options.
|
We can also specify additional configuration options.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
WebClient webClient;
|
WebClient webClient;
|
||||||
|
|
||||||
|
|
@ -5037,7 +5037,7 @@ public void setup() {
|
||||||
As an alternative, we can perform the exact same setup by configuring the `MockMvc`
|
As an alternative, we can perform the exact same setup by configuring the `MockMvc`
|
||||||
instance separately and supplying it to the `MockMvcWebClientBuilder` as follows.
|
instance separately and supplying it to the `MockMvcWebClientBuilder` as follows.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
MockMvc mockMvc = MockMvcBuilders
|
MockMvc mockMvc = MockMvcBuilders
|
||||||
.webAppContextSetup(context)
|
.webAppContextSetup(context)
|
||||||
|
|
@ -5094,7 +5094,7 @@ be displayed afterwards.
|
||||||
If one of the fields were named "summary", then we might have something like the
|
If one of the fields were named "summary", then we might have something like the
|
||||||
following repeated in multiple places within our tests.
|
following repeated in multiple places within our tests.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary");
|
HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary");
|
||||||
summaryInput.setValueAttribute(summary);
|
summaryInput.setValueAttribute(summary);
|
||||||
|
|
@ -5104,7 +5104,7 @@ So what happens if we change the `id` to "smmry"? Doing so would force us to upd
|
||||||
of our tests to incorporate this change! Of course, this violates the _DRY Principle_; so
|
of our tests to incorporate this change! Of course, this violates the _DRY Principle_; so
|
||||||
we should ideally extract this code into its own method as follows.
|
we should ideally extract this code into its own method as follows.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
public HtmlPage createMessage(HtmlPage currentPage, String summary, String text) {
|
public HtmlPage createMessage(HtmlPage currentPage, String summary, String text) {
|
||||||
setSummary(currentPage, summary);
|
setSummary(currentPage, summary);
|
||||||
|
|
@ -5122,7 +5122,7 @@ This ensures that we do not have to update all of our tests if we change the UI.
|
||||||
We might even take this a step further and place this logic within an Object that
|
We might even take this a step further and place this logic within an Object that
|
||||||
represents the `HtmlPage` we are currently on.
|
represents the `HtmlPage` we are currently on.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
public class CreateMessagePage {
|
public class CreateMessagePage {
|
||||||
|
|
||||||
|
|
@ -5171,7 +5171,7 @@ includes a test dependency on `org.seleniumhq.selenium:selenium-htmlunit-driver`
|
||||||
We can easily create a Selenium `WebDriver` that integrates with `MockMvc` using the
|
We can easily create a Selenium `WebDriver` that integrates with `MockMvc` using the
|
||||||
`MockMvcHtmlUnitDriverBuilder` as follows.
|
`MockMvcHtmlUnitDriverBuilder` as follows.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
@Autowired
|
@Autowired
|
||||||
WebApplicationContext context;
|
WebApplicationContext context;
|
||||||
|
|
@ -5204,14 +5204,14 @@ Now we can use WebDriver as we normally would, but without the need to deploy ou
|
||||||
application to a Servlet container. For example, we can request the view to create
|
application to a Servlet container. For example, we can request the view to create
|
||||||
a message with the following.
|
a message with the following.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
CreateMessagePage page = CreateMessagePage.to(driver);
|
CreateMessagePage page = CreateMessagePage.to(driver);
|
||||||
----
|
----
|
||||||
|
|
||||||
We can then fill out the form and submit it to create a message.
|
We can then fill out the form and submit it to create a message.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
ViewMessagePage viewMessagePage =
|
ViewMessagePage viewMessagePage =
|
||||||
page.createMessage(ViewMessagePage.class, expectedSummary, expectedText);
|
page.createMessage(ViewMessagePage.class, expectedSummary, expectedText);
|
||||||
|
|
@ -5223,7 +5223,7 @@ Pattern_. As we mentioned in <<spring-mvc-test-server-htmlunit-webdriver-why>>,
|
||||||
use the Page Object Pattern with HtmlUnit, but it is much easier with WebDriver. Let's
|
use the Page Object Pattern with HtmlUnit, but it is much easier with WebDriver. Let's
|
||||||
take a look at our new `CreateMessagePage` implementation.
|
take a look at our new `CreateMessagePage` implementation.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
public class CreateMessagePage
|
public class CreateMessagePage
|
||||||
extends AbstractPage { // <1>
|
extends AbstractPage { // <1>
|
||||||
|
|
@ -5277,7 +5277,7 @@ annotation to look up our submit button using a css selector, *input[type=submit
|
||||||
Finally, we can verify that a new message was created successfully. The following
|
Finally, we can verify that a new message was created successfully. The following
|
||||||
assertions use the https://code.google.com/p/fest/[FEST assertion library].
|
assertions use the https://code.google.com/p/fest/[FEST assertion library].
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
assertThat(viewMessagePage.getMessage()).isEqualTo(expectedMessage);
|
assertThat(viewMessagePage.getMessage()).isEqualTo(expectedMessage);
|
||||||
assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message");
|
assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message");
|
||||||
|
|
@ -5286,7 +5286,7 @@ assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new m
|
||||||
We can see that our `ViewMessagePage` allows us to interact with our custom domain
|
We can see that our `ViewMessagePage` allows us to interact with our custom domain
|
||||||
model. For example, it exposes a method that returns a `Message` object.
|
model. For example, it exposes a method that returns a `Message` object.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
public Message getMessage() throws ParseException {
|
public Message getMessage() throws ParseException {
|
||||||
Message message = new Message();
|
Message message = new Message();
|
||||||
|
|
@ -5302,7 +5302,7 @@ We can then leverage the rich domain objects in our assertions.
|
||||||
|
|
||||||
Lastly, don't forget to _close_ the `WebDriver` instance when the test is complete.
|
Lastly, don't forget to _close_ the `WebDriver` instance when the test is complete.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
@After
|
@After
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
|
@ -5322,7 +5322,7 @@ In the examples so far, we have used `MockMvcHtmlUnitDriverBuilder` in the simpl
|
||||||
possible, by building a `WebDriver` based on the `WebApplicationContext` loaded for us by
|
possible, by building a `WebDriver` based on the `WebApplicationContext` loaded for us by
|
||||||
the Spring TestContext Framework. This approach is repeated here.
|
the Spring TestContext Framework. This approach is repeated here.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
@Autowired
|
@Autowired
|
||||||
WebApplicationContext context;
|
WebApplicationContext context;
|
||||||
|
|
@ -5339,7 +5339,7 @@ public void setup() {
|
||||||
|
|
||||||
We can also specify additional configuration options.
|
We can also specify additional configuration options.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
WebDriver driver;
|
WebDriver driver;
|
||||||
|
|
||||||
|
|
@ -5360,7 +5360,7 @@ public void setup() {
|
||||||
As an alternative, we can perform the exact same setup by configuring the `MockMvc`
|
As an alternative, we can perform the exact same setup by configuring the `MockMvc`
|
||||||
instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder` as follows.
|
instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder` as follows.
|
||||||
|
|
||||||
[source,java]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
MockMvc mockMvc = MockMvcBuilders
|
MockMvc mockMvc = MockMvcBuilders
|
||||||
.webAppContextSetup(context)
|
.webAppContextSetup(context)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
This part of the documentation covers support for reactive stack, web applications built on a
|
This part of the documentation covers support for reactive stack, web applications built on a
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
|
||||||
:toc: left
|
:toc: left
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
:tabsize: 4
|
||||||
:docinfo1:
|
:docinfo1:
|
||||||
|
|
||||||
This part of the documentation covers support for Servlet stack, web applications built on the
|
This part of the documentation covers support for Servlet stack, web applications built on the
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,6 @@ decoding HTTP messages:
|
||||||
WebClient webClient = WebClient.builder()
|
WebClient webClient = WebClient.builder()
|
||||||
.exchangeStrategies(strategies)
|
.exchangeStrategies(strategies)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
The builder can be used to insert <<webflux-client-filter>>.
|
The builder can be used to insert <<webflux-client-filter>>.
|
||||||
|
|
@ -307,11 +306,9 @@ build a new `WebClient`, based on, but without affecting the current instance:
|
||||||
----
|
----
|
||||||
WebClient client = WebClient.builder()
|
WebClient client = WebClient.builder()
|
||||||
.filter((request, next) -> {
|
.filter((request, next) -> {
|
||||||
|
|
||||||
ClientRequest filtered = ClientRequest.from(request)
|
ClientRequest filtered = ClientRequest.from(request)
|
||||||
.header("foo", "bar")
|
.header("foo", "bar")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return next.exchange(filtered);
|
return next.exchange(filtered);
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ public class MyWebSocketHandler implements WebSocketHandler {
|
||||||
public Mono<Void> handle(WebSocketSession session) {
|
public Mono<Void> handle(WebSocketSession session) {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -67,7 +66,6 @@ static class WebConfig {
|
||||||
public WebSocketHandlerAdapter handlerAdapter() {
|
public WebSocketHandlerAdapter handlerAdapter() {
|
||||||
return new WebSocketHandlerAdapter();
|
return new WebSocketHandlerAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -112,7 +110,6 @@ static class WebConfig {
|
||||||
strategy.setMaxSessionIdleTimeout(0L);
|
strategy.setMaxSessionIdleTimeout(0L);
|
||||||
return new HandshakeWebSocketService(strategy);
|
return new HandshakeWebSocketService(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,19 +53,16 @@ public class MyWebApplicationInitializer implements WebApplicationInitializer {
|
||||||
public void onStartup(ServletContext servletCxt) {
|
public void onStartup(ServletContext servletCxt) {
|
||||||
|
|
||||||
// Load Spring web application configuration
|
// Load Spring web application configuration
|
||||||
AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext();
|
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
|
||||||
cxt.register(AppConfig.class);
|
ac.register(AppConfig.class);
|
||||||
cxt.refresh();
|
ac.refresh();
|
||||||
|
|
||||||
// Create DispatcherServlet
|
// Create and register the DispatcherServlet
|
||||||
DispatcherServlet servlet = new DispatcherServlet(cxt);
|
DispatcherServlet servlet = new DispatcherServlet(ac);
|
||||||
|
|
||||||
// Register and map the Servlet
|
|
||||||
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
|
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
|
||||||
registration.setLoadOnStartup(1);
|
registration.setLoadOnStartup(1);
|
||||||
registration.addMapping("/app/*");
|
registration.addMapping("/app/*");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -154,12 +151,12 @@ Below is example configuration with a `WebApplicationContext` hierarchy:
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getRootConfigClasses() {
|
protected Class<?>[] getRootConfigClasses() {
|
||||||
return new Class[] { RootConfig.class };
|
return new Class<?[] { RootConfig.class };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getServletConfigClasses() {
|
protected Class<?>[] getServletConfigClasses() {
|
||||||
return new Class[] { App1Config.class };
|
return new Class<?[] { App1Config.class };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -319,7 +316,6 @@ example of registering a `DispatcherServlet`:
|
||||||
registration.setLoadOnStartup(1);
|
registration.setLoadOnStartup(1);
|
||||||
registration.addMapping("/");
|
registration.addMapping("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -351,7 +347,6 @@ This is recommended for applications that use Java-based Spring configuration:
|
||||||
protected String[] getServletMappings() {
|
protected String[] getServletMappings() {
|
||||||
return new String[] { "/" };
|
return new String[] { "/" };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -379,7 +374,6 @@ If using XML-based Spring configuration, you should extend directly from
|
||||||
protected String[] getServletMappings() {
|
protected String[] getServletMappings() {
|
||||||
return new String[] { "/" };
|
return new String[] { "/" };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -1933,13 +1927,10 @@ following the `@ModelAttribute` argument:
|
||||||
----
|
----
|
||||||
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
|
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
|
||||||
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
|
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
|
||||||
|
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return "petForm";
|
return "petForm";
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -1967,7 +1958,6 @@ public Account findAccount(@PathVariable String accountId) {
|
||||||
@PostMapping("update")
|
@PostMapping("update")
|
||||||
public String update(@Valid AccountUpdateForm form, BindingResult result,
|
public String update(@Valid AccountUpdateForm form, BindingResult result,
|
||||||
**@ModelAttribute(binding=false)** Account account) {
|
**@ModelAttribute(binding=false)** Account account) {
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
@ -1982,14 +1972,11 @@ subsequently reported back to the user:
|
||||||
----
|
----
|
||||||
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
|
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
|
||||||
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
|
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
|
||||||
|
|
||||||
new PetValidator().validate(pet, result);
|
new PetValidator().validate(pet, result);
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return "petForm";
|
return "petForm";
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2001,13 +1988,10 @@ annotation:
|
||||||
----
|
----
|
||||||
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
|
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
|
||||||
public String processSubmit(**@Valid @ModelAttribute("pet") Pet pet**, BindingResult result) {
|
public String processSubmit(**@Valid @ModelAttribute("pet") Pet pet**, BindingResult result) {
|
||||||
|
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return "petForm";
|
return "petForm";
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2327,31 +2311,32 @@ object and converting from an object to the HTTP response body. The
|
||||||
`RequestMappingHandlerAdapter` supports the `@RequestBody` annotation with the following
|
`RequestMappingHandlerAdapter` supports the `@RequestBody` annotation with the following
|
||||||
default `HttpMessageConverters`:
|
default `HttpMessageConverters`:
|
||||||
|
|
||||||
* `ByteArrayHttpMessageConverter` converts byte arrays.
|
* `ByteArrayHttpMessageConverter` converts byte arrays
|
||||||
* `StringHttpMessageConverter` converts strings.
|
* `StringHttpMessageConverter` converts strings
|
||||||
* `FormHttpMessageConverter` converts form data to/from a MultiValueMap<String, String>.
|
* `FormHttpMessageConverter` converts form data to/from a `MultiValueMap<String, String>`
|
||||||
* `SourceHttpMessageConverter` converts to/from a javax.xml.transform.Source.
|
* `SourceHttpMessageConverter` converts to/from a `javax.xml.transform.Source``
|
||||||
|
|
||||||
For more information on these converters, see <<integration.adoc#rest-message-conversion,
|
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
|
Message Converters>>. Also note that if using the MVC namespace or the MVC Java config,
|
||||||
wider range of message converters are registered by default. See <<mvc-config-enable>> for
|
a wider range of message converters are registered by default, including default JSON
|
||||||
more information.
|
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.
|
||||||
|
|
||||||
If you intend to read and write XML, you will need to configure the
|
For a custom example, if you intend to read and write XML using the `spring-oxm` module,
|
||||||
`MarshallingHttpMessageConverter` with a specific `Marshaller` and an `Unmarshaller`
|
you need to configure the `MarshallingHttpMessageConverter` with a specific `Marshaller`
|
||||||
implementation from the `org.springframework.oxm` package. The example below shows how
|
implementation from the `org.springframework.oxm` package. The example below shows how to
|
||||||
to do that directly in your configuration but if your application is configured through
|
do that directly in your configuration but if your application is configured through the
|
||||||
the MVC namespace or the MVC Java config see <<mvc-config-enable>> instead.
|
MVC namespace or the MVC Java config see <<mvc-config-enable>> instead.
|
||||||
|
|
||||||
[source,xml,indent=0]
|
[source,xml,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
|
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
|
||||||
<property name="messageConverters">
|
<property name="messageConverters">
|
||||||
<util:list id="beanList">
|
<list>
|
||||||
<ref bean="stringHttpMessageConverter"/>
|
<ref bean="stringHttpMessageConverter"/>
|
||||||
<ref bean="marshallingHttpMessageConverter"/>
|
<ref bean="marshallingHttpMessageConverter"/>
|
||||||
</util:list>
|
<list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
@ -2360,11 +2345,10 @@ the MVC namespace or the MVC Java config see <<mvc-config-enable>> instead.
|
||||||
|
|
||||||
<bean id="marshallingHttpMessageConverter"
|
<bean id="marshallingHttpMessageConverter"
|
||||||
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
|
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
|
||||||
<property name="marshaller" ref="castorMarshaller"/>
|
<constructor-arg ref="xstreamMarshaller"/>
|
||||||
<property name="unmarshaller" ref="castorMarshaller"/>
|
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
|
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
|
||||||
----
|
----
|
||||||
|
|
||||||
An `@RequestBody` method parameter can be annotated with `@Valid`, in which case it will
|
An `@RequestBody` method parameter can be annotated with `@Valid`, in which case it will
|
||||||
|
|
@ -2833,7 +2817,6 @@ Spring MVC also provides a mechanism for building links to controller methods. F
|
||||||
|
|
||||||
@GetMapping("/bookings/{booking}")
|
@GetMapping("/bookings/{booking}")
|
||||||
public String getBooking(@PathVariable Long booking) {
|
public String getBooking(@PathVariable Long booking) {
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4029,7 +4012,7 @@ In XML use the `<mvc:annotation-driven>` element:
|
||||||
|
|
||||||
The above registers a number of Spring MVC
|
The above registers a number of Spring MVC
|
||||||
<<mvc-servlet-special-bean-types,infrastructure beans>> also adapting to dependencies
|
<<mvc-servlet-special-bean-types,infrastructure beans>> also adapting to dependencies
|
||||||
available on the classpath -- for JSON, XML, etc.
|
available on the classpath: e.g. payload converters for JSON, XML, etc.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4047,7 +4030,6 @@ In Java config implement `WebMvcConfigurer` interface:
|
||||||
public class WebConfig implements WebMvcConfigurer {
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
// Implement configuration methods...
|
// Implement configuration methods...
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4079,7 +4061,6 @@ In Java config, register custom formatters and converters:
|
||||||
public void addFormatters(FormatterRegistry registry) {
|
public void addFormatters(FormatterRegistry registry) {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4153,7 +4134,6 @@ In Java config, you can customize the global `Validator` instance:
|
||||||
public Validator getValidator(); {
|
public Validator getValidator(); {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4219,7 +4199,6 @@ In Java config, register interceptors to apply to incoming requests:
|
||||||
registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
|
registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
|
||||||
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
|
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4324,7 +4303,6 @@ Below is an example that adds Jackson JSON and XML converters with a customized
|
||||||
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
|
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
|
||||||
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.xml().build()));
|
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.xml().build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4406,7 +4384,6 @@ An example of forwarding a request for `"/"` to a view called `"home"` in Java:
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
registry.addViewController("/").setViewName("home");
|
registry.addViewController("/").setViewName("home");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4442,7 +4419,6 @@ JSON rendering:
|
||||||
registry.enableContentNegotiation(new MappingJackson2JsonView());
|
registry.enableContentNegotiation(new MappingJackson2JsonView());
|
||||||
registry.jsp();
|
registry.jsp();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4506,7 +4482,6 @@ In Java config simply add the respective "Configurer" bean:
|
||||||
configurer.setTemplateLoaderPath("/WEB-INF/");
|
configurer.setTemplateLoaderPath("/WEB-INF/");
|
||||||
return configurer;
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4541,7 +4516,6 @@ In Java config:
|
||||||
.addResourceLocations("/public", "classpath:/static/")
|
.addResourceLocations("/public", "classpath:/static/")
|
||||||
.setCachePeriod(31556926);
|
.setCachePeriod(31556926);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4584,7 +4558,6 @@ For example in Java config;
|
||||||
.resourceChain(true)
|
.resourceChain(true)
|
||||||
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
|
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4647,7 +4620,6 @@ To enable the feature using the default setup use:
|
||||||
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||||
configurer.enable();
|
configurer.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -4797,7 +4769,6 @@ hook of the Spring `ApplicationContext`:
|
||||||
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
|
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -840,7 +840,6 @@ public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -1470,7 +1469,6 @@ In Java config:
|
||||||
registry.setApplicationDestinationPrefixes("/app");
|
registry.setApplicationDestinationPrefixes("/app");
|
||||||
registry.setPathMatcher(new AntPathMatcher("."));
|
registry.setPathMatcher(new AntPathMatcher("."));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -1511,8 +1509,8 @@ And below is a simple example to illustrate a controller with "." separator:
|
||||||
|
|
||||||
@MessageMapping("bar.{baz}")
|
@MessageMapping("bar.{baz}")
|
||||||
public void handleBaz(@DestinationVariable String baz) {
|
public void handleBaz(@DestinationVariable String baz) {
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -1619,18 +1617,14 @@ user and associate it with subsequent STOMP messages on the same session:
|
||||||
@Override
|
@Override
|
||||||
public void configureClientInboundChannel(ChannelRegistration registration) {
|
public void configureClientInboundChannel(ChannelRegistration registration) {
|
||||||
registration.setInterceptors(new ChannelInterceptorAdapter() {
|
registration.setInterceptors(new ChannelInterceptorAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||||
|
|
||||||
StompHeaderAccessor accessor =
|
StompHeaderAccessor accessor =
|
||||||
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
||||||
|
|
||||||
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
|
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
|
||||||
Authentication user = ... ; // access authentication header(s)
|
Authentication user = ... ; // access authentication header(s)
|
||||||
accessor.setUser(user);
|
accessor.setUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1711,7 +1705,6 @@ public class MyController {
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
While user destinations generally imply an authenticated user, it isn't required
|
While user destinations generally imply an authenticated user, it isn't required
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue