summaryrefslogtreecommitdiff
path: root/src/asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/asciidoc')
-rw-r--r--src/asciidoc/appendix.adoc4
-rw-r--r--src/asciidoc/appx-spring-form-tld.adoc5
-rw-r--r--src/asciidoc/core-aop.adoc62
-rw-r--r--src/asciidoc/core-beans.adoc247
-rw-r--r--src/asciidoc/core-expressions.adoc25
-rw-r--r--src/asciidoc/core-resources.adoc2
-rw-r--r--src/asciidoc/core-validation.adoc4
-rw-r--r--src/asciidoc/data-access.adoc31
-rw-r--r--src/asciidoc/index-docinfo.xml2
-rw-r--r--src/asciidoc/integration.adoc88
-rw-r--r--src/asciidoc/overview.adoc4
-rw-r--r--src/asciidoc/testing.adoc930
-rw-r--r--src/asciidoc/web-cors.adoc42
-rw-r--r--src/asciidoc/web-mvc.adoc494
-rw-r--r--src/asciidoc/web-portlet.adoc10
-rw-r--r--src/asciidoc/web-view.adoc27
-rw-r--r--src/asciidoc/web-websocket.adoc76
-rw-r--r--src/asciidoc/web.adoc2
-rw-r--r--src/asciidoc/whats-new.adoc128
19 files changed, 1365 insertions, 818 deletions
diff --git a/src/asciidoc/appendix.adoc b/src/asciidoc/appendix.adoc
index 98091bec..f5bc66b0 100644
--- a/src/asciidoc/appendix.adoc
+++ b/src/asciidoc/appendix.adoc
@@ -3163,9 +3163,9 @@ the correct schema so that the tags in the `cache` namespace are available to yo
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- __xmlns:jdbc="http://www.springframework.org/schema/cache"__ xsi:schemaLocation="
+ __xmlns:cache="http://www.springframework.org/schema/cache"__ xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- __http://www.springframework.org/schema/cache http://www.springframework.org/schema/jdbc/spring-cache.xsd"__> <!-- bean definitions here -->
+ __http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"__> <!-- bean definitions here -->
</beans>
----
diff --git a/src/asciidoc/appx-spring-form-tld.adoc b/src/asciidoc/appx-spring-form-tld.adoc
index fd5ac0bd..9c996924 100644
--- a/src/asciidoc/appx-spring-form-tld.adoc
+++ b/src/asciidoc/appx-spring-form-tld.adoc
@@ -528,11 +528,6 @@ Renders an HTML 'form' tag and exposes a binding path to inner tags for binding.
| true
| HTML Required Attribute
-| commandName
-| false
-| true
-| Name of the model attribute under which the form object is exposed. Defaults to 'command'.
-
| cssClass
| false
| true
diff --git a/src/asciidoc/core-aop.adoc b/src/asciidoc/core-aop.adoc
index 57dffd37..8c8022c1 100644
--- a/src/asciidoc/core-aop.adoc
+++ b/src/asciidoc/core-aop.adoc
@@ -398,10 +398,10 @@ releases to support more of the AspectJ pointcut designators.
Because Spring AOP limits matching to only method execution join points, the discussion
of the pointcut designators above gives a narrower definition than you will find in the
AspectJ programming guide. In addition, AspectJ itself has type-based semantics and at
-an execution join point both '++this++' and '++target++' refer to the same object - the
+an execution join point both `this` and `target` refer to the same object - the
object executing the method. Spring AOP is a proxy-based system and differentiates
-between the proxy object itself (bound to '++this++') and the target object behind the
-proxy (bound to '++target++').
+between the proxy object itself (bound to `this`) and the target object behind the
+proxy (bound to `target`).
[NOTE]
====
@@ -418,9 +418,9 @@ different characteristics, so be sure to make yourself familiar with weaving fir
before making a decision.
====
-Spring AOP also supports an additional PCD named '++bean++'. This PCD allows you to limit
+Spring AOP also supports an additional PCD named `bean`. This PCD allows you to limit
the matching of join points to a particular named Spring bean, or to a set of named
-Spring beans (when using wildcards). The '++bean++' PCD has the following form:
+Spring beans (when using wildcards). The `bean` PCD has the following form:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -428,19 +428,19 @@ Spring beans (when using wildcards). The '++bean++' PCD has the following form:
bean(idOrNameOfBean)
----
-The '++idOrNameOfBean++' token can be the name of any Spring bean: limited wildcard
-support using the '++*++' character is provided, so if you establish some naming
-conventions for your Spring beans you can quite easily write a '++bean++' PCD expression
-to pick them out. As is the case with other pointcut designators, the '++bean++' PCD can
+The `idOrNameOfBean` token can be the name of any Spring bean: limited wildcard
+support using the `*` character is provided, so if you establish some naming
+conventions for your Spring beans you can quite easily write a `bean` PCD expression
+to pick them out. As is the case with other pointcut designators, the `bean` PCD can
be &&'ed, ||'ed, and ! (negated) too.
[NOTE]
====
-Please note that the '++bean++' PCD is __only__ supported in Spring AOP - and __not__ in
+Please note that the `bean` PCD is __only__ supported in Spring AOP - and __not__ in
native AspectJ weaving. It is a Spring-specific extension to the standard PCDs that
AspectJ defines and therefore not available for aspects declared in the `@Aspect` model.
-The '++bean++' PCD operates at the __instance__ level (building on the Spring bean name
+The `bean` PCD operates at the __instance__ level (building on the Spring bean name
concept) rather than at the type level only (which is what weaving-based AOP is limited
to). Instance-based pointcut designators are a special capability of Spring's
proxy-based AOP framework and its close integration with the Spring bean factory, where
@@ -769,7 +769,7 @@ how to make the annotation object(s) available in the advice body.
====
* any join point (method execution only in Spring AOP) on a Spring bean named
- '++tradeService++':
+ `tradeService`:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -778,7 +778,7 @@ how to make the annotation object(s) available in the advice body.
----
* any join point (method execution only in Spring AOP) on Spring beans having names that
- match the wildcard expression '++*Service++':
+ match the wildcard expression `*Service`:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -2391,7 +2391,7 @@ In the XML style I can declare the first two pointcuts:
----
The downside of the XML approach is that you cannot define the
-'++accountPropertyAccess++' pointcut by combining these definitions.
+`accountPropertyAccess` pointcut by combining these definitions.
The @AspectJ style supports additional instantiation models, and richer pointcut
composition. It has the advantage of keeping the aspect as a modular unit. It also has
@@ -2467,7 +2467,7 @@ at runtime, which applies the __strongest__ proxy settings that any of the
This also applies to the `<tx:annotation-driven/>` and `<aop:aspectj-autoproxy/>`
elements.
-To be clear: using '++proxy-target-class="true"++' on `<tx:annotation-driven/>`,
+To be clear: using `proxy-target-class="true"` on `<tx:annotation-driven/>`,
`<aop:aspectj-autoproxy/>` or `<aop:config/>` elements will force the use of CGLIB
proxies __for all three of them__.
====
@@ -2720,7 +2720,7 @@ Spring will now look for a bean definition named "account" and use that as the
definition to configure new `Account` instances.
You can also use autowiring to avoid having to specify a dedicated bean definition at
-all. To have Spring apply autowiring use the '++autowire++' property of the
+all. To have Spring apply autowiring use the `autowire` property of the
`@Configurable` annotation: specify either `@Configurable(autowire=Autowire.BY_TYPE)` or
`@Configurable(autowire=Autowire.BY_NAME` for autowiring by type or by name
respectively. As an alternative, as of Spring 2.5 it is preferable to specify explicit,
@@ -2740,7 +2740,7 @@ the annotation. In essence the aspect says "after returning from the initializat
new object of a type annotated with `@Configurable`, configure the newly created object
using Spring in accordance with the properties of the annotation". In this context,
__initialization__ refers to newly instantiated objects (e.g., objects instantiated with
-the '++new++' operator) as well as to `Serializable` objects that are undergoing
+the `new` operator) as well as to `Serializable` objects that are undergoing
deserialization (e.g., via
http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html[readResolve()]).
@@ -2929,7 +2929,7 @@ fully-qualified class names:
When using AspectJ aspects with Spring applications, it is natural to both want and
expect to be able to configure such aspects using Spring. The AspectJ runtime itself is
responsible for aspect creation, and the means of configuring the AspectJ created
-aspects via Spring depends on the AspectJ instantiation model (the '++per-xxx++' clause)
+aspects via Spring depends on the AspectJ instantiation model (the `per-xxx` clause)
used by the aspect.
The majority of AspectJ aspects are __singleton__ aspects. Configuration of these
@@ -3067,10 +3067,10 @@ profiler, using the @AspectJ-style of aspect declaration.
}
----
-We will also need to create an '++META-INF/aop.xml++' file, to inform the AspectJ weaver
+We will also need to create an `META-INF/aop.xml` file, to inform the AspectJ weaver
that we want to weave our `ProfilingAspect` into our classes. This file convention,
namely the presence of a file (or files) on the Java classpath called
-'++META-INF/aop.xml++' is standard AspectJ.
+`META-INF/aop.xml` is standard AspectJ.
[source,xml,indent=0]
[subs="verbatim,quotes"]
@@ -3094,7 +3094,7 @@ namely the presence of a file (or files) on the Java classpath called
Now to the Spring-specific portion of the configuration. We need to configure a
`LoadTimeWeaver` (all explained later, just take it on trust for now). This load-time
weaver is the essential component responsible for weaving the aspect configuration in
-one or more '++META-INF/aop.xml++' files into the classes in your application. The good
+one or more `META-INF/aop.xml` files into the classes in your application. The good
thing is that it does not require a lot of configuration, as can be seen below (there
are some more options that you can specify, but these are detailed later).
@@ -3120,7 +3120,7 @@ are some more options that you can specify, but these are detailed later).
</beans>
----
-Now that all the required artifacts are in place - the aspect, the '++META-INF/aop.xml++'
+Now that all the required artifacts are in place - the aspect, the `META-INF/aop.xml`
file, and the Spring configuration -, let us create a simple driver class with a
`main(..)` method to demonstrate the LTW in action.
@@ -3157,7 +3157,7 @@ to switch on the LTW. This is the command line we will use to run the above `Mai
java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main
----
-The '++-javaagent++' is a flag for specifying and enabling
+The `-javaagent` is a flag for specifying and enabling
http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agents
to instrument programs running on the JVM]. The Spring Framework ships with such an
agent, the `InstrumentationSavingAgent`, which is packaged in the
@@ -3235,13 +3235,13 @@ Furthermore, the compiled aspect classes need to be available on the classpath.
[[aop-aj-ltw-aop_dot_xml]]
==== 'META-INF/aop.xml'
-The AspectJ LTW infrastructure is configured using one or more '++META-INF/aop.xml++'
+The AspectJ LTW infrastructure is configured using one or more `META-INF/aop.xml`
files, that are on the Java classpath (either directly, or more typically in jar files).
The structure and contents of this file is detailed in the main AspectJ reference
documentation, and the interested reader is
http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[referred to
-that resource]. (I appreciate that this section is brief, but the '++aop.xml++' file is
+that resource]. (I appreciate that this section is brief, but the `aop.xml` file is
100% AspectJ - there is no Spring-specific information or semantics that apply to it,
and so there is no extra value that I can contribute either as a result), so rather than
rehash the quite satisfactory section that the AspectJ developers wrote, I am just
@@ -3301,7 +3301,7 @@ which typically is done using the `@EnableLoadTimeWeaving` annotation.
Alternatively, if you prefer XML based configuration, use the
`<context:load-time-weaver/>` element. Note that the element is defined in the
-'++context++' namespace.
+`context` namespace.
[source,xml,indent=0]
[subs="verbatim,quotes"]
@@ -3380,7 +3380,7 @@ To specify a specific `LoadTimeWeaver` with Java configuration implement the
----
If you are using XML based configuration you can specify the fully-qualified classname
-as the value of the '++weaver-class++' attribute on the `<context:load-time-weaver/>`
+as the value of the `weaver-class` attribute on the `<context:load-time-weaver/>`
element:
[source,xml,indent=0]
@@ -3403,7 +3403,7 @@ element:
----
The `LoadTimeWeaver` that is defined and registered by the configuration can be later
-retrieved from the Spring container using the well-known name '++loadTimeWeaver++'.
+retrieved from the Spring container using the well-known name `loadTimeWeaver`.
Remember that the `LoadTimeWeaver` exists just as a mechanism for Spring's LTW
infrastructure to add one or more `ClassFileTransformers`. The actual
`ClassFileTransformer` that does the LTW is the `ClassPreProcessorAgentAdapter` (from
@@ -3412,10 +3412,10 @@ the `org.aspectj.weaver.loadtime` package) class. See the class-level javadocs o
the weaving is actually effected is beyond the scope of this section.
There is one final attribute of the configuration left to discuss: the
-'++aspectjWeaving++' attribute (or '++aspectj-weaving++' if you are using XML). This is a
+`aspectjWeaving` attribute (or `aspectj-weaving` if you are using XML). This is a
simple attribute that controls whether LTW is enabled or not; it is as simple as that.
It accepts one of three possible values, summarized below, with the default value being
-'++autodetect++' if the attribute is not present.
+`autodetect` if the attribute is not present.
[[aop-aj-ltw-ltw-tag-attrs]]
.AspectJ weaving attribute values
@@ -3432,7 +3432,7 @@ It accepts one of three possible values, summarized below, with the default valu
| `AUTODETECT`
| `autodetect`
-| If the Spring LTW infrastructure can find at least one '++META-INF/aop.xml++' file,
+| If the Spring LTW infrastructure can find at least one `META-INF/aop.xml` file,
then AspectJ weaving is on, else it is off. This is the default value.
|===
diff --git a/src/asciidoc/core-beans.adoc b/src/asciidoc/core-beans.adoc
index 89d85349..8af1139e 100644
--- a/src/asciidoc/core-beans.adoc
+++ b/src/asciidoc/core-beans.adoc
@@ -2513,6 +2513,19 @@ created from the same `loginAction` bean definition will not see these changes i
they are particular to an individual request. When the request completes processing, the
bean that is scoped to the request is discarded.
+When using annotation-driven components or Java Config, the `@RequestScope` annotation
+can be used to assign a component to the `request` scope.
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ **@RequestScope**
+ @Component
+ public class LoginAction {
+ // ...
+ }
+----
+
[[beans-factory-scopes-session]]
==== Session scope
@@ -2535,6 +2548,19 @@ changes in state, because they are particular to an individual HTTP `Session`. W
HTTP `Session` is eventually discarded, the bean that is scoped to that particular HTTP
`Session` is also discarded.
+When using annotation-driven components or Java Config, the `@SessionScope` annotation
+can be used to assign a component to the `session` scope.
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ **@SessionScope**
+ @Component
+ public class UserPreferences {
+ // ...
+ }
+----
+
[[beans-factory-scopes-global-session]]
==== Global session scope
@@ -2578,6 +2604,19 @@ differs in two important ways: It is a singleton per `ServletContext`, not per S
'ApplicationContext' (for which there may be several in any given web application),
and it is actually exposed and therefore visible as a `ServletContext` attribute.
+When using annotation-driven components or Java Config, the `@ApplicationScope`
+annotation can be used to assign a component to the `application` scope.
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ **@ApplicationScope**
+ @Component
+ public class AppPreferences {
+ // ...
+ }
+----
+
[[beans-factory-scopes-other-injection]]
==== Scoped beans as dependencies
@@ -3446,7 +3485,7 @@ dependency type:
| `BootstrapContextAware`
| Resource adapter `BootstrapContext` the container runs in. Typically available only in
- JCA aware ++ApplicationContext++s
+ JCA aware ``ApplicationContext``s
| <<cci>>
| `LoadTimeWeaverAware`
@@ -3598,21 +3637,21 @@ after the Spring container finishes instantiating, configuring, and initializing
you can plug in one or more `BeanPostProcessor` implementations.
You can configure multiple `BeanPostProcessor` instances, and you can control the order
-in which these ++BeanPostProcessor++s execute by setting the `order` property. You can
+in which these ``BeanPostProcessor``s execute by setting the `order` property. You can
set this property only if the `BeanPostProcessor` implements the `Ordered` interface; if
you write your own `BeanPostProcessor` you should consider implementing the `Ordered`
interface too. For further details, consult the javadocs of the `BeanPostProcessor` and
`Ordered` interfaces. See also the note below on
<<beans-factory-programmatically-registering-beanpostprocessors, programmatic
-registration of `BeanPostProcessors`>>.
+registration of ``BeanPostProcessor``s>>.
[NOTE]
====
-++BeanPostProcessor++s operate on bean (or object) __instances__; that is to say, the
-Spring IoC container instantiates a bean instance and __then__ ++BeanPostProcessor++s do
+``BeanPostProcessor``s operate on bean (or object) __instances__; that is to say, the
+Spring IoC container instantiates a bean instance and __then__ ``BeanPostProcessor``s do
their work.
-++BeanPostProcessor++s are scoped __per-container__. This is only relevant if you are
+``BeanPostProcessor``s are scoped __per-container__. This is only relevant if you are
using container hierarchies. If you define a `BeanPostProcessor` in one container, it
will __only__ post-process the beans in that container. In other words, beans that are
defined in one container are not post-processed by a `BeanPostProcessor` defined in
@@ -3640,12 +3679,12 @@ configuration metadata which implement the `BeanPostProcessor` interface. The
later upon bean creation. Bean post-processors can be deployed in the container just
like any other beans.
-Note that when declaring a ++BeanPostProcessor++ using an `@Bean` factory method on a
+Note that when declaring a `BeanPostProcessor` using an `@Bean` factory method on a
configuration class, the return type of the factory method should be the implementation
class itself or at least the `org.springframework.beans.factory.config.BeanPostProcessor`
interface, clearly indicating the post-processor nature of that bean. Otherwise, the
`ApplicationContext` won't be able to autodetect it by type before fully creating it.
-Since a ++BeanPostProcessor++ needs to be instantiated early in order to apply to the
+Since a `BeanPostProcessor` needs to be instantiated early in order to apply to the
initialization of other beans in the context, this early type detection is critical.
@@ -3658,9 +3697,9 @@ While the recommended approach for `BeanPostProcessor` registration is through
register them __programmatically__ against a `ConfigurableBeanFactory` using the
`addBeanPostProcessor` method. This can be useful when needing to evaluate conditional
logic before registration, or even for copying bean post processors across contexts in a
-hierarchy. Note however that `BeanPostProcessors` added programmatically __do not
+hierarchy. Note however that ``BeanPostProcessor``s added programmatically __do not
respect the `Ordered` interface__. Here it is the __order of registration__ that
-dictates the order of execution. Note also that `BeanPostProcessors` registered
+dictates the order of execution. Note also that ``BeanPostProcessor``s registered
programmatically are always processed before those registered through auto-detection,
regardless of any explicit ordering.
====
@@ -3669,11 +3708,11 @@ regardless of any explicit ordering.
[NOTE]
====
Classes that implement the `BeanPostProcessor` interface are __special__ and are treated
-differently by the container. All `BeanPostProcessors` __and beans that they reference
+differently by the container. All ``BeanPostProcessor``s __and beans that they reference
directly__ are instantiated on startup, as part of the special startup phase of the
-`ApplicationContext`. Next, all `BeanPostProcessors` are registered in a sorted fashion
+`ApplicationContext`. Next, all ``BeanPostProcessor``s are registered in a sorted fashion
and applied to all further beans in the container. Because AOP auto-proxying is
-implemented as a `BeanPostProcessor` itself, neither `BeanPostProcessors` nor the beans
+implemented as a `BeanPostProcessor` itself, neither ``BeanPostProcessor``s nor the beans
they reference directly are eligible for auto-proxying, and thus do not have aspects
woven into them.
@@ -3690,7 +3729,7 @@ directly correspond to the declared name of a bean and no name attribute is used
Spring will access other beans for matching them by type.
====
-The following examples show how to write, register, and use `BeanPostProcessors` in an
+The following examples show how to write, register, and use ``BeanPostProcessor``s in an
`ApplicationContext`.
@@ -3811,10 +3850,10 @@ this interface are similar to those of the `BeanPostProcessor`, with one major
difference: `BeanFactoryPostProcessor` operates on the __bean configuration metadata__;
that is, the Spring IoC container allows a `BeanFactoryPostProcessor` to read the
configuration metadata and potentially change it __before__ the container instantiates
-any beans other than `BeanFactoryPostProcessors`.
+any beans other than ``BeanFactoryPostProcessor``s.
-You can configure multiple `BeanFactoryPostProcessors`, and you can control the order in
-which these `BeanFactoryPostProcessors` execute by setting the `order` property.
+You can configure multiple ``BeanFactoryPostProcessor``s, and you can control the order in
+which these ``BeanFactoryPostProcessor``s execute by setting the `order` property.
However, you can only set this property if the `BeanFactoryPostProcessor` implements the
`Ordered` interface. If you write your own `BeanFactoryPostProcessor`, you should
consider implementing the `Ordered` interface too. Consult the javadocs of the
@@ -3830,10 +3869,10 @@ to work with bean instances within a `BeanFactoryPostProcessor` (e.g., using
standard container lifecycle. This may cause negative side effects such as bypassing
bean post processing.
-Also, `BeanFactoryPostProcessors` are scoped __per-container__. This is only relevant if
+Also, ``BeanFactoryPostProcessor``s are scoped __per-container__. This is only relevant if
you are using container hierarchies. If you define a `BeanFactoryPostProcessor` in one
container, it will __only__ be applied to the bean definitions in that container. Bean
-definitions in one container will not be post-processed by `BeanFactoryPostProcessors`
+definitions in one container will not be post-processed by ``BeanFactoryPostProcessor``s
in another container, even if both containers are part of the same hierarchy.
====
@@ -3853,8 +3892,8 @@ you would any other bean.
[NOTE]
====
-As with ++BeanPostProcessor++s , you typically do not want to configure
-++BeanFactoryPostProcessor++s for lazy initialization. If no other bean references a
+As with ``BeanPostProcessor``s , you typically do not want to configure
+``BeanFactoryPostProcessor``s for lazy initialization. If no other bean references a
`Bean(Factory)PostProcessor`, that post-processor will not get instantiated at all.
Thus, marking it for lazy initialization will be ignored, and the
`Bean(Factory)PostProcessor` will be instantiated eagerly even if you set the
@@ -4172,7 +4211,7 @@ example:
This annotation simply indicates that the affected bean property must be populated at
configuration time, through an explicit property value in a bean definition or through
autowiring. The container throws an exception if the affected bean property has not been
-populated; this allows for eager and explicit failure, avoiding ++NullPointerException++s
+populated; this allows for eager and explicit failure, avoiding ``NullPointerException``s
or the like later on. It is still recommended that you put assertions into the bean
class itself, for example, into an init method. Doing so enforces those required
references and values even when you use the class outside of a container.
@@ -4182,18 +4221,24 @@ references and values even when you use the class outside of a container.
[[beans-autowired-annotation]]
=== @Autowired
-As expected, you can apply the `@Autowired` annotation to "traditional" setter methods:
+[NOTE]
+====
+JSR 330's `@Inject` annotation can be used in place of Spring's `@Autowired` annotation
+in the examples below. See <<beans-standard-annotations,here>> for more details.
+====
+
+You can apply the `@Autowired` annotation to constructors:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- public class SimpleMovieLister {
+ public class MovieRecommender {
- private MovieFinder movieFinder;
+ private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
+ public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
+ this.customerPreferenceDao = customerPreferenceDao;
}
// ...
@@ -4203,10 +4248,31 @@ As expected, you can apply the `@Autowired` annotation to "traditional" setter m
[NOTE]
====
-JSR 330's `@Inject` annotation can be used in place of Spring's `@Autowired` annotation
-in the examples below. See <<beans-standard-annotations,here>> for more details.
+As of Spring Framework 4.3, the `@Autowired` constructor is no longer necessary if the
+target bean only defines one constructor. If several constructors are available, at
+least one must be annotated to teach the container which one it has to use.
====
+As expected, you can also apply the `@Autowired` annotation to "traditional" setter
+methods:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Autowired
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+
+ }
+----
+
You can also apply the annotation to methods with arbitrary names and/or multiple
arguments:
@@ -4568,12 +4634,28 @@ If you intend to express annotation-driven injection by name, do not primarily u
`@Autowired`, even if is technically capable of referring to a bean name through
`@Qualifier` values. Instead, use the JSR-250 `@Resource` annotation, which is
semantically defined to identify a specific target component by its unique name, with
-the declared type being irrelevant for the matching process.
-
-As a specific consequence of this semantic difference, beans that are themselves defined
-as a collection or map type cannot be injected through `@Autowired`, because type
-matching is not properly applicable to them. Use `@Resource` for such beans, referring
-to the specific collection or map bean by unique name.
+the declared type being irrelevant for the matching process. `@Autowired` has rather
+different semantics: After selecting candidate beans by type, the specified String
+qualifier value will be considered within those type-selected candidates only, e.g.
+matching an "account" qualifier against beans marked with the same qualifier label.
+
+For beans that are themselves defined as a collection/map or array type, `@Resource`
+is a fine solution, referring to the specific collection or array bean by unique name.
+That said, as of 4.3, collection/map and array types can be matched through Spring's
+`@Autowired` type matching algorithm as well, as long as the element type information
+is preserved in `@Bean` return type signatures or collection inheritance hierarchies.
+In this case, qualifier values can be used to select among same-typed collections,
+as outlined in the previous paragraph.
+
+As of 4.3, `@Autowired` also considers self references for injection, i.e. references
+back to the bean that is currently injected. Note that self injection is a fallback;
+regular dependencies on other components always have precedence. In that sense, self
+references do not participate in regular candidate selection and are therefore in
+particular never primary; on the contrary, they always end up as lowest precedence.
+In practice, use self references as a last resort only, e.g. for calling other methods
+on the same instance through the bean's transactional proxy: Consider factoring out
+the affected methods to a separate delegate bean in such a scenario. Alternatively,
+use `@Resource` which may obtain a proxy back to the current bean by its unique name.
`@Autowired` applies to fields, constructors, and multi-argument methods, allowing for
narrowing through qualifier annotations at the parameter level. By contrast, `@Resource`
@@ -5110,19 +5192,26 @@ the `@RestController` annotation from Spring MVC is __composed__ of `@Controller
In addition, composed annotations may optionally redeclare attributes from
meta-annotations to allow user customization. This can be particularly useful when you
-want to only expose a subset of the meta-annotation's attributes. For example, the
-following is a custom `@Scope` annotation that hardcodes the scope name to `session` but
-still allows customization of the `proxyMode`.
+want to only expose a subset of the meta-annotation's attributes. For example, Spring's
+`@SessionScope` annotation hardcodes the scope name to `session` but still allows
+customization of the `proxyMode`.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @Target(ElementType.TYPE)
+ @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
- **@Scope("session")**
+ @Documented
+ @Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {
- ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
+ /**
+ * Alias for {@link Scope#proxyMode}.
+ * <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.
+ */
+ @AliasFor(annotation = Scope.class)
+ ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
+
}
----
@@ -5133,7 +5222,7 @@ still allows customization of the `proxyMode`.
----
@Service
**@SessionScope**
- public class SessionScopedUserService implements UserService {
+ public class SessionScopedService {
// ...
}
----
@@ -5144,8 +5233,8 @@ Or with an overridden value for the `proxyMode` as follows:
[subs="verbatim,quotes"]
----
@Service
- **@SessionScope(proxyMode = ScopedProxyMode.TARGET_CLASS)**
- public class SessionScopedService {
+ **@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)**
+ public class SessionScopedUserService implements UserService {
// ...
}
----
@@ -5157,7 +5246,7 @@ For further details, consult the <<annotation-programming-model,Spring Annotatio
=== Automatically detecting classes and registering bean definitions
Spring can automatically detect stereotyped classes and register corresponding
-++BeanDefinition++s with the `ApplicationContext`. For example, the following two classes
+``BeanDefinition``s with the `ApplicationContext`. For example, the following two classes
are eligible for such autodetection:
[source,java,indent=0]
@@ -5405,13 +5494,12 @@ support for autowiring of `@Bean` methods:
}
@Bean
- @Scope(BeanDefinition.SCOPE_SINGLETON)
private TestBean privateInstance() {
return new TestBean("privateInstance", i++);
}
@Bean
- @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
+ @RequestScope
public TestBean requestScopedInstance() {
return new TestBean("requestScopedInstance", 3);
}
@@ -5557,6 +5645,9 @@ within the annotation:
}
----
+For details on web-specific scopes, see <<beans-factory-scopes-other>>.
+
+
[NOTE]
====
To provide a custom strategy for scope resolution rather than relying on the
@@ -6389,7 +6480,7 @@ link) to our `@Bean` using Java, it would look like the following:
----
// an HTTP Session-scoped bean exposed as a proxy
@Bean
- **@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)**
+ **@SessionScope**
public UserPreferences userPreferences() {
return new UserPreferences();
}
@@ -6429,7 +6520,7 @@ resulting bean. This functionality can be overridden, however, with the `name` a
==== Bean aliasing
As discussed in <<beans-beanname>>, it is sometimes desirable to give a single bean
-multiple names, otherwise known as__bean aliasing__. The `name` attribute of the `@Bean`
+multiple names, otherwise known as __bean aliasing__. The `name` attribute of the `@Bean`
annotation accepts a String array for this purpose.
[source,java,indent=0]
@@ -6485,7 +6576,7 @@ inter-bean dependencies. See <<beans-java-basic-concepts>> for a general introdu
[[beans-java-injecting-dependencies]]
==== Injecting inter-bean dependencies
-When ++@Bean++s have dependencies on one another, expressing that dependency is as simple
+When ``@Bean``s have dependencies on one another, expressing that dependency is as simple
as having one bean method call another:
[source,java,indent=0]
@@ -6613,7 +6704,7 @@ where the magic comes in: All `@Configuration` classes are subclassed at startup
with `CGLIB`. In the subclass, the child method checks the container first for any
cached (scoped) beans before it calls the parent method and creates a new instance. Note
that as of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because
-CGLIB classes have been repackaged under org.springframework and included directly
+CGLIB classes have been repackaged under `org.springframework.cglib` and included directly
within the spring-core JAR.
[NOTE]
@@ -6781,8 +6872,12 @@ work on the configuration class itself since it is being created as a bean insta
@Configuration
public class RepositoryConfig {
+ private final DataSource dataSource;
+
@Autowired
- private DataSource dataSource;
+ public RepositoryConfig(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
@Bean
public AccountRepository accountRepository() {
@@ -6810,6 +6905,14 @@ work on the configuration class itself since it is being created as a bean insta
}
----
+[TIP]
+====
+Constructor injection in `@Configuration` classes is only supported as of Spring
+Framework 4.3. Note also that there is no need to specify `@Autowired` if the target
+bean defines only one constructor; in the example above, `@Autowired` is not necessary
+on the `RepositoryConfig` constructor.
+====
+
.[[beans-java-injecting-imported-beans-fq]]Fully-qualifying imported beans for ease of navigation
--
In the scenario above, using `@Autowired` works well and provides the desired
@@ -8189,11 +8292,42 @@ method signature to return the event that should be published, something like:
}
----
+NOTE: This feature is not supported for <<context-functionality-events-async,asynchronous
+listeners>>.
+
This new method will publish a new `ListUpdateEvent` for every `BlackListEvent` handled
by the method above. If you need to publish several events, just return a `Collection` of
events instead.
-Finally if you need the listener to be invoked before another one, just add the `@Order`
+[[context-functionality-events-async]]
+==== Asynchronous Listeners
+
+If you want a particular listener to process events asynchronously, simply reuse the
+<<scheduling-annotation-support-async,regular `@Async` support>>:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @EventListener
+ @Async
+ public void processBlackListEvent(BlackListEvent event) {
+ // BlackListEvent is processed in a separate thread
+ }
+----
+
+Be aware of the following limitations when using asynchronous events:
+
+. If the event listener throws an `Exception` it will not be propagated to the caller,
+ check `AsyncUncaughtExceptionHandler` for more details.
+. Such event listener cannot send replies. If you need to send another event as the
+ result of the processing, inject `ApplicationEventPublisher` to send the event
+ manually.
+
+
+[[context-functionality-events-order]]
+==== Ordering Listeners
+
+If you need the listener to be invoked before another one, just add the `@Order`
annotation to the method declaration:
[source,java,indent=0]
@@ -8266,7 +8400,7 @@ For optimal usage and understanding of application contexts, users should genera
familiarize themselves with Spring's `Resource` abstraction, as described in the chapter
<<resources>>.
-An application context is a `ResourceLoader`, which can be used to load ++Resource++s. A
+An application context is a `ResourceLoader`, which can be used to load ``Resource``s. A
`Resource` is essentially a more feature rich version of the JDK class `java.net.URL`,
in fact, the implementations of the `Resource` wrap an instance of `java.net.URL` where
appropriate. A `Resource` can obtain low-level resources from almost any location in a
@@ -8352,7 +8486,7 @@ class for the configuration details involved in RAR deployment.
__For a simple deployment of a Spring ApplicationContext as a Java EE RAR file:__ package
all application classes into a RAR file, which is a standard JAR file with a different
file extension. Add all required library JARs into the root of the RAR archive. Add a
-"META-INF/ra.xml" deployment descriptor (as shown in ++SpringContextResourceAdapter++'s
+"META-INF/ra.xml" deployment descriptor (as shown in ``SpringContextResourceAdapter``s
JavaDoc) and the corresponding Spring XML bean definition file(s) (typically
"META-INF/applicationContext.xml"), and drop the resulting RAR file into your
application server's deployment directory.
@@ -8470,7 +8604,7 @@ implementation, you must write code like this:
In both cases, the explicit registration step is inconvenient, which is one reason why
the various `ApplicationContext` implementations are preferred above plain `BeanFactory`
implementations in the vast majority of Spring-backed applications, especially when
-using `BeanFactoryPostProcessors` and `BeanPostProcessors`. These mechanisms implement
+using ``BeanFactoryPostProcessor``s and ``BeanPostProcessor``s. These mechanisms implement
important functionality such as property placeholder replacement and AOP.
@@ -8506,4 +8640,3 @@ utility class
locator that is described in this
https://spring.io/blog/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/[Spring
team blog entry].
-
diff --git a/src/asciidoc/core-expressions.adoc b/src/asciidoc/core-expressions.adoc
index ec15a381..86e34a50 100644
--- a/src/asciidoc/core-expressions.adoc
+++ b/src/asciidoc/core-expressions.adoc
@@ -247,7 +247,7 @@ expression using the methods `setVariable()` and `registerFunction()`. The use o
variables and functions are described in the language reference sections
<<expressions-ref-variables,Variables>> and <<expressions-ref-functions,Functions>>. The
`StandardEvaluationContext` is also where you can register custom
-++ConstructorResolver++s, ++MethodResolver++s, and ++PropertyAccessor++s to extend how SpEL
+``ConstructorResolver``s, ``MethodResolver``s, and ``PropertyAccessor``s to extend how SpEL
evaluates expressions. Please refer to the JavaDoc of these classes for more details.
@@ -432,7 +432,7 @@ More and more types of expression will be compilable in the future.
[[expressions-beandef]]
== Expression support for defining bean definitions
SpEL expressions can be used with XML or annotation-based configuration metadata for
-defining ++BeanDefinition++s. In both cases the syntax to define the expression is of the
+defining ``BeanDefinition``s. In both cases the syntax to define the expression is of the
form `#{ <expression string> }`.
@@ -785,7 +785,7 @@ expression based `matches` operator.
----
// evaluates to false
boolean falseValue = parser.parseExpression(
- "'xyz' instanceof T(int)").getValue(Boolean.class);
+ "'xyz' instanceof T(Integer.class)").getValue(Boolean.class);
// evaluates to true
boolean trueValue = parser.parseExpression(
@@ -796,6 +796,13 @@ expression based `matches` operator.
"'5.0067' matches '\^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
----
+[NOTE]
+====
+Be careful with primitive types as they are immediately boxed up to the wrapper type,
+so `1 instanceof T(int)` evaluates to `false` while `1 instanceof T(Integer.class)`
+evaluates to `true`, as expected.
+====
+
Each symbolic operator can also be specified as a purely alphabetic equivalent. This
avoids problems where the symbols used have special meaning for the document type in
which the expression is embedded (eg. an XML document). The textual equivalents are
@@ -1056,6 +1063,18 @@ lookup beans from an expression using the (@) symbol.
Object bean = parser.parseExpression("@foo").getValue(context);
----
+To access a factory bean itself, the bean name should instead be prefixed with a (&) symbol.
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ ExpressionParser parser = new SpelExpressionParser();
+ StandardEvaluationContext context = new StandardEvaluationContext();
+ context.setBeanResolver(new MyBeanResolver());
+
+ // This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
+ Object bean = parser.parseExpression("&foo").getValue(context);
+----
[[expressions-operator-ternary]]
diff --git a/src/asciidoc/core-resources.adoc b/src/asciidoc/core-resources.adoc
index 140be8b6..11cfca24 100644
--- a/src/asciidoc/core-resources.adoc
+++ b/src/asciidoc/core-resources.adoc
@@ -253,7 +253,7 @@ Similarly, one can force a `UrlResource` to be used by specifying any of the sta
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
----
-The following table summarizes the strategy for converting ++String++s to ++Resource++s:
+The following table summarizes the strategy for converting ``String``s to ``Resource``s:
[[resources-resource-strings]]
.Resource strings
diff --git a/src/asciidoc/core-validation.adoc b/src/asciidoc/core-validation.adoc
index bb5916ef..0374d8cf 100644
--- a/src/asciidoc/core-validation.adoc
+++ b/src/asciidoc/core-validation.adoc
@@ -349,7 +349,7 @@ the properties of instantiated `Companies` and `Employees`:
Spring uses the concept of `PropertyEditors` to effect the conversion between an
`Object` and a `String`. If you think about it, it sometimes might be handy to be able
to represent properties in a different way than the object itself. For example, a `Date`
-can be represented in a human readable way (as the `String` ' `2007-14-09`'), while
+can be represented in a human readable way (as the `String` `'2007-14-09'`), while
we're still able to convert the human readable form back to the original date (or even
better: convert any date entered in a human readable form, back to `Date` objects). This
behavior can be achieved by __registering custom editors__, of type
@@ -1317,7 +1317,7 @@ See <<mvc-config-conversion>> in the Spring MVC chapter.
[[format-configuring-formatting-globaldatetimeformat]]
== Configuring a global date & time format
By default, date and time fields that are not annotated with `@DateTimeFormat` are
-converted from strings using the the `DateFormat.SHORT` style. If you prefer, you can
+converted from strings using the `DateFormat.SHORT` style. If you prefer, you can
change this by defining your own global format.
You will need to ensure that Spring does not register default formatters, and instead
diff --git a/src/asciidoc/data-access.adoc b/src/asciidoc/data-access.adoc
index 0cef7939..d26eba96 100644
--- a/src/asciidoc/data-access.adoc
+++ b/src/asciidoc/data-access.adoc
@@ -801,7 +801,7 @@ the call stack, and make a determination whether to mark the transaction for rol
In its default configuration, the Spring Framework's transaction infrastructure code
__only__ marks a transaction for rollback in the case of runtime, unchecked exceptions;
that is, when the thrown exception is an instance or subclass of `RuntimeException`. (
-++Error++s will also - by default - result in a rollback). Checked exceptions that are
+``Error``s will also - by default - result in a rollback). Checked exceptions that are
thrown from a transactional method do __not__ result in rollback in the default
configuration.
@@ -2330,7 +2330,7 @@ creation and release of resources, which helps you avoid common errors such as
forgetting to close the connection. It performs the basic tasks of the core JDBC
workflow such as statement creation and execution, leaving application code to provide
SQL and extract results. The `JdbcTemplate` class executes SQL queries, update
-statements and stored procedure calls, performs iteration over ++ResultSet++s and
+statements and stored procedure calls, performs iteration over ``ResultSet``s and
extraction of returned parameter values. It also catches JDBC exceptions and translates
them to the generic, more informative, exception hierarchy defined in the
`org.springframework.dao` package.
@@ -3435,7 +3435,7 @@ The batch update methods for this call returns an array of int arrays containing
entry for each batch with an array of the number of affected rows for each update. The top
level array's length indicates the number of batches executed and the second level array's
length indicates the number of updates in that batch. The number of updates in each batch
-should be the the batch size provided for all batches except for the last one that might
+should be the batch size provided for all batches except for the last one that might
be less, depending on the total number of update objects provided. The update count for
each update statement is the one reported by the JDBC driver. If the count is not
available, the JDBC driver returns a -2 value.
@@ -4543,8 +4543,8 @@ declaration of an `SqlOutParameter`.
You use the `SqlTypeValue` to pass in the value of a Java object like `TestItem` into a
stored procedure. The `SqlTypeValue` interface has a single method named
`createTypeValue` that you must implement. The active connection is passed in, and you
-can use it to create database-specific objects such as ++StructDescriptor++s, as shown in
-the following example, or ++ArrayDescriptor++s.
+can use it to create database-specific objects such as ``StructDescriptor``s, as shown in
+the following example, or ``ArrayDescriptor``s.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -4873,6 +4873,25 @@ followed by a set of `CREATE` statements.
The `ignore-failures` option can be set to `NONE` (the default), `DROPS` (ignore failed
drops), or `ALL` (ignore all failures).
+Each statement should be separated by `;` or a new line if the `;` character is not
+present at all in the script. You can control that globally or script by script, for
+example:
+
+[source,xml,indent=0]
+[subs="verbatim,quotes"]
+----
+ <jdbc:initialize-database data-source="dataSource" **separator="@@"**>
+ <jdbc:script location="classpath:com/foo/sql/db-schema.sql" **separator=";"**/>
+ <jdbc:script location="classpath:com/foo/sql/db-test-data-1.sql"/>
+ <jdbc:script location="classpath:com/foo/sql/db-test-data-2.sql"/>
+ </jdbc:initialize-database>
+----
+
+In this example, the two `test-data` scripts use `@@` as statement separator and only
+the `db-schema.sql` uses `;`. This configuration specifies that the default separator
+is `@@` and override that default for the `db-schema` script.
+
+
If you need more control than you get from the XML namespace, you can simply use the
`DataSourceInitializer` directly and define it as a component in your application.
@@ -7086,7 +7105,7 @@ set using the `targetClass` property. Optionally, you can set the binding name u
----
A `JibxMarshaller` is configured for a single class. If you want to marshal multiple
-classes, you have to configure multiple ++JibxMarshaller++s with different `targetClass`
+classes, you have to configure multiple ``JibxMarshaller``s with different `targetClass`
property values.
diff --git a/src/asciidoc/index-docinfo.xml b/src/asciidoc/index-docinfo.xml
index 78f1c77c..57d964cf 100644
--- a/src/asciidoc/index-docinfo.xml
+++ b/src/asciidoc/index-docinfo.xml
@@ -1,7 +1,7 @@
<productname>Spring Framework</productname>
<releaseinfo>{revnumber}</releaseinfo>
<copyright>
- <year>2004-2015</year>
+ <year>2004-2016</year>
</copyright>
<legalnotice>
<para>Copies of this document may be made for your own use and for distribution to
diff --git a/src/asciidoc/integration.adoc b/src/asciidoc/integration.adoc
index 43903b45..19dd7b1f 100644
--- a/src/asciidoc/integration.adoc
+++ b/src/asciidoc/integration.adoc
@@ -1292,7 +1292,7 @@ Concrete implementations for the main media (mime) types are provided in the fra
and are registered by default with the `RestTemplate` on the client-side and with
`AnnotationMethodHandlerAdapter` on the server-side.
-The implementations of ++HttpMessageConverter++s are described in the following sections.
+The implementations of ``HttpMessageConverter``s are described in the following sections.
For all converters a default media type is used but can be overridden by setting the
`supportedMediaTypes` bean property
@@ -2796,6 +2796,9 @@ as follow to automatically send a response:
}
----
+TIP: If you have several `@JmsListener`-annotated methods, you can also place the `@SendTo`
+annotation at class-level to share a default reply destination.
+
If you need to set additional headers in a transport-independent manner, you could return a
`Message` instead, something like:
@@ -3505,6 +3508,9 @@ be marked with the `ManagedAttribute` annotation. When marking properties you ca
either the annotation of the getter or the setter to create a write-only or read-only
attribute respectively.
+NOTE: A `ManagedResource` annotated bean must be public as well as the methods exposing
+an operation or an attribute.
+
The example below shows the annotated version of the `JmxTestBean` class that you saw
earlier:
@@ -3888,7 +3894,7 @@ lists of method names.
=== Controlling the ObjectNames for your beans
Behind the scenes, the `MBeanExporter` delegates to an implementation of the
-`ObjectNamingStrategy` to obtain ++ObjectName++s for each of the beans it is registering.
+`ObjectNamingStrategy` to obtain ``ObjectName``s for each of the beans it is registering.
The default implementation, `KeyNamingStrategy`, will, by default, use the key of the
`beans` `Map` as the `ObjectName`. In addition, the `KeyNamingStrategy` can map the key
of the `beans` `Map` to an entry in a `Properties` file (or files) to resolve the
@@ -3903,7 +3909,7 @@ uses source level metadata to obtain the `ObjectName`.
==== Reading ObjectNames from Properties
You can configure your own `KeyNamingStrategy` instance and configure it to read
-++ObjectName++s from a `Properties` instance rather than use bean key. The
+``ObjectName``s from a `Properties` instance rather than use bean key. The
`KeyNamingStrategy` will attempt to locate an entry in the `Properties` with a key
corresponding to the bean key. If no entry is found or if the `Properties` instance is
`null` then the bean key itself is used.
@@ -6556,6 +6562,8 @@ Context, then those would typically have been provided through dependency inject
[NOTE]
====
+As of Spring Framework 4.3, `@Scheduled` methods are supported on beans of any scope.
+
Make sure that you are not initializing multiple instances of the same `@Scheduled`
annotation class at runtime, unless you do want to schedule callbacks to each such
instance. Related to this, make sure that you do not use `@Configurable` on bean
@@ -8168,6 +8176,7 @@ materialized by the `org.springframework.cache.Cache` and
There are <<cache-store-configuration,a few implementations>> of that abstraction
available out of the box: JDK `java.util.concurrent.ConcurrentMap` based caches,
http://ehcache.org/[EhCache], Gemfire cache,
+https://github.com/ben-manes/caffeine/wiki[Caffeine],
https://code.google.com/p/guava-libraries/wiki/CachesExplained[Guava caches] and
JSR-107 compliant caches. See <<cache-plug>> for more information on plugging in
other cache stores/providers.
@@ -8394,6 +8403,33 @@ result in an exception as a custom `CacheManager` will be ignored by the
`CacheResolver` implementation. This is probably not what you expect.
====
+[[cache-annotations-cacheable-synchronized]]
+===== Synchronized caching
+In a multi-threaded environment, certain operations might be concurrently invoked for
+the same argument (typically on startup). By default, the cache abstraction does not
+lock anything and the same value may be computed several times, defeating the purpose
+of caching.
+
+For those particular cases, the `sync` attribute can be used to instruct the underlying
+cache provider to _lock_ the cache entry while the value is being computed. As a result,
+only one thread will be busy computing the value while the others are blocked until the
+entry is updated in the cache.
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Cacheable(cacheNames="foos", **sync="true"**)
+ public Foo executeExpensiveOperation(String id) {...}
+----
+
+[NOTE]
+====
+This is an optional feature and your favorite cache library may not support it. All
+`CacheManager` implementations provided by the core framework support it. Check the
+documentation of your cache provider for more details.
+====
+
+
[[cache-annotations-cacheable-condition]]
===== Conditional caching
Sometimes, a method might not be suitable for caching all the time (for example, it
@@ -8561,10 +8597,8 @@ and thus requires a result.
There are cases when multiple annotations of the same type, such as `@CacheEvict` or
`@CachePut` need to be specified, for example because the condition or the key
-expression is different between different caches. Unfortunately Java does not support
-such declarations however there is a workaround - using an __enclosing__ annotation, in
-this case, `@Caching`. `@Caching` allows multiple nested `@Cacheable`, `@CachePut` and
-`@CacheEvict` to be used on the same method:
+expression is different between different caches. `@Caching` allows multiple nested
+`@Cacheable`, `@CachePut` and `@CacheEvict` to be used on the same method:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -9006,7 +9040,7 @@ we did in the example above by defining the target cache through the `cache:defi
=== Configuring the cache storage
Out of the box, the cache abstraction provides several storage integration. To use
them, one needs to simply declare an appropriate `CacheManager` - an entity that
-controls and manages ++Cache++s and can be used to retrieve these for storage.
+controls and manages ``Cache``s and can be used to retrieve these for storage.
[[cache-store-configuration-jdk]]
@@ -9062,6 +9096,42 @@ This setup bootstraps the ehcache library inside Spring IoC (through the `ehcach
is then wired into the dedicated `CacheManager` implementation. Note the entire
ehcache-specific configuration is read from `ehcache.xml`.
+[[cache-store-configuration-caffeine]]
+==== Caffeine Cache
+
+Caffeine is a Java 8 rewrite of Guava's cache and its implementation is located under
+`org.springframework.cache.caffeine` package and provides access to several features
+of Caffeine.
+
+Configuring a `CacheManager` that creates the cache on demand is straightforward:
+
+[source,xml,indent=0]
+[subs="verbatim,quotes"]
+----
+ <bean id="cacheManager"
+ class="org.springframework.cache.caffeine.CaffeineCacheManager"/>
+----
+
+It is also possible to provide the caches to use explicitly. In that case, only those
+will be made available by the manager:
+
+[source,xml,indent=0]
+[subs="verbatim,quotes"]
+----
+ <bean id="cacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager">
+ <property name="caches">
+ <set>
+ <value>default</value>
+ <value>books</value>
+ </set>
+ </property>
+ </bean>
+----
+
+The Caffeine `CacheManager` also supports customs `Caffeine` and `CacheLoader`. See
+the https://github.com/ben-manes/caffeine/wiki[Caffeine documentation] for more
+information about those.
+
[[cache-store-configuration-guava]]
==== Guava Cache
@@ -9149,7 +9219,7 @@ performs no caching - that is, forces the cached methods to be executed every ti
</bean>
----
-The `CompositeCacheManager` above chains multiple ++CacheManager++s and additionally,
+The `CompositeCacheManager` above chains multiple ``CacheManager``s and additionally,
through the `fallbackToNoOpCache` flag, adds a __no op__ cache that for all the
definitions not handled by the configured cache managers. That is, every cache
definition not found in either `jdkCache` or `gemfireCache` (configured above) will be
diff --git a/src/asciidoc/overview.adoc b/src/asciidoc/overview.adoc
index 183fec5e..a59898ae 100644
--- a/src/asciidoc/overview.adoc
+++ b/src/asciidoc/overview.adoc
@@ -238,7 +238,7 @@ of the `spring-webmvc` module.
The `spring-test` module supports the <<unit-testing,unit testing>> and
<<integration-testing,integration testing>> of Spring components with JUnit or TestNG. It
provides consistent <<testcontext-ctx-management,loading>> of Spring
-++ApplicationContext++s and <<testcontext-ctx-management-caching,caching>> of those
+``ApplicationContext``s and <<testcontext-ctx-management-caching,caching>> of those
contexts. It also provides <<mock-objects,mock objects>> that you can use to test your
code in isolation.
@@ -260,7 +260,7 @@ container-managed transactions. All your custom business logic can be implemente
simple POJOs and managed by Spring's IoC container. Additional services include support
for sending email and validation that is independent of the web layer, which lets you
choose where to execute validation rules. Spring's ORM support is integrated with JPA,
-Hibernate and and JDO; for example, when using Hibernate, you can continue to use
+Hibernate and JDO; for example, when using Hibernate, you can continue to use
your existing mapping files and standard Hibernate `SessionFactory` configuration. Form
controllers seamlessly integrate the web-layer with the domain model, removing the need
for `ActionForms` or other classes that transform HTTP parameters to values for your
diff --git a/src/asciidoc/testing.adoc b/src/asciidoc/testing.adoc
index 3ef4ba77..aa9e7dc8 100644
--- a/src/asciidoc/testing.adoc
+++ b/src/asciidoc/testing.adoc
@@ -64,7 +64,7 @@ depends on environment-specific properties.
==== JNDI
The `org.springframework.mock.jndi` package contains an implementation of the JNDI SPI,
which you can use to set up a simple JNDI environment for test suites or stand-alone
-applications. If, for example, JDBC ++DataSource++s get bound to the same JNDI names in
+applications. If, for example, JDBC ``DataSource``s get bound to the same JNDI names in
test code as within a Java EE container, you can reuse both application code and
configuration in testing scenarios without modification.
@@ -75,11 +75,11 @@ The `org.springframework.mock.web` package contains a comprehensive set of Servl
mock objects, which are useful for testing web contexts, controllers, and filters. These
mock objects are targeted at usage with Spring's Web MVC framework and are generally more
convenient to use than dynamic mock objects such as http://www.easymock.org[EasyMock] or
-alternative Servlet API mock objects such as http://www.mockobjects.com[MockObjects]. As of
+alternative Servlet API mock objects such as http://www.mockobjects.com[MockObjects]. Since
Spring Framework 4.0, the set of mocks in the `org.springframework.mock.web` package is
based on the Servlet 3.0 API.
-For thorough integration testing of your Spring MVC and REST ++Controller++s in
+For thorough integration testing of your Spring MVC and REST ``Controller``s in
conjunction with your `WebApplicationContext` configuration for Spring MVC, see the
<<spring-mvc-test-framework,_Spring MVC Test Framework_>>.
@@ -132,10 +132,10 @@ dealing with Spring MVC `ModelAndView` objects.
.Unit testing Spring MVC Controllers
[TIP]
====
-To unit test your Spring MVC ++Controller++s as POJOs, use `ModelAndViewAssert` combined
+To unit test your Spring MVC ``Controller``s as POJOs, use `ModelAndViewAssert` combined
with `MockHttpServletRequest`, `MockHttpSession`, and so on from Spring's
<<mock-objects-servlet, Servlet API mocks>>. For thorough integration testing of your
-Spring MVC and REST ++Controller++s in conjunction with your `WebApplicationContext`
+Spring MVC and REST ``Controller``s in conjunction with your `WebApplicationContext`
configuration for Spring MVC, use the <<spring-mvc-test-framework,_Spring MVC Test
Framework_>> instead.
====
@@ -193,7 +193,7 @@ configuration details.
[[testing-ctx-management]]
==== Context management and caching
The Spring TestContext Framework provides consistent loading of Spring
-++ApplicationContext++s and ++WebApplicationContext++s as well as caching of those
+``ApplicationContext``s and ``WebApplicationContext``s as well as caching of those
contexts. Support for the caching of loaded contexts is important, because startup time
can become an issue -- not because of the overhead of Spring itself, but because the
objects instantiated by the Spring container take time to instantiate. For example, a
@@ -201,10 +201,11 @@ project with 50 to 100 Hibernate mapping files might take 10 to 20 seconds to lo
mapping files, and incurring that cost before running every test in every test fixture
leads to slower overall test runs that reduce developer productivity.
-Test classes typically declare either an array of __resource locations__ for XML
+Test classes typically declare either an array of __resource locations__ for XML or Groovy
configuration metadata -- often in the classpath -- or an array of __annotated classes__
that is used to configure the application. These locations or classes are the same as or
-similar to those specified in `web.xml` or other deployment configuration files.
+similar to those specified in `web.xml` or other configuration files for production
+deployments.
By default, once loaded, the configured `ApplicationContext` is reused for each test.
Thus the setup cost is incurred only once per test suite, and subsequent test execution
@@ -226,7 +227,7 @@ configure instances of your test classes via Dependency Injection. This provides
convenient mechanism for setting up test fixtures using preconfigured beans from your
application context. A strong benefit here is that you can reuse application contexts
across various testing scenarios (e.g., for configuring Spring-managed object graphs,
-transactional proxies, ++DataSource++s, etc.), thus avoiding the need to duplicate
+transactional proxies, ``DataSource``s, etc.), thus avoiding the need to duplicate
complex test fixture setup for individual test cases.
As an example, consider the scenario where we have a class, `HibernateTitleRepository`,
@@ -330,23 +331,22 @@ you can use in your unit and integration tests in conjunction with the TestConte
framework. Refer to the corresponding javadocs for further information, including
default attribute values, attribute aliases, and so on.
-* `@ContextConfiguration`
-
-+
-
-Defines class-level metadata that is used to determine how to load and configure an
-`ApplicationContext` for integration tests. Specifically, `@ContextConfiguration`
-declares the application context resource `locations` or the annotated `classes`
-that will be used to load the context.
+===== @BootstrapWith
+`@BootstrapWith` is a class-level annotation that is used to configure how the _Spring
+TestContext Framework_ is bootstrapped. Specifically, `@BootstrapWith` is used to specify
+a custom `TestContextBootstrapper`. Consult the <<testcontext-bootstrapping,Bootstrapping
+the TestContext framework>> section for further details.
-+
-
-Resource locations are typically XML configuration files located in the classpath;
-whereas, annotated classes are typically `@Configuration` classes. However, resource
-locations can also refer to files in the file system, and annotated classes can be
-component classes, etc.
+===== @ContextConfiguration
+`@ContextConfiguration` defines class-level metadata that is used to determine how to
+load and configure an `ApplicationContext` for integration tests. Specifically,
+`@ContextConfiguration` declares the application context resource `locations` or the
+annotated `classes` that will be used to load the context.
-+
+Resource locations are typically XML configuration files or Groovy scripts located in
+the classpath; whereas, annotated classes are typically `@Configuration` classes. However,
+resource locations can also refer to files and scripts in the file system, and annotated
+classes can be component classes, etc.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -357,8 +357,6 @@ component classes, etc.
}
----
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -368,13 +366,9 @@ component classes, etc.
}
----
-+
-
As an alternative or in addition to declaring resource locations or annotated classes,
`@ContextConfiguration` may be used to declare `ApplicationContextInitializer` classes.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -384,15 +378,11 @@ As an alternative or in addition to declaring resource locations or annotated cl
}
----
-+
-
`@ContextConfiguration` may optionally be used to declare the `ContextLoader` strategy
as well. Note, however, that you typically do not need to explicitly configure the
loader since the default loader supports either resource `locations` or annotated
`classes` as well as `initializers`.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -402,8 +392,6 @@ loader since the default loader supports either resource `locations` or annotate
}
----
-+
-
[NOTE]
====
`@ContextConfiguration` provides support for __inheriting__ resource locations or
@@ -411,24 +399,18 @@ configuration classes as well as context initializers declared by superclasses b
default.
====
-+
-
See <<testcontext-ctx-management>> and the `@ContextConfiguration` javadocs for
further details.
-* `@WebAppConfiguration`
-
-+
-
-A class-level annotation that is used to declare that the `ApplicationContext` loaded
-for an integration test should be a `WebApplicationContext`. The mere presence of
-`@WebAppConfiguration` on a test class ensures that a `WebApplicationContext` will be
-loaded for the test, using the default value of `"file:src/main/webapp"` for the path to
-the root of the web application (i.e., the __resource base path__). The resource base
-path is used behind the scenes to create a `MockServletContext` which serves as the
-`ServletContext` for the test's `WebApplicationContext`.
-
-+
+===== @WebAppConfiguration
+`@WebAppConfiguration` is a class-level annotation that is used to declare that the
+`ApplicationContext` loaded for an integration test should be a `WebApplicationContext`.
+The mere presence of `@WebAppConfiguration` on a test class ensures that a
+`WebApplicationContext` will be loaded for the test, using the default value of
+`"file:src/main/webapp"` for the path to the root of the web application (i.e., the
+__resource base path__). The resource base path is used behind the scenes to create a
+`MockServletContext` which serves as the `ServletContext` for the test's
+`WebApplicationContext`.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -440,14 +422,10 @@ path is used behind the scenes to create a `MockServletContext` which serves as
}
----
-+
-
To override the default, specify a different base resource path via the __implicit__
`value` attribute. Both `classpath:` and `file:` resource prefixes are supported. If no
resource prefix is supplied the path is assumed to be a file system resource.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -458,26 +436,17 @@ resource prefix is supplied the path is assumed to be a file system resource.
}
----
-+
-
Note that `@WebAppConfiguration` must be used in conjunction with
`@ContextConfiguration`, either within a single test class or within a test class
hierarchy. See the `@WebAppConfiguration` javadocs for further details.
-+
-
-* `@ContextHierarchy`
-
-+
-
-A class-level annotation that is used to define a hierarchy of ++ApplicationContext++s
-for integration tests. `@ContextHierarchy` should be declared with a list of one or more
-`@ContextConfiguration` instances, each of which defines a level in the context
-hierarchy. The following examples demonstrate the use of `@ContextHierarchy` within a
-single test class; however, `@ContextHierarchy` can also be used within a test class
-hierarchy.
-
-+
+===== @ContextHierarchy
+`@ContextHierarchy` is a class-level annotation that is used to define a hierarchy of
+``ApplicationContext``s for integration tests. `@ContextHierarchy` should be declared
+with a list of one or more `@ContextConfiguration` instances, each of which defines a
+level in the context hierarchy. The following examples demonstrate the use of
+`@ContextHierarchy` within a single test class; however, `@ContextHierarchy` can also be
+used within a test class hierarchy.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -491,8 +460,6 @@ hierarchy.
}
----
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -506,8 +473,6 @@ hierarchy.
}
----
-+
-
If you need to merge or override the configuration for a given level of the context
hierarchy within a test class hierarchy, you must explicitly name that level by
supplying the same value to the `name` attribute in `@ContextConfiguration` at each
@@ -515,14 +480,10 @@ corresponding level in the class hierarchy. See
<<testcontext-ctx-management-ctx-hierarchies>> and the `@ContextHierarchy` javadocs
for further examples.
-* `@ActiveProfiles`
-
-+
-
-A class-level annotation that is used to declare which __bean definition profiles__
-should be active when loading an `ApplicationContext` for test classes.
-
-+
+===== @ActiveProfiles
+`@ActiveProfiles` is a class-level annotation that is used to declare which __bean
+definition profiles__ should be active when loading an `ApplicationContext` for an
+integration test.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -534,8 +495,6 @@ should be active when loading an `ApplicationContext` for test classes.
}
----
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -546,8 +505,6 @@ should be active when loading an `ApplicationContext` for test classes.
}
----
-+
-
[NOTE]
====
`@ActiveProfiles` provides support for __inheriting__ active bean definition profiles
@@ -557,20 +514,13 @@ definition profiles programmatically by implementing a custom
and registering it via the `resolver` attribute of `@ActiveProfiles`.
====
-+
-
See <<testcontext-ctx-management-env-profiles>> and the `@ActiveProfiles` javadocs
for examples and further details.
-* `@TestPropertySource`
-
-+
-
-A class-level annotation that is used to configure the locations of properties files and
-inlined properties to be added to the set of `PropertySources` in the `Environment` for
-an `ApplicationContext` loaded for an integration test.
-
-+
+===== @TestPropertySource
+`@TestPropertySource` is a class-level annotation that is used to configure the locations
+of properties files and inlined properties to be added to the set of `PropertySources` in
+the `Environment` for an `ApplicationContext` loaded for an integration test.
Test property sources have higher precedence than those loaded from the operating
system's environment or Java system properties as well as property sources added by the
@@ -579,12 +529,8 @@ sources can be used to selectively override properties defined in system and app
property sources. Furthermore, inlined properties have higher precedence than properties
loaded from resource locations.
-+
-
The following example demonstrates how to declare a properties file from the classpath.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -595,12 +541,8 @@ The following example demonstrates how to declare a properties file from the cla
}
----
-+
-
The following example demonstrates how to declare _inlined_ properties.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -611,32 +553,23 @@ The following example demonstrates how to declare _inlined_ properties.
}
----
-* `@DirtiesContext`
-
-+
-
-Indicates that the underlying Spring `ApplicationContext` has been __dirtied__ during
-the execution of a test (i.e., modified or corrupted in some manner -- for example, by
-changing the state of a singleton bean) and should be closed. When an application
-context is marked __dirty__, it is removed from the testing framework's cache and
-closed. As a consequence, the underlying Spring container will be rebuilt for any
+===== @DirtiesContext
+`@DirtiesContext` indicates that the underlying Spring `ApplicationContext` has been
+__dirtied__ during the execution of a test (i.e., modified or corrupted in some manner --
+for example, by changing the state of a singleton bean) and should be closed. When an
+application context is marked __dirty__, it is removed from the testing framework's cache
+and closed. As a consequence, the underlying Spring container will be rebuilt for any
subsequent test that requires a context with the same configuration metadata.
-+
-
`@DirtiesContext` can be used as both a class-level and method-level annotation within
the same class or class hierarchy. In such scenarios, the `ApplicationContext` is marked
as __dirty__ before or after any such annotated method as well as before or after the
current test class, depending on the configured `methodMode` and `classMode`.
-+
-
The following examples explain when the context would be dirtied for various
configuration scenarios:
-+
-
-** Before the current test class, when declared on a class with class mode set to
+* Before the current test class, when declared on a class with class mode set to
`BEFORE_CLASS`.
+
@@ -652,7 +585,7 @@ configuration scenarios:
+
-** After the current test class, when declared on a class with class mode set to
+* After the current test class, when declared on a class with class mode set to
`AFTER_CLASS` (i.e., the default class mode).
+
@@ -668,7 +601,7 @@ configuration scenarios:
+
-** Before each test method in the current test class, when declared on a class with class
+* Before each test method in the current test class, when declared on a class with class
mode set to `BEFORE_EACH_TEST_METHOD.`
+
@@ -684,7 +617,7 @@ mode set to `BEFORE_EACH_TEST_METHOD.`
+
-** After each test method in the current test class, when declared on a class with class
+* After each test method in the current test class, when declared on a class with class
mode set to `AFTER_EACH_TEST_METHOD.`
+
@@ -700,7 +633,7 @@ mode set to `AFTER_EACH_TEST_METHOD.`
+
-** Before the current test, when declared on a method with the method mode set to
+* Before the current test, when declared on a method with the method mode set to
`BEFORE_METHOD`.
+
@@ -717,7 +650,7 @@ mode set to `AFTER_EACH_TEST_METHOD.`
+
-** After the current test, when declared on a method with the method mode set to
+* After the current test, when declared on a method with the method mode set to
`AFTER_METHOD` (i.e., the default method mode).
+
@@ -732,20 +665,16 @@ mode set to `AFTER_EACH_TEST_METHOD.`
}
----
-+
-
If `@DirtiesContext` is used in a test whose context is configured as part of a context
hierarchy via `@ContextHierarchy`, the `hierarchyMode` flag can be used to control how
the context cache is cleared. By default an __exhaustive__ algorithm will be used that
clears the context cache including not only the current level but also all other context
hierarchies that share an ancestor context common to the current test; all
-++ApplicationContext++s that reside in a sub-hierarchy of the common ancestor context
+``ApplicationContext``s that reside in a sub-hierarchy of the common ancestor context
will be removed from the context cache and closed. If the __exhaustive__ algorithm is
overkill for a particular use case, the simpler __current level__ algorithm can be
specified instead, as seen below.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -767,20 +696,14 @@ specified instead, as seen below.
}
----
-+
-
For further details regarding the `EXHAUSTIVE` and `CURRENT_LEVEL` algorithms see the
`DirtiesContext.HierarchyMode` javadocs.
-* `@TestExecutionListeners`
-
-+
-
-Defines class-level metadata for configuring which ++TestExecutionListener++s should be
-registered with the `TestContextManager`. Typically, `@TestExecutionListeners` is used
-in conjunction with `@ContextConfiguration`.
-
-+
+===== @TestExecutionListeners
+`@TestExecutionListeners` defines class-level metadata for configuring the
+`TestExecutionListener` implementations that should be registered with the
+`TestContextManager`. Typically, `@TestExecutionListeners` is used in conjunction with
+`@ContextConfiguration`.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -792,23 +715,15 @@ in conjunction with `@ContextConfiguration`.
}
----
-+
-
-`@TestExecutionListeners` supports __inherited__ listeners by default. See the javadocs
+`@TestExecutionListeners` supports _inherited_ listeners by default. See the javadocs
for an example and further details.
-+
-
-* `@Commit`
-
-+
-
-Indicates that the transaction for a transactional test method should be __committed__
-after the test method has completed. `@Commit` can be used as a direct replacement for
-`@Rollback(false)` in order to more explicitly convey the intent of the code. Analogous to
-`@Rollback`, `@Commit` may also be declared as a class-level or method-level annotation.
-
-+
+===== @Commit
+`@Commit` indicates that the transaction for a transactional test method should be
+__committed__ after the test method has completed. `@Commit` can be used as a direct
+replacement for `@Rollback(false)` in order to more explicitly convey the intent of the
+code. Analogous to `@Rollback`, `@Commit` may also be declared as a class-level or
+method-level annotation.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -820,25 +735,18 @@ after the test method has completed. `@Commit` can be used as a direct replaceme
}
----
-* `@Rollback`
-
-+
-
-Indicates whether the transaction for a transactional test method should be __rolled
-back__ after the test method has completed. If `true`, the transaction is rolled back;
-otherwise, the transaction is committed (see also `@Commit`). Rollback semantics for
-integration tests in the Spring TestContext Framework default to `true` even if
+===== @Rollback
+`@Rollback` indicates whether the transaction for a transactional test method should be
+__rolled back__ after the test method has completed. If `true`, the transaction is rolled
+back; otherwise, the transaction is committed (see also `@Commit`). Rollback semantics
+for integration tests in the Spring TestContext Framework default to `true` even if
`@Rollback` is not explicitly declared.
-+
-
When declared as a class-level annotation, `@Rollback` defines the default rollback
semantics for all test methods within the test class hierarchy. When declared as a
method-level annotation, `@Rollback` defines rollback semantics for the specific test
method, potentially overriding class-level `@Rollback` or `@Commit` semantics.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -849,52 +757,41 @@ method, potentially overriding class-level `@Rollback` or `@Commit` semantics.
}
----
-* `@BeforeTransaction`
-
-+
-
-Indicates that the annotated `public void` method should be executed __before__ a
-transaction is started for test methods configured to run within a transaction via the
-`@Transactional` annotation.
-
-+
+===== @BeforeTransaction
+`@BeforeTransaction` indicates that the annotated `void` method should be executed
+__before__ a transaction is started for test methods configured to run within a
+transaction via Spring's `@Transactional` annotation. As of Spring Framework 4.3,
+`@BeforeTransaction` methods are not required to be `public` and may be declared on Java
+8 based interface default methods.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
**@BeforeTransaction**
- public void beforeTransaction() {
+ void beforeTransaction() {
// logic to be executed before a transaction is started
}
----
-* `@AfterTransaction`
-
-+
-
-Indicates that the annotated `public void` method should be executed __after__ a
-transaction has ended for test methods configured to run within a transaction via the
-`@Transactional` annotation.
-
-+
+===== @AfterTransaction
+`@AfterTransaction` indicates that the annotated `void` method should be executed
+__after__ a transaction is ended for test methods configured to run within a transaction
+via Spring's `@Transactional` annotation. As of Spring Framework 4.3, `@AfterTransaction`
+methods are not required to be `public` and may be declared on Java 8 based interface
+default methods.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
**@AfterTransaction**
- public void afterTransaction() {
+ void afterTransaction() {
// logic to be executed after a transaction has ended
}
----
-* `@Sql`
-
-+
-
-Used to annotate a test class or test method to configure SQL scripts to be executed
-against a given database during integration tests.
-
-+
+===== @Sql
+`@Sql` is used to annotate a test class or test method to configure SQL scripts to be
+executed against a given database during integration tests.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -906,18 +803,11 @@ against a given database during integration tests.
}
----
-+
-
See <<testcontext-executing-sql-declaratively>> for further details.
-* `@SqlConfig`
-
-+
-
-Defines metadata that is used to determine how to parse and execute SQL scripts
-configured via the `@Sql` annotation.
-
-+
+===== @SqlConfig
+`@SqlConfig` defines metadata that is used to determine how to parse and execute SQL
+scripts configured via the `@Sql` annotation.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -932,16 +822,12 @@ configured via the `@Sql` annotation.
}
----
-* `@SqlGroup`
-
-+
-
-A container annotation that aggregates several `@Sql` annotations. Can be used natively,
-declaring several nested `@Sql` annotations. Can also be used in conjunction with Java
-8's support for repeatable annotations, where `@Sql` can simply be declared several times
-on the same class or method, implicitly generating this container annotation.
-
-+
+===== @SqlGroup
+`@SqlGroup` is a container annotation that aggregates several `@Sql` annotations.
+`@SqlGroup` can be used natively, declaring several nested `@Sql` annotations, or it can
+be used in conjunction with Java 8's support for repeatable annotations, where `@Sql` can
+simply be declared several times on the same class or method, implicitly generating this
+container annotation.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -982,7 +868,7 @@ however, these lifecycle annotations have limited usage within an actual test cl
If a method within a test class is annotated with `@PostConstruct`, that method will be
executed before any __before__ methods of the underlying test framework (e.g., methods
-annotated with JUnit's `@Before`), and that will apply for every test method in the test
+annotated with JUnit 4's `@Before`), and that will apply for every test method in the test
class. On the other hand, if a method within a test class is annotated with
`@PreDestroy`, that method will __never__ be executed. Within a test class it is
therefore recommended to use test lifecycle callbacks from the underlying test framework
@@ -991,32 +877,25 @@ instead of `@PostConstruct` and `@PreDestroy`.
[[integration-testing-annotations-junit]]
-==== Spring JUnit Testing Annotations
+==== Spring JUnit 4 Testing Annotations
The following annotations are __only__ supported when used in conjunction with the
-<<testcontext-junit4-runner,SpringJUnit4ClassRunner>>,
-<<testcontext-junit4-rules,Spring's JUnit rules>>, or
-<<testcontext-support-classes-junit4,Spring's JUnit support classes>>.
+<<testcontext-junit4-runner,SpringRunner>>, <<testcontext-junit4-rules,Spring's JUnit
+rules>>, or <<testcontext-support-classes-junit4,Spring's JUnit 4 support classes>>.
-* `@IfProfileValue`
-
-+
-
-Indicates that the annotated test is enabled for a specific testing environment. If the
-configured `ProfileValueSource` returns a matching `value` for the provided `name`, the
-test is enabled. Otherwise, the test will be disabled and effectively _ignored_.
-
-+
+===== @IfProfileValue
+`@IfProfileValue` indicates that the annotated test is enabled for a specific testing
+environment. If the configured `ProfileValueSource` returns a matching `value` for the
+provided `name`, the test is enabled. Otherwise, the test will be disabled and
+effectively _ignored_.
`@IfProfileValue` can be applied at the class level, the method level, or both.
Class-level usage of `@IfProfileValue` takes precedence over method-level usage for any
methods within that class or its subclasses. Specifically, a test is enabled if it is
enabled both at the class level _and_ at the method level; the absence of
`@IfProfileValue` means the test is implicitly enabled. This is analogous to the
-semantics of JUnit's `@Ignore` annotation, except that the presence of `@Ignore` always
+semantics of JUnit 4's `@Ignore` annotation, except that the presence of `@Ignore` always
disables a test.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -1027,14 +906,10 @@ disables a test.
}
----
-+
-
Alternatively, you can configure `@IfProfileValue` with a list of `values` (with __OR__
-semantics) to achieve TestNG-like support for __test groups__ in a JUnit environment.
+semantics) to achieve TestNG-like support for __test groups__ in a JUnit 4 environment.
Consider the following example:
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -1045,18 +920,11 @@ Consider the following example:
}
----
-+
-
-* `@ProfileValueSourceConfiguration`
-
-+
-
-Class-level annotation that specifies what type of `ProfileValueSource` to use when
-retrieving __profile values__ configured through the `@IfProfileValue` annotation. If
-`@ProfileValueSourceConfiguration` is not declared for a test,
-`SystemProfileValueSource` is used by default.
-
-+
+===== @ProfileValueSourceConfiguration
+`@ProfileValueSourceConfiguration` is a class-level annotation that specifies what type
+of `ProfileValueSource` to use when retrieving __profile values__ configured through the
+`@IfProfileValue` annotation. If `@ProfileValueSourceConfiguration` is not declared for a
+test, `SystemProfileValueSource` is used by default.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -1067,21 +935,14 @@ retrieving __profile values__ configured through the `@IfProfileValue` annotatio
}
----
-* `@Timed`
-
-+
-
-Indicates that the annotated test method must finish execution in a specified time
-period (in milliseconds). If the text execution time exceeds the specified time period,
-the test fails.
-
-+
+===== @Timed
+`@Timed` indicates that the annotated test method must finish execution in a specified
+time period (in milliseconds). If the text execution time exceeds the specified time
+period, the test fails.
The time period includes execution of the test method itself, any repetitions of the
test (see `@Repeat`), as well as any __set up__ or __tear down__ of the test fixture.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -1091,29 +952,20 @@ test (see `@Repeat`), as well as any __set up__ or __tear down__ of the test fix
}
----
-+
-
-Spring's `@Timed` annotation has different semantics than JUnit's `@Test(timeout=...)`
-support. Specifically, due to the manner in which JUnit handles test execution timeouts
+Spring's `@Timed` annotation has different semantics than JUnit 4's `@Test(timeout=...)`
+support. Specifically, due to the manner in which JUnit 4 handles test execution timeouts
(that is, by executing the test method in a separate `Thread`), `@Test(timeout=...)`
preemptively fails the test if the test takes too long. Spring's `@Timed`, on the other
hand, does not preemptively fail the test but rather waits for the test to complete
before failing.
-* `@Repeat`
-
-+
-
-Indicates that the annotated test method must be executed repeatedly. The number of
-times that the test method is to be executed is specified in the annotation.
-
-+
+===== @Repeat
+`@Repeat` indicates that the annotated test method must be executed repeatedly. The
+number of times that the test method is to be executed is specified in the annotation.
The scope of execution to be repeated includes execution of the test method itself as
well as any __set up__ or __tear down__ of the test fixture.
-+
-
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@@ -1127,13 +979,14 @@ well as any __set up__ or __tear down__ of the test fixture.
[[integration-testing-annotations-meta]]
==== Meta-Annotation Support for Testing
-As of Spring Framework 4.0, it is possible to use test-related annotations as
-<<beans-meta-annotations,meta-annotations>> in order to create custom _composed annotations_
-and reduce configuration duplication across a test suite.
+It is possible to use most test-related annotations as
+<<beans-meta-annotations,meta-annotations>> in order to create custom _composed
+annotations_ and reduce configuration duplication across a test suite.
Each of the following may be used as meta-annotations in conjunction with the
<<testcontext-framework,TestContext framework>>.
+* `@BootstrapWith`
* `@ContextConfiguration`
* `@ContextHierarchy`
* `@ActiveProfiles`
@@ -1144,6 +997,7 @@ Each of the following may be used as meta-annotations in conjunction with the
* `@Transactional`
* `@BeforeTransaction`
* `@AfterTransaction`
+* `@Commit`
* `@Rollback`
* `@Sql`
* `@SqlConfig`
@@ -1154,18 +1008,18 @@ Each of the following may be used as meta-annotations in conjunction with the
* `@ProfileValueSourceConfiguration`
For example, if we discover that we are repeating the following configuration
-across our JUnit-based test suite...
+across our JUnit 4 based test suite...
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class OrderRepositoryTests { }
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
@@ -1192,11 +1046,11 @@ configuration of individual test classes as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@TransactionalDevTest
public class OrderRepositoryTests { }
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@TransactionalDevTest
public class UserRepositoryTests { }
----
@@ -1214,14 +1068,14 @@ configuration__ with reasonable defaults that can be overridden through annotati
configuration.
In addition to generic testing infrastructure, the TestContext framework provides
-explicit support for JUnit and TestNG in the form of `abstract` support classes. For
-JUnit, Spring also provides a custom JUnit `Runner` and custom JUnit `Rules` that allow
+explicit support for JUnit 4 and TestNG in the form of `abstract` support classes. For
+JUnit 4, Spring also provides a custom JUnit `Runner` and custom JUnit `Rules` that allow
one to write so-called __POJO test classes__. POJO test classes are not required to
extend a particular class hierarchy.
The following section provides an overview of the internals of the TestContext
-framework. If you are only interested in using the framework and not necessarily
-interested in extending it with your own custom listeners or custom loaders, feel free
+framework. If you are only interested in _using_ the framework and not necessarily
+interested in _extending_ it with your own custom listeners or custom loaders, feel free
to go directly to the configuration (<<testcontext-ctx-management,context management>>,
<<testcontext-fixture-di,dependency injection>>, <<testcontext-tx,transaction
management>>), <<testcontext-support-classes,support classes>>, and
@@ -1230,89 +1084,106 @@ management>>), <<testcontext-support-classes,support classes>>, and
[[testcontext-key-abstractions]]
==== Key abstractions
-The core of the framework consists of the `TestContext` and `TestContextManager` classes
-and the `TestExecutionListener`, `ContextLoader`, and `SmartContextLoader` interfaces. A
-`TestContextManager` is created on a per-test basis (e.g., for the execution of a single
-test method in JUnit). The `TestContextManager` in turn manages a `TestContext` that
-holds the context of the current test. The `TestContextManager` also updates the state
-of the `TestContext` as the test progresses and delegates to ++TestExecutionListener++s,
-which instrument the actual test execution by providing dependency injection, managing
-transactions, and so on. A `ContextLoader` (or `SmartContextLoader`) is responsible for
-loading an `ApplicationContext` for a given test class. Consult the javadocs and the
-Spring test suite for further information and examples of various implementations.
-
-* `TestContext`: Encapsulates the context in which a test is executed, agnostic of the
- actual testing framework in use, and provides context management and caching support
- for the test instance for which it is responsible. The `TestContext` also delegates to
- a `ContextLoader` (or `SmartContextLoader`) to load an `ApplicationContext` if
- requested.
-* `TestContextManager`: The main entry point into the __Spring TestContext Framework__,
- which manages a single `TestContext` and signals events to all registered
- ++TestExecutionListener++s at well-defined test execution points:
-** prior to any __before class methods__ of a particular testing framework
-** test instance preparation
-** prior to any __before methods__ of a particular testing framework
-** after any __after methods__ of a particular testing framework
-** after any __after class methods__ of a particular testing framework
-* `TestExecutionListener`: Defines a __listener__ API for reacting to test execution
- events published by the `TestContextManager` with which the listener is registered. See
- <<testcontext-tel-config>>.
-* `ContextLoader`: Strategy interface introduced in Spring 2.5 for loading an
- `ApplicationContext` for an integration test managed by the Spring TestContext
- Framework.
-
-+
-
+The core of the framework consists of the `TestContextManager` class and the
+`TestContext`, `TestExecutionListener`, and `SmartContextLoader` interfaces. A
+`TestContextManager` is created per test class (e.g., for the execution of all test
+methods within a single test class in JUnit 4). The `TestContextManager` in turn manages a
+`TestContext` that holds the context of the current test. The `TestContextManager` also
+updates the state of the `TestContext` as the test progresses and delegates to
+`TestExecutionListener` implementations, which instrument the actual test execution by
+providing dependency injection, managing transactions, and so on. A `SmartContextLoader`
+is responsible for loading an `ApplicationContext` for a given test class. Consult the
+javadocs and the Spring test suite for further information and examples of various
+implementations.
+
+===== TestContext
+`TestContext` encapsulates the context in which a test is executed, agnostic of the
+actual testing framework in use, and provides context management and caching support for
+the test instance for which it is responsible. The `TestContext` also delegates to a
+`SmartContextLoader` to load an `ApplicationContext` if requested.
+
+===== TestContextManager
+`TestContextManager` is the main entry point into the __Spring TestContext Framework__,
+which manages a single `TestContext` and signals events to each registered
+`TestExecutionListener` at well-defined test execution points:
+
+* prior to any __before class__ or __before all__ methods of a particular testing framework
+* test instance post-processing
+* prior to any __before__ or __before each__ methods of a particular testing framework
+* after any __after__ or __after each__ methods of a particular testing framework
+* after any __after class__ or __after all__ methods of a particular testing framework
+
+===== TestExecutionListener
+`TestExecutionListener` defines the API for reacting to test execution events published
+by the `TestContextManager` with which the listener is registered. See
+<<testcontext-tel-config>>.
+
+===== Context Loaders
+`ContextLoader` is a strategy interface that was introduced in Spring 2.5 for loading an
+`ApplicationContext` for an integration test managed by the Spring TestContext Framework.
Implement `SmartContextLoader` instead of this interface in order to provide support for
annotated classes, active bean definition profiles, test property sources, context
-hierarchies, and ++WebApplicationContext++s.
-
-* `SmartContextLoader`: Extension of the `ContextLoader` interface introduced in Spring
- 3.1.
+hierarchies, and `WebApplicationContext` support.
-+
-
-The `SmartContextLoader` SPI supersedes the `ContextLoader` SPI that was introduced in
-Spring 2.5. Specifically, a `SmartContextLoader` can choose to process resource
-`locations`, annotated `classes`, or context `initializers`. Furthermore, a
+`SmartContextLoader` is an extension of the `ContextLoader` interface introduced in
+Spring 3.1. The `SmartContextLoader` SPI supersedes the `ContextLoader` SPI that was
+introduced in Spring 2.5. Specifically, a `SmartContextLoader` can choose to process
+resource `locations`, annotated `classes`, or context `initializers`. Furthermore, a
`SmartContextLoader` can set active bean definition profiles and test property sources in
the context that it loads.
-+
-
Spring provides the following implementations:
-+
-
-** `DelegatingSmartContextLoader`: one of two default loaders which delegates internally
+* `DelegatingSmartContextLoader`: one of two default loaders which delegates internally
to an `AnnotationConfigContextLoader`, a `GenericXmlContextLoader`, or a
`GenericGroovyXmlContextLoader` depending either on the configuration declared for the
test class or on the presence of default locations or default configuration classes.
Groovy support is only enabled if Groovy is on the classpath.
-** `WebDelegatingSmartContextLoader`: one of two default loaders which delegates
+* `WebDelegatingSmartContextLoader`: one of two default loaders which delegates
internally to an `AnnotationConfigWebContextLoader`, a `GenericXmlWebContextLoader`, or a
`GenericGroovyXmlWebContextLoader` depending either on the configuration declared for the
test class or on the presence of default locations or default configuration classes. A
web `ContextLoader` will only be used if `@WebAppConfiguration` is present on the test
class. Groovy support is only enabled if Groovy is on the classpath.
-** `AnnotationConfigContextLoader`: loads a standard `ApplicationContext` from
+* `AnnotationConfigContextLoader`: loads a standard `ApplicationContext` from
__annotated classes__.
-** `AnnotationConfigWebContextLoader`: loads a `WebApplicationContext` from __annotated
+* `AnnotationConfigWebContextLoader`: loads a `WebApplicationContext` from __annotated
classes__.
-** `GenericGroovyXmlContextLoader`: loads a standard `ApplicationContext` from __resource
+* `GenericGroovyXmlContextLoader`: loads a standard `ApplicationContext` from __resource
locations__ that are either Groovy scripts or XML configuration files.
-** `GenericGroovyXmlWebContextLoader`: loads a `WebApplicationContext` from __resource
+* `GenericGroovyXmlWebContextLoader`: loads a `WebApplicationContext` from __resource
locations__ that are either Groovy scripts or XML configuration files.
-** `GenericXmlContextLoader`: loads a standard `ApplicationContext` from XML __resource
+* `GenericXmlContextLoader`: loads a standard `ApplicationContext` from XML __resource
locations__.
-** `GenericXmlWebContextLoader`: loads a `WebApplicationContext` from XML __resource
+* `GenericXmlWebContextLoader`: loads a `WebApplicationContext` from XML __resource
locations__.
-** `GenericPropertiesContextLoader`: loads a standard `ApplicationContext` from Java
+* `GenericPropertiesContextLoader`: loads a standard `ApplicationContext` from Java
Properties files.
-The following sections explain how to configure the TestContext framework through
-annotations and provide working examples of how to write unit and integration tests with
-the framework.
+[[testcontext-bootstrapping]]
+==== Bootstrapping the TestContext framework
+
+The default configuration for the internals of the Spring TestContext Framework is
+sufficient for all common use cases. However, there are times when a development team or
+third party framework would like to change the default `ContextLoader`, implement a
+custom `TestContext` or `ContextCache`, augment the default sets of
+`ContextCustomizerFactory` and `TestExecutionListener` implementations, etc. For such low
+level control over how the TestContext framework operates, Spring provides a
+bootstrapping strategy.
+
+`TestContextBootstrapper` defines the SPI for _bootstrapping_ the TestContext framework.
+A `TestContextBootstrapper` is used by the `TestContextManager` to load the
+`TestExecutionListener` implementations for the current test and to build the
+`TestContext` that it manages. A custom bootstrapping strategy can be configured for a
+test class (or test class hierarchy) via `@BootstrapWith`, either directly or as a
+meta-annotation. If a bootstrapper is not explicitly configured via `@BootstrapWith`,
+either the `DefaultTestContextBootstrapper` or the `WebTestContextBootstrapper` will be
+used, depending on the presence of `@WebAppConfiguration`.
+
+Since the `TestContextBootstrapper` SPI is likely to change in the future in order to
+accommodate new requirements, implementers are strongly encouraged not to implement this
+interface directly but rather to extend `AbstractTestContextBootstrapper` or one of its
+concrete subclasses instead.
[[testcontext-tel-config]]
==== TestExecutionListener configuration
@@ -1322,9 +1193,12 @@ by default, exactly in this order.
* `ServletTestExecutionListener`: configures Servlet API mocks for a
`WebApplicationContext`
+* `DirtiesContextBeforeModesTestExecutionListener`: handles the `@DirtiesContext` annotation for
+ _before_ modes
* `DependencyInjectionTestExecutionListener`: provides dependency injection for the test
instance
-* `DirtiesContextTestExecutionListener`: handles the `@DirtiesContext` annotation
+* `DirtiesContextTestExecutionListener`: handles the `@DirtiesContext` annotation for
+ _after_ modes
* `TransactionalTestExecutionListener`: provides transactional test execution with
default rollback semantics
* `SqlScriptsTestExecutionListener`: executes SQL scripts configured via the `@Sql`
@@ -1333,7 +1207,7 @@ by default, exactly in this order.
[[testcontext-tel-config-registering-tels]]
===== Registering custom TestExecutionListeners
-Custom ++TestExecutionListener++s can be registered for a test class and its subclasses
+Custom ``TestExecutionListener``s can be registered for a test class and its subclasses
via the `@TestExecutionListeners` annotation. See
<<integration-testing-annotations,annotation support>> and the javadocs for
`@TestExecutionListeners` for details and examples.
@@ -1341,31 +1215,31 @@ via the `@TestExecutionListeners` annotation. See
[[testcontext-tel-config-automatic-discovery]]
===== Automatic discovery of default TestExecutionListeners
-Registering custom ++TestExecutionListener++s via `@TestExecutionListeners` is suitable
+Registering custom ``TestExecutionListener``s via `@TestExecutionListeners` is suitable
for custom listeners that are used in limited testing scenarios; however, it can become
-cumbersome if a custom listener needs to be used across a test suite. To address this
-issue, Spring Framework 4.1 supports automatic discovery of _default_
+cumbersome if a custom listener needs to be used across a test suite. Since Spring
+Framework 4.1, this issue is addressed via support for automatic discovery of _default_
`TestExecutionListener` implementations via the `SpringFactoriesLoader` mechanism.
Specifically, the `spring-test` module declares all core default
-++TestExecutionListener++s under the
+``TestExecutionListener``s under the
`org.springframework.test.context.TestExecutionListener` key in its
`META-INF/spring.factories` properties file. Third-party frameworks and developers can
-contribute their own ++TestExecutionListener++s to the list of default listeners in the
+contribute their own ``TestExecutionListener``s to the list of default listeners in the
same manner via their own `META-INF/spring.factories` properties file.
[[testcontext-tel-config-ordering]]
===== Ordering TestExecutionListeners
-When the TestContext framework discovers default ++TestExecutionListener++s via the
+When the TestContext framework discovers default ``TestExecutionListener``s via the
aforementioned `SpringFactoriesLoader` mechanism, the instantiated listeners are sorted
using Spring's `AnnotationAwareOrderComparator` which honors Spring's `Ordered` interface
and `@Order` annotation for ordering. `AbstractTestExecutionListener` and all default
-++TestExecutionListener++s provided by Spring implement `Ordered` with appropriate
+``TestExecutionListener``s provided by Spring implement `Ordered` with appropriate
values. Third-party frameworks and developers should therefore make sure that their
-_default_ ++TestExecutionListener++s are registered in the proper order by implementing
+_default_ ``TestExecutionListener``s are registered in the proper order by implementing
`Ordered` or declaring `@Order`. Consult the javadocs for the `getOrder()` methods of the
-core default ++TestExecutionListener++s for details on what values are assigned to each
+core default ``TestExecutionListener``s for details on what values are assigned to each
core listener.
[[testcontext-tel-config-merging]]
@@ -1383,6 +1257,7 @@ any custom listeners. The following listing demonstrates this style of configura
@TestExecutionListeners({
MyCustomTestExecutionListener.class,
ServletTestExecutionListener.class,
+ DirtiesContextBeforeModesTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
@@ -1396,8 +1271,9 @@ any custom listeners. The following listing demonstrates this style of configura
The challenge with this approach is that it requires that the developer know exactly
which listeners are registered by default. Moreover, the set of default listeners can
change from release to release -- for example, `SqlScriptsTestExecutionListener` was
-introduced in Spring Framework 4.1. Furthermore, third-party frameworks like Spring
-Security register their own default ++TestExecutionListener++s via the aforementioned
+introduced in Spring Framework 4.1, and `DirtiesContextBeforeModesTestExecutionListener`
+was introduced in Spring Framework 4.2. Furthermore, third-party frameworks like Spring
+Security register their own default ``TestExecutionListener``s via the aforementioned
<<testcontext-tel-config-automatic-discovery, automatic discovery mechanism>>.
To avoid having to be aware of and re-declare **all** _default_ listeners, the
@@ -1453,7 +1329,7 @@ on either a field or setter method. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration
public class MyTest {
@@ -1470,7 +1346,7 @@ the web application context into your test as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
**@WebAppConfiguration**
@ContextConfiguration
public class MyWebAppTest {
@@ -1496,9 +1372,10 @@ addition to context resource `locations` and annotated `classes`, an application
can also be configured via application context `initializers`.
The following sections explain how to configure an `ApplicationContext` via XML
-configuration files, annotated classes (typically `@Configuration` classes), or context
-initializers using Spring's `@ContextConfiguration` annotation. Alternatively, you can
-implement and configure your own custom `SmartContextLoader` for advanced use cases.
+configuration files, Groovy scripts, annotated classes (typically `@Configuration`
+classes), or context initializers using Spring's `@ContextConfiguration` annotation.
+Alternatively, you can implement and configure your own custom `SmartContextLoader` for
+advanced use cases.
[[testcontext-ctx-management-xml]]
===== Context configuration with XML resources
@@ -1515,7 +1392,7 @@ prefixed with `classpath:`, `file:`, `http:`, etc.) will be used __as is__.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from "/app-config.xml" and
// "/test-config.xml" in the root of the classpath
**@ContextConfiguration(locations={"/app-config.xml", "/test-config.xml"})**
@@ -1533,7 +1410,7 @@ demonstrated in the following example.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
**@ContextConfiguration({"/app-config.xml", "/test-config.xml"})**
public class MyTest {
// class body...
@@ -1552,7 +1429,7 @@ a default location based on the name of the test class. If your class is named
----
package com.example;
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from
// "classpath:com/example/MyTest-context.xml"
**@ContextConfiguration**
@@ -1582,7 +1459,7 @@ TestContext Framework is enabled automatically if Groovy is on the classpath.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from "/AppConfig.groovy" and
// "/TestConfig.groovy" in the root of the classpath
**@ContextConfiguration({"/AppConfig.groovy", "/TestConfig.Groovy"})**
@@ -1603,7 +1480,7 @@ detect a default location based on the name of the test class. If your class is
----
package com.example;
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from
// "classpath:com/example/MyTestContext.groovy"
**@ContextConfiguration**
@@ -1625,7 +1502,7 @@ The following listing demonstrates how to combine both in an integration test.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from
// "/app-config.xml" and "/TestConfig.groovy"
@ContextConfiguration({ "/app-config.xml", "/TestConfig.groovy" })
@@ -1645,7 +1522,7 @@ To load an `ApplicationContext` for your tests using __annotated classes__ (see
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from AppConfig and TestConfig
**@ContextConfiguration(classes = {AppConfig.class, TestConfig.class})**
public class MyTest {
@@ -1682,7 +1559,7 @@ configuration class is arbitrary. In addition, a test class can contain more tha
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from the
// static nested Config class
**@ContextConfiguration**
@@ -1738,11 +1615,11 @@ classes to configure your tests, you will have to pick one as the __entry point_
that one will have to include or import the other. For example, in XML or Groovy scripts
you can include `@Configuration` classes via component scanning or define them as normal
Spring beans; whereas, in a `@Configuration` class you can use `@ImportResource` to
-import XML configuration files. Note that this behavior is semantically equivalent to how
-you configure your application in production: in production configuration you will define
-either a set of XML or Groovy resource locations or a set of `@Configuration` classes
-that your production `ApplicationContext` will be loaded from, but you still have the
-freedom to include or import the other type of configuration.
+import XML configuration files or Groovy scripts. Note that this behavior is semantically
+equivalent to how you configure your application in production: in production
+configuration you will define either a set of XML or Groovy resource locations or a set
+of `@Configuration` classes that your production `ApplicationContext` will be loaded
+from, but you still have the freedom to include or import the other type of configuration.
[[testcontext-ctx-management-initializers]]
===== Context configuration with context initializers
@@ -1755,13 +1632,13 @@ the concrete `ConfigurableApplicationContext` type supported by each declared
initializer must be compatible with the type of `ApplicationContext` created by the
`SmartContextLoader` in use (i.e., typically a `GenericApplicationContext`).
Furthermore, the order in which the initializers are invoked depends on whether they
-implement Spring's `Ordered` interface, are annotated with Spring's `@Order` or the
-standard `@Priority` annotation.
+implement Spring's `Ordered` interface or are annotated with Spring's `@Order` annotation
+or the standard `@Priority` annotation.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from TestConfig
// and initialized by TestAppCtxInitializer
**@ContextConfiguration(
@@ -1772,8 +1649,8 @@ standard `@Priority` annotation.
}
----
-It is also possible to omit the declaration of XML configuration files or annotated
-classes in `@ContextConfiguration` entirely and instead declare only
+It is also possible to omit the declaration of XML configuration files, Groovy scripts,
+or annotated classes in `@ContextConfiguration` entirely and instead declare only
`ApplicationContextInitializer` classes which are then responsible for registering beans
in the context -- for example, by programmatically loading bean definitions from XML
files or configuration classes.
@@ -1781,7 +1658,7 @@ files or configuration classes.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be initialized by EntireAppInitializer
// which presumably registers beans in the context
**@ContextConfiguration(initializers = EntireAppInitializer.class)**
@@ -1816,7 +1693,7 @@ therefore __override__ (i.e., replace) those defined in __"base-config.xml"__.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from "/base-config.xml"
// in the root of the classpath
**@ContextConfiguration("/base-config.xml")**
@@ -1840,7 +1717,7 @@ override (i.e., replace) those defined in `BaseConfig`.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from BaseConfig
**@ContextConfiguration(classes = BaseConfig.class)**
public class BaseTest {
@@ -1857,13 +1734,13 @@ override (i.e., replace) those defined in `BaseConfig`.
In the following example that uses context initializers, the `ApplicationContext` for
`ExtendedTest` will be initialized using `BaseInitializer` __and__
`ExtendedInitializer`. Note, however, that the order in which the initializers are
-invoked depends on whether they implement Spring's `Ordered` interface, are annotated
-with Spring's `@Order` or the standard `@Priority` annotation.
+invoked depends on whether they implement Spring's `Ordered` interface or are annotated
+with Spring's `@Order` annotation or the standard `@Priority` annotation.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be initialized by BaseInitializer
**@ContextConfiguration(initializers = BaseInitializer.class)**
public class BaseTest {
@@ -1948,7 +1825,7 @@ Let's take a look at some examples with XML configuration and `@Configuration` c
----
package com.bank.service;
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// ApplicationContext will be loaded from "classpath:/app-config.xml"
@ContextConfiguration("/app-config.xml")
@ActiveProfiles("dev")
@@ -2067,7 +1944,7 @@ integration test but using `@Configuration` classes instead of XML.
----
package com.bank.service;
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
TransferServiceConfig.class,
StandaloneDataConfig.class,
@@ -2115,7 +1992,7 @@ annotations) has been moved to an abstract superclass, `AbstractIntegrationTest`
----
package com.bank.service;
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
TransferServiceConfig.class,
StandaloneDataConfig.class,
@@ -2406,7 +2283,7 @@ a `WebApplicationContext`.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// defaults to "file:src/main/webapp"
@WebAppConfiguration
@@ -2433,7 +2310,7 @@ nested `@Configuration` classes).
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// file system resource
@WebAppConfiguration("webapp")
@@ -2456,7 +2333,7 @@ whereas, `@ContextConfiguration` resource locations are classpath based.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// classpath resource
@WebAppConfiguration("classpath:test-web-resources")
@@ -2542,6 +2419,7 @@ the context cache key:
* `locations` __(from @ContextConfiguration)__
* `classes` __(from @ContextConfiguration)__
* `contextInitializerClasses` __(from @ContextConfiguration)__
+* `contextCustomizers` __(from ContextCustomizerFactory)__
* `contextLoader` __(from @ContextConfiguration)__
* `parent` __(from @ContextHierarchy)__
* `activeProfiles` __(from @ActiveProfiles)__
@@ -2580,6 +2458,13 @@ framework will not be able to cache application contexts between test classes an
build process will run significantly slower as a result.
====
+Since Spring Framework 4.3, the size of the context cache is bounded with a default
+maximum size of 32. Whenever the maximum size is reached, a _least recently used_ (LRU)
+eviction policy is used to evict and close stale contexts. The maximum size can be
+configured from the command line or a build script by setting a JVM system property named
+`spring.test.context.cache.maxSize`. As an alternative, the same property can be set
+programmatically via the `SpringProperties` API.
+
Since having a large number of application contexts loaded within a given test suite can
cause the suite to take an unnecessarily long time to execute, it is often beneficial to
know exactly how many contexts have been loaded and cached. To view the statistics for
@@ -2592,8 +2477,8 @@ you can annotate your test class or test method with `@DirtiesContext` (see the
discussion of `@DirtiesContext` in <<integration-testing-annotations-spring>>). This
instructs Spring to remove the context from the cache and rebuild the application
context before executing the next test. Note that support for the `@DirtiesContext`
-annotation is provided by the `DirtiesContextTestExecutionListener` which is enabled by
-default.
+annotation is provided by the `DirtiesContextBeforeModesTestExecutionListener` and the
+`DirtiesContextTestExecutionListener` which are enabled by default.
[[testcontext-ctx-management-ctx-hierarchies]]
@@ -2601,7 +2486,7 @@ default.
When writing integration tests that rely on a loaded Spring `ApplicationContext`, it is
often sufficient to test against a single context; however, there are times when it is
-beneficial or even necessary to test against a hierarchy of ++ApplicationContext++s. For
+beneficial or even necessary to test against a hierarchy of ``ApplicationContext``s. For
example, if you are developing a Spring MVC web application you will typically have a
root `WebApplicationContext` loaded via Spring's `ContextLoaderListener` and a child
`WebApplicationContext` loaded via Spring's `DispatcherServlet`. This results in a
@@ -2611,7 +2496,7 @@ components. Another use case can be found in Spring Batch applications where you
have a parent context that provides configuration for shared batch infrastructure and a
child context for the configuration of a specific batch job.
-As of Spring Framework 3.2.2, it is possible to write integration tests that use context
+Since Spring Framework 3.2.2, it is possible to write integration tests that use context
hierarchies by declaring context configuration via the `@ContextHierarchy` annotation,
either on an individual test class or within a test class hierarchy. If a context
hierarchy is declared on multiple classes within a test class hierarchy it is also
@@ -2621,7 +2506,7 @@ configuration resource type (i.e., XML configuration files or annotated classes)
consistent; otherwise, it is perfectly acceptable to have different levels in a context
hierarchy configured using different resource types.
-The following JUnit-based examples demonstrate common configuration scenarios for
+The following JUnit 4 based examples demonstrate common configuration scenarios for
integration tests that require the use of context hierarchies.
.Single test class with context hierarchy
@@ -2637,7 +2522,7 @@ lowest context in the hierarchy).
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = TestAppConfig.class),
@@ -2672,7 +2557,7 @@ for the concrete subclasses.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
public abstract class AbstractWebTests {}
@@ -2703,7 +2588,7 @@ and `{"/user-config.xml", "/order-config.xml"}`.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
@ContextConfiguration(name = "child", locations = "/user-config.xml")
@@ -2729,7 +2614,7 @@ application context for `ExtendedTests` will be loaded only from
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
@ContextConfiguration(name = "child", locations = "/user-config.xml")
@@ -2765,7 +2650,7 @@ application context that you configured with `@ContextConfiguration`. You may us
injection, field injection, or both, depending on which annotations you choose and
whether you place them on setter methods or fields. For consistency with the annotation
support introduced in Spring 2.5 and 3.0, you can use Spring's `@Autowired` annotation
-or the `@Inject` annotation from JSR 300.
+or the `@Inject` annotation from JSR 330.
[TIP]
====
@@ -2797,7 +2682,7 @@ is presented after all sample code listings.
[NOTE]
====
The dependency injection behavior in the following code listings is not specific to
-JUnit. The same DI techniques can be used in conjunction with any testing framework.
+JUnit 4. The same DI techniques can be used in conjunction with any testing framework.
The following examples make calls to static assertion methods such as `assertNotNull()`
but without prepending the call with `Assert`. In such cases, assume that the method was
@@ -2805,13 +2690,13 @@ properly imported through an `import static` declaration that is not shown in th
example.
====
-The first code listing shows a JUnit-based implementation of the test class that uses
+The first code listing shows a JUnit 4 based implementation of the test class that uses
`@Autowired` for field injection.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// specifies the Spring configuration to load for this test fixture
**@ContextConfiguration("repository-config.xml")**
public class HibernateTitleRepositoryTests {
@@ -2834,7 +2719,7 @@ seen below.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
// specifies the Spring configuration to load for this test fixture
**@ContextConfiguration("repository-config.xml")**
public class HibernateTitleRepositoryTests {
@@ -2873,7 +2758,7 @@ this:
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
+ <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- configuration elided for brevity -->
</bean>
@@ -2915,9 +2800,8 @@ bean by name there (as shown above, assuming that "myDataSource" is the bean id)
==== Testing request and session scoped beans
<<beans-factory-scopes-other,Request and session scoped beans>> have been supported by
-Spring for several years now, but it's always been a bit non-trivial to test them. As of
-Spring 3.2 it's a breeze to test your request-scoped and session-scoped beans by
-following these steps.
+Spring since the early years, and since Spring 3.2 it's a breeze to test your
+request-scoped and session-scoped beans by following these steps.
* Ensure that a `WebApplicationContext` is loaded for your test by annotating your test
class with `@WebAppConfiguration`.
@@ -2945,8 +2829,8 @@ framework.
c:loginAction-ref="loginAction" />
<bean id="loginAction" class="com.example.LoginAction"
- c:username="#{request.getParameter(''user'')}"
- c:password="#{request.getParameter(''pswd'')}"
+ c:username="#{request.getParameter('user')}"
+ c:password="#{request.getParameter('pswd')}"
scope="request">
<aop:scoped-proxy />
</bean>
@@ -2967,7 +2851,7 @@ inputs for the username and password.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class RequestScopedBeanTests {
@@ -3007,7 +2891,7 @@ framework.
<bean id="userPreferences"
class="com.example.UserPreferences"
- c:theme="#{session.getAttribute(''theme'')}"
+ c:theme="#{session.getAttribute('theme')}"
scope="session">
<aop:scoped-proxy />
</bean>
@@ -3027,7 +2911,7 @@ configured theme.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class SessionScopedBeanTests {
@@ -3098,7 +2982,7 @@ See <<testing-examples-petclinic>> for an additional example.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@Transactional
public class HibernateUserRepositoryTests {
@@ -3149,7 +3033,7 @@ via the `@Commit` and `@Rollback` annotations. See the corresponding entries in
[[testcontext-tx-programmatic-tx-mgt]]
===== Programmatic transaction management
-As of Spring Framework 4.1, it is possible to interact with test-managed transactions
+Since Spring Framework 4.1, it is possible to interact with test-managed transactions
_programmatically_ via the static methods in `TestTransaction`. For example,
`TestTransaction` may be used within _test_ methods, _before_ methods, and _after_
methods to start or end the current test-managed transaction or to configure the current
@@ -3196,17 +3080,17 @@ javadocs for `TestTransaction` for further details.
Occasionally you need to execute certain code before or after a transactional test method
but outside the transactional context -- for example, to verify the initial database state
prior to execution of your test or to verify expected transactional commit behavior after
-test execution (if the test was configured not to roll back the transaction).
+test execution (if the test was configured to commit the transaction).
`TransactionalTestExecutionListener` supports the `@BeforeTransaction` and
-`@AfterTransaction` annotations exactly for such scenarios. Simply annotate any `public
-void` method in your test class with one of these annotations, and the
-`TransactionalTestExecutionListener` ensures that your __before transaction method__ or
-__after transaction method__ is executed at the appropriate time.
+`@AfterTransaction` annotations exactly for such scenarios. Simply annotate any `void`
+method in a test class or any `void` default method in a test interface with one of these
+annotations, and the `TransactionalTestExecutionListener` ensures that your __before
+transaction method__ or __after transaction method__ is executed at the appropriate time.
[TIP]
====
-Any __before methods__ (such as methods annotated with JUnit's `@Before`) and any __after
-methods__ (such as methods annotated with JUnit's `@After`) are executed __within__ a
+Any __before methods__ (such as methods annotated with JUnit 4's `@Before`) and any __after
+methods__ (such as methods annotated with JUnit 4's `@After`) are executed __within__ a
transaction. In addition, methods annotated with `@BeforeTransaction` or
`@AfterTransaction` are naturally not executed for test methods that are not configured
to run within a transaction.
@@ -3227,7 +3111,7 @@ used to look up a transaction manager in the test's `ApplicationContext`.
[[testcontext-tx-annotation-demo]]
===== Demonstration of all transaction-related annotations
-The following JUnit-based example displays a fictitious integration testing scenario
+The following JUnit 4 based example displays a fictitious integration testing scenario
highlighting all transaction-related annotations. The example is **not** intended to
demonstrate best practices but rather to demonstrate how these annotations can be used.
Consult the <<integration-testing-annotations,annotation support>> section for further
@@ -3238,14 +3122,14 @@ declarative SQL script execution with default transaction rollback semantics.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration
**@Transactional(transactionManager = "txMgr")**
**@Commit**
public class FictitiousTransactionalTest {
**@BeforeTransaction**
- public void verifyInitialDatabaseState() {
+ void verifyInitialDatabaseState() {
// logic to verify the initial state before a transaction is started
}
@@ -3267,7 +3151,7 @@ declarative SQL script execution with default transaction rollback semantics.
}
**@AfterTransaction**
- public void verifyFinalDatabaseState() {
+ void verifyFinalDatabaseState() {
// logic to verify the final state after transaction has rolled back
}
@@ -3278,13 +3162,14 @@ declarative SQL script execution with default transaction rollback semantics.
.Avoid false positives when testing ORM code
[NOTE]
====
-When you test application code that manipulates the state of the Hibernate or JPA session,
-make sure to __flush__ the underlying session within test methods that execute that code.
-Failing to flush the underlying session can produce __false positives__: your test may
-pass, but the same code throws an exception in a live, production environment. In the
-following Hibernate-based example test case, one method demonstrates a false positive,
-and the other method correctly exposes the results of flushing the session. Note that
-this applies to any ORM frameworks that maintain an in-memory __unit of work__.
+When you test application code that manipulates the state of a Hibernate session or JPA
+persistence context, make sure to __flush__ the underlying unit of work within test
+methods that execute that code. Failing to flush the underlying unit of work can produce
+__false positives__: your test may pass, but the same code throws an exception in a live,
+production environment. In the following Hibernate-based example test case, one method
+demonstrates a false positive, and the other method correctly exposes the results of
+flushing the session. Note that this applies to any ORM frameworks that maintain an
+in-memory __unit of work__.
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -3292,8 +3177,9 @@ this applies to any ORM frameworks that maintain an in-memory __unit of work__.
// ...
@Autowired
- private SessionFactory sessionFactory;
+ SessionFactory sessionFactory;
+ @Transactional
@Test // no expected exception!
public void falsePositive() {
updateEntityInHibernateSession();
@@ -3301,6 +3187,7 @@ this applies to any ORM frameworks that maintain an in-memory __unit of work__.
// Session is finally flushed (i.e., in production code)
}
+ @Transactional
@Test(expected = ...)
public void updateWithSessionFlush() {
updateEntityInHibernateSession();
@@ -3318,19 +3205,21 @@ Or for JPA:
----
// ...
- @Autowired
- private EntityManager entityManager;
+ @PersistenceContext
+ EntityManager entityManager;
+ @Transactional
@Test // no expected exception!
public void falsePositive() {
- updateEntityInJpaTransaction();
+ updateEntityInJpaPersistenceContext();
// False positive: an exception will be thrown once the JPA
// EntityManager is finally flushed (i.e., in production code)
}
+ @Transactional
@Test(expected = ...)
public void updateWithEntityManagerFlush() {
- updateEntityInJpaTransaction();
+ updateEntityInJpaPersistenceContext();
// Manual flush is required to avoid false positive in test
entityManager.flush();
}
@@ -3409,7 +3298,7 @@ for the various `executeSqlScript(..)` methods for further details.
[[testcontext-executing-sql-declaratively]]
-===== Executing SQL scripts declaratively with `@Sql`
+===== Executing SQL scripts declaratively with @Sql
In addition to the aforementioned mechanisms for executing SQL scripts
_programmatically_, SQL scripts can also be configured _declaratively_ in the Spring
@@ -3429,12 +3318,12 @@ which references a URL (e.g., a path prefixed with `classpath:`, `file:`, `http:
will be loaded using the specified resource protocol.
The following example demonstrates how to use `@Sql` at the class level and at the method
-level within a JUnit-based integration test class.
+level within a JUnit 4 based integration test class.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration
@Sql("/test-schema.sql")
public class DatabaseTests {
@@ -3576,16 +3465,16 @@ executed in an isolated transaction. Although a thorough discussion of all suppo
options for transaction management with `@Sql` is beyond the scope of this reference
manual, the javadocs for `@SqlConfig` and `SqlScriptsTestExecutionListener` provide
detailed information, and the following example demonstrates a typical testing scenario
-using JUnit and transactional tests with `@Sql`. Note that there is no need to clean up
+using JUnit 4 and transactional tests with `@Sql`. Note that there is no need to clean up
the database after the `usersTest()` method is executed since any changes made to the
-database (either within the the test method or within the `/test-data.sql` script) will
+database (either within the test method or within the `/test-data.sql` script) will
be automatically rolled back by the `TransactionalTestExecutionListener` (see
<<testcontext-tx,transaction management>> for details).
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestDatabaseConfig.class)
@Transactional
public class TransactionalSqlScriptsTests {
@@ -3621,17 +3510,18 @@ be automatically rolled back by the `TransactionalTestExecutionListener` (see
[[testcontext-junit4-runner]]
-===== Spring JUnit Runner
-
-The __Spring TestContext Framework__ offers full integration with JUnit 4.9+ through a
-custom runner (supported on JUnit 4.9 through 4.12). By annotating test classes with
-`@RunWith(SpringJUnit4ClassRunner.class)`, developers can implement standard JUnit-based
-unit and integration tests and simultaneously reap the benefits of the TestContext
-framework such as support for loading application contexts, dependency injection of test
-instances, transactional test method execution, and so on. If you would like to use the
-Spring TestContext Framework with an alternative runner such as JUnit's `Parameterized`
-or third-party runners such as the `MockitoJUnitRunner`, you may optionally use
-<<testcontext-junit4-rules,Spring's support for JUnit rules>> instead.
+===== Spring JUnit 4 Runner
+
+The __Spring TestContext Framework__ offers full integration with JUnit 4 through a
+custom runner (supported on JUnit 4.12 or higher). By annotating test classes with
+`@RunWith(SpringJUnit4ClassRunner.class)` or the shorter `@RunWith(SpringRunner.class)`
+variant, developers can implement standard JUnit 4 based unit and integration tests and
+simultaneously reap the benefits of the TestContext framework such as support for loading
+application contexts, dependency injection of test instances, transactional test method
+execution, and so on. If you would like to use the Spring TestContext Framework with an
+alternative runner such as JUnit 4's `Parameterized` or third-party runners such as the
+`MockitoJUnitRunner`, you may optionally use <<testcontext-junit4-rules,Spring's support
+for JUnit rules>> instead.
The following code listing displays the minimal requirements for configuring a test class
to run with the custom Spring `Runner`. `@TestExecutionListeners` is configured with an
@@ -3641,7 +3531,7 @@ empty list in order to disable the default listeners, which otherwise would requ
[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@RunWith(SpringJUnit4ClassRunner.class)
+@RunWith(SpringRunner.class)
@TestExecutionListeners({})
public class SimpleTest {
@@ -3654,10 +3544,10 @@ public class SimpleTest {
[[testcontext-junit4-rules]]
-===== Spring JUnit Rules
+===== Spring JUnit 4 Rules
The `org.springframework.test.context.junit4.rules` package provides the following JUnit
-rules.
+4 rules (supported on JUnit 4.12 or higher).
* `SpringClassRule`
* `SpringMethodRule`
@@ -3666,10 +3556,10 @@ rules.
_Spring TestContext Framework_; whereas, `SpringMethodRule` is a JUnit `MethodRule` that
supports instance-level and method-level features of the _Spring TestContext Framework_.
-In contrast to the `SpringJUnit4ClassRunner`, Spring's rule-based JUnit support has the
-advantage that it is independent of any `org.junit.runner.Runner` implementation and can
-therefore be combined with existing alternative runners like JUnit's `Parameterized` or
-third-party runners such as the `MockitoJUnitRunner`.
+In contrast to the `SpringRunner`, Spring's rule-based JUnit support has the advantage
+that it is independent of any `org.junit.runner.Runner` implementation and can therefore
+be combined with existing alternative runners like JUnit 4's `Parameterized` or third-party
+runners such as the `MockitoJUnitRunner`.
In order to support the full functionality of the TestContext framework, a
`SpringClassRule` must be combined with a `SpringMethodRule`. The following example
@@ -3698,17 +3588,17 @@ public class IntegrationTest {
[[testcontext-support-classes-junit4]]
-===== JUnit support classes
+===== JUnit 4 support classes
The `org.springframework.test.context.junit4` package provides the following support
-classes for JUnit-based test cases.
+classes for JUnit 4 based test cases (supported on JUnit 4.12 or higher).
* `AbstractJUnit4SpringContextTests`
* `AbstractTransactionalJUnit4SpringContextTests`
`AbstractJUnit4SpringContextTests` is an abstract base test class that integrates the
__Spring TestContext Framework__ with explicit `ApplicationContext` testing support in
-a JUnit 4.9+ environment. When you extend `AbstractJUnit4SpringContextTests`, you can
+a JUnit 4 environment. When you extend `AbstractJUnit4SpringContextTests`, you can
access a `protected` `applicationContext` instance variable that can be used to perform
explicit bean lookups or to test the state of the context as a whole.
@@ -3732,7 +3622,7 @@ provides an `executeSqlScript(..)` method for executing SQL scripts against the
====
These classes are a convenience for extension. If you do not want your test classes to be
tied to a Spring-specific class hierarchy, you can configure your own custom test classes
-by using `@RunWith(SpringJUnit4ClassRunner.class)` or <<testcontext-junit4-rules,Spring's
+by using `@RunWith(SpringRunner.class)` or <<testcontext-junit4-rules,Spring's
JUnit rules>>.
====
@@ -3825,14 +3715,14 @@ of the Servlet API>> available in the `spring-test` module. This allows performi
requests and generating responses without the need for running in a Servlet container.
For the most part everything should work as it does at runtime with a few notable
exceptions as explained in <<spring-mvc-test-vs-end-to-end-integration-tests>>. Here is a
-JUnit-based example of using Spring MVC Test:
+JUnit 4 based example of using Spring MVC Test:
[source,java,indent=0]
----
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration("test-servlet-context.xml")
public class ExampleTests {
@@ -3892,7 +3782,7 @@ into the test to use to build a `MockMvc` instance:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration("my-servlet-context.xml")
public class MyWebTests {
@@ -3957,7 +3847,7 @@ expectations:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RunWith(SpringJUnit4ClassRunner.class)
+ @RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration("test-servlet-context.xml")
public class AccountTests {
@@ -4112,7 +4002,7 @@ This can be done as follows, where `print()` is a static import from
----
As long as request processing does not cause an unhandled exception, the `print()` method
-will print all the available result data to `System.out`. Spring Framework 4.2 introduces
+will print all the available result data to `System.out`. Spring Framework 4.2 introduced
a `log()` method and two additional variants of the `print()` method, one that accepts
an `OutputStream` and one that accepts a `Writer`. For example, invoking
`print(System.err)` will print the result data to `System.err`; while invoking
@@ -4155,7 +4045,7 @@ be verified using JsonPath expressions:
[subs="verbatim,quotes"]
----
mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON))
- .andExpect(jsonPath("$.links[?(@.rel == ''self'')].href").value("http://localhost:8080/people"));
+ .andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people"));
----
When XML response content contains hypermedia links created with
@@ -4167,7 +4057,7 @@ be verified using XPath expressions:
----
Map<String, String> ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom");
mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML))
- .andExpect(xpath("/person/ns:link[@rel=''self'']/@href", ns).string("http://localhost:8080/people"));
+ .andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people"));
----
[[spring-mvc-test-server-filters]]
@@ -5035,39 +4925,93 @@ http://www.gebish.org/manual/current/[The Book of Geb] user's manual.
[[spring-mvc-test-client]]
==== Client-Side REST Tests
-Client-side tests are for code using the `RestTemplate`. The goal is to define expected
-requests and provide "stub" responses:
+Client-side tests can be used to test code that internally uses the `RestTemplate`.
+The idea is to declare expected requests and to provide "stub" responses so that
+you can focus on testing the code in isolation, i.e. without running a server.
+Here is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
RestTemplate restTemplate = new RestTemplate();
- MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
- mockServer.expect(requestTo("/greeting")).andRespond(withSuccess("Hello world", MediaType.TEXT_PLAIN));
+ MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
+ mockServer.expect(requestTo("/greeting")).andRespond(withSuccess());
- // use RestTemplate ...
+ // Test code that uses the above RestTemplate ...
mockServer.verify();
----
-In the above example, `MockRestServiceServer` -- the central class for client-side REST
-tests -- configures the `RestTemplate` with a custom `ClientHttpRequestFactory` that
+In the above example, `MockRestServiceServer`, the central class for client-side REST
+tests, configures the `RestTemplate` with a custom `ClientHttpRequestFactory` that
asserts actual requests against expectations and returns "stub" responses. In this case
-we expect a single request to "/greeting" and want to return a 200 response with
-"text/plain" content. We could define as many additional requests and stub responses as
-necessary.
+we expect a request to "/greeting" and want to return a 200 response with
+"text/plain" content. We could define as additional expected requests and stub responses as
+needed. When expected requests and stub responses are defined, the `RestTemplate` can be
+used in client-side code as usual. At the end of testing `mockServer.verify()` can be
+used to verify that all expectations have been satisfied.
+
+By default requests are expected in the order in which expectations were declared.
+You can set the `ignoreExpectOrder` option when building the server in which case
+all expectations are checked (in order) to find a match for a given request. That
+means requests are allowed to come in any order. Here is an example:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
+----
+
+Even with unordered requests by default each request is allowed to execute once only.
+The `expect` method provides an overloaded variant that accepts an `ExpectedCount`
+argument that specifies a count range, e.g. `once`, `manyTimes`, `max`, `min`,
+`between`, and so on. Here is an example:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ RestTemplate restTemplate = new RestTemplate();
+
+ MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
+ mockServer.expect(times(2), requestTo("/foo")).andRespond(withSuccess());
+ mockServer.expect(times(3), requestTo("/bar")).andRespond(withSuccess());
+
+ // ...
+
+ mockServer.verify();
+----
+
+Note that when `ignoreExpectOrder` is not set (the default), and therefore requests
+are expected in order of declaration, then that order only applies to the first of
+any expected request. For example if "/foo" is expected 2 times followed by "/bar"
+3 times, then there should be a request to "/foo" before there is a request to "/bar"
+but aside from that subsequent "/foo" and "/bar" requests can come at any time.
+
+As an alternative to all of the above the client-side test support also provides a
+`ClientHttpRequestFactory` implementation that can be configured into a `RestTemplate`
+to bind it to a `MockMvc` instance. That allows processing requests using actual
+server-side logic but without running a server. Here is an example:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ this.restTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(mockMvc));
+
+ // Test code that uses the above RestTemplate ...
+
+ mockServer.verify();
+----
+
-Once expected requests and stub responses have been defined, the `RestTemplate` can be
-used in client-side code as usual. At the end of the tests `mockServer.verify()` can be
-used to verify that all expected requests were performed.
[[spring-mvc-test-client-static-imports]]
===== Static Imports
Just like with server-side tests, the fluent API for client-side tests requires a few
static imports. Those are easy to find by searching __"MockRest*"__. Eclipse users
should add `"MockRestRequestMatchers.{asterisk}"` and `"MockRestResponseCreators.{asterisk}"`
-as "favorite static members" in the Eclipse preferences under
+as "favorite static members" in the Eclipse preferences under
__Java -> Editor -> Content Assist -> Favorites__.
That allows using content assist after typing the first character of the
static method name. Other IDEs (e.g. IntelliJ) may not require any additional
@@ -5086,7 +5030,7 @@ tests] of client-side REST tests.
The PetClinic application, available on
https://github.com/spring-projects/spring-petclinic[GitHub], illustrates several features
-of the __Spring TestContext Framework__ in a JUnit environment. Most test functionality
+of the __Spring TestContext Framework__ in a JUnit 4 environment. Most test functionality
is included in the `AbstractClinicTests`, for which a partial listing is shown below:
[source,java,indent=0]
diff --git a/src/asciidoc/web-cors.adoc b/src/asciidoc/web-cors.adoc
index 5e8c351c..d32a095f 100644
--- a/src/asciidoc/web-cors.adoc
+++ b/src/asciidoc/web-cors.adoc
@@ -17,7 +17,7 @@ and less powerful hacks like IFRAME or JSONP.
As of Spring Framework 4.2, CORS is supported out of the box. CORS requests
(https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L906[including preflight ones with an `OPTIONS` method])
-are automatically dispatched to the various registered ++HandlerMapping++s. They handle
+are automatically dispatched to the various registered ``HandlerMapping``s. They handle
CORS preflight requests and intercept CORS simple and actual requests thanks to a
{api-spring-framework}/web/cors/CorsProcessor.html[CorsProcessor]
implementation (https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java[DefaultCorsProcessor]
@@ -203,4 +203,42 @@ It can be provided in various ways:
* Handlers can implement the {api-spring-framework}/web/cors/CorsConfigurationSource.html[`CorsConfigurationSource`]
interface (like https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java[`ResourceHttpRequestHandler`]
now does) in order to provide a {api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
- instance for each request. \ No newline at end of file
+ instance for each request.
+
+== Filter based CORS support
+
+In order to support CORS with filter-based security frameworks like
+http://projects.spring.io/spring-security/[Spring Security], or
+with other libraries that do not support natively CORS, Spring Framework also
+provides a http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/filter/CorsFilter.html[`CorsFilter`].
+Instead of using `@CrossOrigin` or `WebMvcConfigurer#addCorsMappings(CorsRegistry)`, you
+need to register a custom filter defined like bellow:
+
+[source,java,indent=0]
+----
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+public class MyCorsFilter extends CorsFilter {
+
+ public MyCorsFilter() {
+ super(configurationSource());
+ }
+
+ private static UrlBasedCorsConfigurationSource configurationSource() {
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ config.addAllowedOrigin("http://domain1.com");
+ config.addAllowedHeader("*");
+ config.addAllowedMethod("*");
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", config);
+ return source;
+ }
+}
+----
+
+You need to ensure that `CorsFilter` is ordered before the other filters, see
+https://spring.io/blog/2015/06/08/cors-support-in-spring-framework#filter-based-cors-support[this blog post]
+about how to configure Spring Boot accordingly.
diff --git a/src/asciidoc/web-mvc.adoc b/src/asciidoc/web-mvc.adoc
index e1853347..65f5bdf7 100644
--- a/src/asciidoc/web-mvc.adoc
+++ b/src/asciidoc/web-mvc.adoc
@@ -25,7 +25,7 @@ For an explanation of this principle, refer to __Expert Spring Web MVC and Web F
Seth Ladd and others; specifically see the section "A Look At Design," on page 117 of
the first edition. Alternatively, see
-* http://www.objectmentor.com/resources/articles/ocp.pdf[Bob Martin, The Open-Closed
+* https://www.cs.duke.edu/courses/fall07/cps108/papers/ocp.pdf[Bob Martin, The Open-Closed
Principle (PDF)]
You cannot add advice to final methods when you use Spring MVC. For example, you cannot
@@ -37,7 +37,7 @@ add advice to final methods.
In Spring Web MVC you can use any object as a command or form-backing object; you do not
need to implement a framework-specific interface or base class. Spring's data binding is
highly flexible: for example, it treats type mismatches as validation errors that can be
-evaluated by the application, not as system errors. Thus you need not duplicate your
+evaluated by the application, not as system errors. Thus you do not need to duplicate your
business objects' properties as simple, untyped strings in your form objects simply to
handle invalid submissions, or to convert the Strings properly. Instead, it is often
preferable to bind directly to your business objects.
@@ -160,11 +160,44 @@ pattern that Spring Web MVC shares with many other leading web frameworks).
image::images/mvc.png[width=400]
The `DispatcherServlet` is an actual `Servlet` (it inherits from the `HttpServlet` base
+class), and as such is declared in your web application. You need to map requests that
+you want the `DispatcherServlet` to handle, by using a URL mapping. Here is a standard
+Java EE Servlet configuration in a Servlet 3.0+ environment:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ public class MyWebApplicationInitializer implements WebApplicationInitializer {
+
+ @Override
+ public void onStartup(ServletContext container) {
+ ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
+ registration.setLoadOnStartup(1);
+ registration.addMapping("/example/*");
+ }
+
+ }
+----
+
+In the preceding example, all requests starting with `/example` will be handled by the
+`DispatcherServlet` instance named `example`.
+
+`WebApplicationInitializer` is an interface provided by Spring MVC that ensures your
+code-based configuration is detected and automatically used to initialize any Servlet 3
+container. An abstract base class implementation of this interface named
+`AbstractAnnotationConfigDispatcherServletInitializer` makes it even easier to register the
+`DispatcherServlet` by simply specifying its servlet mapping and listing configuration
+classes - it's even the recommended way to set up your Spring MVC application.
+See <<mvc-container-config,Code-based Servlet container initialization>> for more details.
+
+The `DispatcherServlet` is an actual `Servlet` (it inherits from the `HttpServlet` base
class), and as such is declared in the `web.xml` of your web application. You need to
map requests that you want the `DispatcherServlet` to handle, by using a URL mapping in
the same `web.xml` file. This is standard Java EE Servlet configuration; the following
example shows such a `DispatcherServlet` declaration and mapping:
+Below is the `web.xml` equivalent of the above code based example:
+
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
@@ -183,41 +216,13 @@ example shows such a `DispatcherServlet` declaration and mapping:
</web-app>
----
-In the preceding example, all requests starting with `/example` will be handled by the
-`DispatcherServlet` instance named `example`. In a Servlet 3.0+ environment, you also
-have the option of configuring the Servlet container programmatically. Below is the code
-based equivalent of the above `web.xml` example:
-
-[source,java,indent=0]
-[subs="verbatim,quotes"]
-----
- public class MyWebApplicationInitializer implements WebApplicationInitializer {
-
- @Override
- public void onStartup(ServletContext container) {
- ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
- registration.setLoadOnStartup(1);
- registration.addMapping("/example/*");
- }
-
- }
-----
-
-`WebApplicationInitializer` is an interface provided by Spring MVC that ensures your
-code-based configuration is detected and automatically used to initialize any Servlet 3
-container. An abstract base class implementation of this interface named
-`AbstractDispatcherServletInitializer` makes it even easier to register the
-`DispatcherServlet` by simply specifying its servlet mapping.
-See <<mvc-container-config,Code-based Servlet container initialization>> for more details.
-
-The above is only the first step in setting up Spring Web MVC. You now need to configure
-the various beans used by the Spring Web MVC framework (over and above the
-`DispatcherServlet` itself).
As detailed in <<context-introduction>>, `ApplicationContext` instances in Spring can be
scoped. In the Web MVC framework, each `DispatcherServlet` has its own
`WebApplicationContext`, which inherits all the beans already defined in the root
-`WebApplicationContext`. These inherited beans can be overridden in the servlet-specific
+`WebApplicationContext`. The root `WebApplicationContext` should contain all the
+infrastructure beans that should be shared between your other contexts and Servlet
+instances. These inherited beans can be overridden in the servlet-specific
scope, and you can define new scope-specific beans local to a given Servlet instance.
.Typical context hierarchy in Spring Web MVC
@@ -295,7 +300,32 @@ a link to the `ServletContext`). The `WebApplicationContext` is bound in the
`ServletContext`, and by using static methods on the `RequestContextUtils` class you can
always look up the `WebApplicationContext` if you need access to it.
+Note that we can achieve the same with java-based configurations:
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ public class GolfingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
+
+ @Override
+ protected Class<?>[] getRootConfigClasses() {
+ // GolfingAppConfig defines beans that would be in root-context.xml
+ return new Class[] { GolfingAppConfig.class };
+ }
+
+ @Override
+ protected Class<?>[] getServletConfigClasses() {
+ // GolfingWebConfig defines beans that would be in golfing-servlet.xml
+ return new Class[] { GolfingWebConfig.class };
+ }
+
+ @Override
+ protected String[] getServletMappings() {
+ return new String[] { "/golfing/*" };
+ }
+
+ }
+----
[[mvc-servlet-special-bean-types]]
=== Special Bean Types In the WebApplicationContext
@@ -581,16 +611,16 @@ application that uses this annotation:
}
----
-In the example, the `@RequestMapping` is used in a number of places. The first usage is
-on the type (class) level, which indicates that all handling methods on this controller
+In the above example, `@RequestMapping` is used in a number of places. The first usage is
+on the type (class) level, which indicates that all handler methods in this controller
are relative to the `/appointments` path. The `get()` method has a further
-`@RequestMapping` refinement: it only accepts GET requests, meaning that an HTTP GET for
+`@RequestMapping` refinement: it only accepts `GET` requests, meaning that an HTTP `GET` for
`/appointments` invokes this method. The `add()` has a similar refinement, and the
-`getNewForm()` combines the definition of HTTP method and path into one, so that GET
+`getNewForm()` combines the definition of HTTP method and path into one, so that `GET`
requests for `appointments/new` are handled by that method.
The `getForDay()` method shows another usage of `@RequestMapping`: URI templates. (See
-<<mvc-ann-requestmapping-uri-templates,the next section >>).
+<<mvc-ann-requestmapping-uri-templates>>).
A `@RequestMapping` on the class level is not required. Without it, all paths are simply
absolute, and not relative. The following example from the __PetClinic__ sample
@@ -621,10 +651,66 @@ application shows a multi-action controller using `@RequestMapping`:
}
----
-The above example does not specify GET vs. PUT, POST, and so forth, because
-`@RequestMapping` maps all HTTP methods by default. Use `@RequestMapping(method=GET)`
-to narrow the mapping.
+The above example does not specify `GET` vs. `PUT`, `POST`, and so forth, because
+`@RequestMapping` maps all HTTP methods by default. Use `@RequestMapping(method=GET)` or
+`@GetMapping` to narrow the mapping.
+
+[[mvc-ann-requestmapping-composed]]
+==== Composed @RequestMapping Variants
+
+Spring Framework 4.3 introduces the following method-level _composed_ variants of the
+`@RequestMapping` annotation that help to simplify mappings for common HTTP methods and
+better express the semantics of the annotated handler method. For example, a
+`@GetMapping` can be read as a `GET` `@RequestMapping`.
+
+- `@GetMapping`
+- `@PostMapping`
+- `@PutMapping`
+- `@DeleteMapping`
+- `@PatchMapping`
+
+The following example shows a modified version of the `AppointmentsController` from the
+previous section that has been simplified with _composed_ `@RequestMapping` annotations.
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Controller
+ **@RequestMapping("/appointments")**
+ public class AppointmentsController {
+
+ private final AppointmentBook appointmentBook;
+
+ @Autowired
+ public AppointmentsController(AppointmentBook appointmentBook) {
+ this.appointmentBook = appointmentBook;
+ }
+
+ **@GetMapping**
+ public Map<String, Appointment> get() {
+ return appointmentBook.getAppointmentsForToday();
+ }
+ **@GetMapping("/{day}")**
+ public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
+ return appointmentBook.getAppointmentsForDay(day);
+ }
+
+ **@GetMapping("/new")**
+ public AppointmentForm getNewForm() {
+ return new AppointmentForm();
+ }
+
+ **@PostMapping**
+ public String add(@Valid AppointmentForm appointment, BindingResult result) {
+ if (result.hasErrors()) {
+ return "appointments/new";
+ }
+ appointmentBook.addAppointment(appointment);
+ return "redirect:/appointments";
+ }
+ }
+----
[[mvc-ann-requestmapping-proxying]]
==== @Controller and AOP Proxying
@@ -699,7 +785,7 @@ to the value of a URI template variable:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
+ @GetMapping("/owners/{ownerId}")
public String findOwner(**@PathVariable** String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
@@ -721,20 +807,21 @@ template variable by name. You can specify it in the annotation:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
+ @GetMapping("/owners/{ownerId}")
public String findOwner(**@PathVariable("ownerId")** String theOwner, Model model) {
// implementation omitted
}
----
Or if the URI template variable name matches the method argument name you can omit that
-detail. As long as your code is not compiled without debugging information, Spring MVC
-will match the method argument name to the URI template variable name:
+detail. As long as your code is compiled with debugging information or the `-parameters`
+compiler flag on Java 8, Spring MVC will match the method argument name to the URI
+template variable name:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
+ @GetMapping("/owners/{ownerId}")
public String findOwner(**@PathVariable** String ownerId, Model model) {
// implementation omitted
}
@@ -746,7 +833,7 @@ A method can have any number of `@PathVariable` annotations:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)
+ @GetMapping("/owners/{ownerId}/pets/{petId}")
public String findPet(**@PathVariable** String ownerId, **@PathVariable** String petId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
Pet pet = owner.getPet(petId);
@@ -758,7 +845,7 @@ A method can have any number of `@PathVariable` annotations:
When a `@PathVariable` annotation is used on a `Map<String, String>` argument, the map
is populated with all URI template variables.
-A URI template can be assembled from type and path level __@RequestMapping__
+A URI template can be assembled from type and method level __@RequestMapping__
annotations. As a result the `findPet()` method can be invoked with a URL such as
`/owners/42/pets/21`.
@@ -777,7 +864,7 @@ annotations. As a result the `findPet()` method can be invoked with a URL such a
}
----
-A `@PathVariable` argument can be of __any simple type__ such as int, long, Date, etc.
+A `@PathVariable` argument can be of __any simple type__ such as `int`, `long`, `Date`, etc.
Spring automatically converts to the appropriate type or throws a
`TypeMismatchException` if it fails to do so. You can also register support for parsing
additional data types. See <<mvc-ann-typeconversion>> and <<mvc-ann-webdatabinder>>.
@@ -790,24 +877,24 @@ Sometimes you need more precision in defining URI template variables. Consider t
The `@RequestMapping` annotation supports the use of regular expressions in URI template
variables. The syntax is `{varName:regex}` where the first part defines the variable
-name and the second - the regular expression.For example:
+name and the second - the regular expression. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
- public void handle(@PathVariable String version, @PathVariable String extension) {
- // ...
- }
+ public void handle(@PathVariable String version, @PathVariable String extension) {
+ // ...
}
----
[[mvc-ann-requestmapping-patterns]]
==== Path Patterns
-In addition to URI templates, the `@RequestMapping` annotation also supports Ant-style
-path patterns (for example, `/myPath/{asterisk}.do`). A combination of URI template variables and
-Ant-style globs is also supported (e.g. `/owners/{asterisk}/pets/{petId}`).
+In addition to URI templates, the `@RequestMapping` annotation and all _composed_
+`@RequestMapping` variants also support Ant-style path patterns (for example,
+`/myPath/{asterisk}.do`). A combination of URI template variables and Ant-style globs is
+also supported (e.g. `/owners/{asterisk}/pets/{petId}`).
[[mvc-ann-requestmapping-pattern-comparison]]
@@ -837,7 +924,7 @@ can be customized (see <<mvc-config-path-matching>> in the section on configurin
[[mvc-ann-requestmapping-placeholders]]
==== Path Patterns with Placeholders
-Patterns in `@RequestMapping` annotations support ${...} placeholders against local
+Patterns in `@RequestMapping` annotations support `${...}` placeholders against local
properties and/or system properties and environment variables. This may be useful in
cases where the path a controller is mapped to may need to be customized through
configuration. For more information on placeholders, see the javadocs of the
@@ -944,7 +1031,7 @@ Below is an example of extracting the matrix variable "q":
----
// GET /pets/42;q=11;r=22
- @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
+ @GetMapping("/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) {
// petId == 42
@@ -961,7 +1048,7 @@ specific to identify where the variable is expected to be:
----
// GET /owners/42;q=11/pets/21;q=22
- @RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
+ @GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable(name="q", pathVar="ownerId") int q1,
@MatrixVariable(name="q", pathVar="petId") int q2) {
@@ -979,7 +1066,7 @@ A matrix variable may be defined as optional and a default value specified:
----
// GET /pets/42
- @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
+ @GetMapping("/pets/{petId}")
public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) {
// q == 1
@@ -994,10 +1081,10 @@ All matrix variables may be obtained in a Map:
----
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23
- @RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
+ @GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
- @MatrixVariable Map<String, String> matrixVars,
- @MatrixVariable(pathVar="petId"") Map<String, String> petMatrixVars) {
+ @MatrixVariable MultiValueMap<String, String> matrixVars,
+ @MatrixVariable(pathVar="petId"") MultiValueMap<String, String> petMatrixVars) {
// matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
// petMatrixVars: ["q" : 11, "s" : 23]
@@ -1045,21 +1132,20 @@ to `false`.
[[mvc-ann-requestmapping-consumes]]
==== Consumable Media Types
You can narrow the primary mapping by specifying a list of consumable media types. The
-request will be matched only if the __Content-Type__ request header matches the specified
+request will be matched only if the `Content-Type` request header matches the specified
media type. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @Controller
- @RequestMapping(path = "/pets", method = RequestMethod.POST, **consumes="application/json"**)
+ @PostMapping(path = "/pets", **consumes = "application/json"**)
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
}
----
-Consumable media type expressions can also be negated as in __!text/plain__ to match to
-all requests other than those with __Content-Type__ of __text/plain__. Also consider
+Consumable media type expressions can also be negated as in `!text/plain` to match to
+all requests other than those with `Content-Type` of `text/plain`. Also consider
using constants provided in `MediaType` such as `APPLICATION_JSON_VALUE` and
`APPLICATION_JSON_UTF8_VALUE`.
@@ -1075,7 +1161,7 @@ rather than extend type-level consumable types.
[[mvc-ann-requestmapping-produces]]
==== Producible Media Types
You can narrow the primary mapping by specifying a list of producible media types. The
-request will be matched only if the __Accept__ request header matches one of these
+request will be matched only if the `Accept` request header matches one of these
values. Furthermore, use of the __produces__ condition ensures the actual content type
used to generate the response respects the media types specified in the __produces__
condition. For example:
@@ -1083,8 +1169,7 @@ condition. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @Controller
- @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, **produces = MediaType.APPLICATION_JSON_UTF8_VALUE**)
+ @GetMapping(path = "/pets/{petId}", **produces = MediaType.APPLICATION_JSON_UTF8_VALUE**)
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// implementation omitted
@@ -1100,8 +1185,8 @@ the `UTF-8` charset.
====
Just like with __consumes__, producible media type expressions can be negated as in
-__!text/plain__ to match to all requests other than those with an __Accept__ header
-value of __text/plain__. Also consider using constants provided in `MediaType` such
+`!text/plain` to match to all requests other than those with an `Accept` header
+value of `text/plain`. Also consider using constants provided in `MediaType` such
as `APPLICATION_JSON_VALUE` and `APPLICATION_JSON_UTF8_VALUE`.
[TIP]
@@ -1126,7 +1211,7 @@ example with a request parameter value condition:
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
- @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, **params="myParam=myValue"**)
+ @GetMapping(path = "/pets/{petId}", **params = "myParam=myValue"**)
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
@@ -1144,7 +1229,7 @@ specific request header value:
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
- @RequestMapping(path = "/pets", method = RequestMethod.GET, **headers="myHeader=myValue"**)
+ @GetMapping(path = "/pets", **headers = "myHeader=myValue"**)
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
@@ -1162,13 +1247,35 @@ respectively instead. They are intended specifically for that purpose.
====
+[[mvc-ann-requestmapping-head-options]]
+==== HTTP HEAD and HTTP OPTIONS
+
+`@RequestMapping` methods mapped to "GET" are also implicitly mapped to "HEAD",
+i.e. there is no need to have "HEAD" explicitly declared. An HTTP HEAD request
+is processed as if it were an HTTP GET except instead of writing the body only
+the number of bytes are counted and the "Content-Length" header set.
+
+`@RequestMapping` methods have built-in support for HTTP OPTIONS. By default an
+HTTP OPTIONS request is handled by setting the "Allow" response header to the
+HTTP methods explicitly declared on all `@RequestMapping` methods with matching
+URL patterns. When no HTTP methods are explicitly declared the "Allow" header
+is set to "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS". Ideally always declare the
+HTTP method(s) that an `@RequestMapping` method is intended to handle, or alternatively
+use one of the dedicated _composed_ `@RequestMapping` variants (see
+<<mvc-ann-requestmapping-composed>>).
+
+Although not necessary an `@RequestMapping` method can be mapped to and handle
+either HTTP HEAD or HTTP OPTIONS, or both.
+
+
+
[[mvc-ann-methods]]
=== Defining @RequestMapping handler methods
-An `@RequestMapping` handler method can have a very flexible signatures. The supported
+`@RequestMapping` handler methods can have very flexible signatures. The supported
method arguments and return values are described in the following section. Most
-arguments can be used in arbitrary order with the only exception of `BindingResult`
+arguments can be used in arbitrary order with the only exception being `BindingResult`
arguments. This is described in the next section.
[NOTE]
@@ -1195,7 +1302,7 @@ The following are the supported method arguments:
[NOTE]
====
Session access may not be thread-safe, in particular in a Servlet environment. Consider
-setting the ++RequestMappingHandlerAdapter++'s "synchronizeOnSession" flag to "true" if
+setting the ``RequestMappingHandlerAdapter``'s "synchronizeOnSession" flag to "true" if
multiple requests are allowed to access a session concurrently.
====
@@ -1226,13 +1333,18 @@ multiple requests are allowed to access a session concurrently.
See <<mvc-ann-requestheader>>.
* `@RequestBody` annotated parameters for access to the HTTP request body. Parameter
values are converted to the declared method argument type using
- ++HttpMessageConverter++s. See <<mvc-ann-requestbody>>.
+ ``HttpMessageConverter``s. See <<mvc-ann-requestbody>>.
* `@RequestPart` annotated parameters for access to the content of a
"multipart/form-data" request part. See <<mvc-multipart-forms-non-browsers>> and
<<mvc-multipart>>.
+* `@SessionAttribute` annotated parameters for access to existing, permanent
+ session attributes (e.g. user authentication object) as opposed to model
+ attributes temporarily stored in the session as part of a controller workflow
+ via `@SessionAttributes`.
+* `@RequestAttribute` annotated parameters for access to request attributes.
* `HttpEntity<?>` parameters for access to the Servlet request HTTP headers and
contents. The request stream will be converted to the entity body using
- ++HttpMessageConverter++s. See <<mvc-ann-httpentity>>.
+ ``HttpMessageConverter``s. See <<mvc-ann-httpentity>>.
* `java.util.Map` / `org.springframework.ui.Model` / `org.springframework.ui.ModelMap`
for enriching the implicit model that is exposed to the web view.
* `org.springframework.web.servlet.mvc.support.RedirectAttributes` to specify the exact
@@ -1245,7 +1357,7 @@ multiple requests are allowed to access a session concurrently.
methods and/or the HandlerAdapter configuration. See the `webBindingInitializer`
property on `RequestMappingHandlerAdapter`. Such command objects along with their
validation results will be exposed as model attributes by default, using the command
- class class name - e.g. model attribute "orderAddress" for a command object of type
+ class name - e.g. model attribute "orderAddress" for a command object of type
"some.package.OrderAddress". The `ModelAttribute` annotation can be used on a method
argument to customize the model attribute name used.
* `org.springframework.validation.Errors` /
@@ -1267,7 +1379,7 @@ sample won't work:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(method = RequestMethod.POST)
+ @PostMapping
public String processSubmit(**@ModelAttribute("pet") Pet pet**, Model model, **BindingResult result**) { ... }
----
@@ -1277,7 +1389,7 @@ this working you have to reorder the parameters as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(method = RequestMethod.POST)
+ @PostMapping
public String processSubmit(**@ModelAttribute("pet") Pet pet**, **BindingResult result**, Model model) { ... }
----
@@ -1315,10 +1427,10 @@ The following are the supported return types:
signature).
* If the method is annotated with `@ResponseBody`, the return type is written to the
response HTTP body. The return value will be converted to the declared method argument
- type using ++HttpMessageConverter++s. See <<mvc-ann-responsebody>>.
+ type using ``HttpMessageConverter``s. See <<mvc-ann-responsebody>>.
* An `HttpEntity<?>` or `ResponseEntity<?>` object to provide access to the Servlet
response HTTP headers and contents. The entity body will be converted to the response
- stream using ++HttpMessageConverter++s. See <<mvc-ann-httpentity>>.
+ stream using ``HttpMessageConverter``s. See <<mvc-ann-httpentity>>.
* An `HttpHeaders` object to return a response with no body.
* A `Callable<?>` can be returned when the application wants to produce the return value
asynchronously in a thread managed by Spring MVC.
@@ -1357,7 +1469,7 @@ The following code snippet shows the usage:
// ...
- @RequestMapping(method = RequestMethod.GET)
+ @GetMapping
public String setupForm(**@RequestParam("petId") int petId**, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
@@ -1370,7 +1482,7 @@ The following code snippet shows the usage:
----
Parameters using this annotation are required by default, but you can specify that a
-parameter is optional by setting ++@RequestParam++'s `required` attribute to `false`
+parameter is optional by setting ``@RequestParam``'s `required` attribute to `false`
(e.g., `@RequestParam(path="id", required=false)`).
Type conversion is applied automatically if the target method parameter type is not
@@ -1389,7 +1501,7 @@ be bound to the value of the HTTP request body. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/something", method = RequestMethod.PUT)
+ @PutMapping("/something")
public void handle(@RequestBody String body, Writer writer) throws IOException {
writer.write(body);
}
@@ -1461,14 +1573,14 @@ or the MVC Java config.
[[mvc-ann-responsebody]]
==== Mapping the response body with the @ResponseBody annotation
-The `@ResponseBody` annotation is similar to `@RequestBody`. This annotation can be put
+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:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/something", method = RequestMethod.PUT)
+ @GetMapping("/something")
@ResponseBody
public String helloWorld() {
return "Hello World";
@@ -1487,7 +1599,7 @@ section and <<rest-message-conversion,Message Converters>>.
It's a very common use case to have Controllers implement a REST API, thus serving only
JSON, XML or custom MediaType content. For convenience, instead of annotating all your
-`@RequestMapping` methods with `@ResponseBody`, you can annotate your Controller Class
+`@RequestMapping` methods with `@ResponseBody`, you can annotate your controller Class
with `@RestController`.
{api-spring-framework}/web/bind/annotation/RestController.html[`@RestController`]
@@ -1495,8 +1607,9 @@ is a stereotype annotation that combines `@ResponseBody` and `@Controller`. More
that, it gives more meaning to your Controller and also may carry additional semantics
in future releases of the framework.
-As with regular ++@Controller++s, a `@RestController` may be assisted by a
-`@ControllerAdvice` Bean. See the <<mvc-ann-controller-advice>> section for more details.
+As with regular ``@Controller``s, a `@RestController` may be assisted by
+`@ControllerAdvice` or `@RestControllerAdvice` beans. See the <<mvc-ann-controller-advice>>
+section for more details.
[[mvc-ann-httpentity]]
==== Using HttpEntity
@@ -1578,7 +1691,7 @@ depending on your needs.
A controller can have any number of `@ModelAttribute` methods. All such methods are
invoked before `@RequestMapping` methods of the same controller.
-`@ModelAttribute` methods can also be defined in an ++@ControllerAdvice++-annotated class
+`@ModelAttribute` methods can also be defined in an ``@ControllerAdvice``-annotated class
and such methods apply to many controllers. See the <<mvc-ann-controller-advice>> section
for more details.
@@ -1595,8 +1708,8 @@ i.e., with or without an attribute name.
The `@ModelAttribute` annotation can be used on `@RequestMapping` methods as well. In
that case the return value of the `@RequestMapping` method is interpreted as a model
-attribute rather than as a view name. The view name is derived from view name
-conventions instead much like for methods returning void -- see <<mvc-coc-r2vnt>>.
+attribute rather than as a view name. The view name is then derived based on view name
+conventions instead, much like for methods returning `void` -- see <<mvc-coc-r2vnt>>.
[[mvc-ann-modelattrib-method-args]]
@@ -1615,7 +1728,7 @@ form field individually.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
+ @PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@ModelAttribute Pet pet**) { }
----
@@ -1629,7 +1742,7 @@ Given the above example where can the Pet instance come from? There are several
more detail below).
* It may be instantiated using its default constructor.
-An `@ModelAttribute` method is a common way to to retrieve an attribute from the
+An `@ModelAttribute` method is a common way to retrieve an attribute from the
database, which may optionally be stored between requests through the use of
`@SessionAttributes`. In some cases it may be convenient to retrieve the attribute by
using an URI template variable and a type converter. Here is an example:
@@ -1637,9 +1750,9 @@ using an URI template variable and a type converter. Here is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/accounts/{account}", method = RequestMethod.PUT)
+ @PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) {
-
+ // ...
}
----
@@ -1662,7 +1775,7 @@ following the `@ModelAttribute` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
+ @PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
if (result.hasErrors()) {
@@ -1678,6 +1791,31 @@ With a `BindingResult` you can check if errors were found in which case it's com
render the same form where the errors can be shown with the help of Spring's `<errors>`
form tag.
+Note that in some cases it may be useful to gain access to an attribute in the
+model without data binding. For such cases you may inject the `Model` into the
+controller or alternatively use the `binding` flag on the annotation:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+@ModelAttribute
+public AccountForm setUpForm() {
+ return new AccountForm();
+}
+
+@ModelAttribute
+public Account findAccount(@PathVariable String accountId) {
+ return accountRepository.findOne(accountId);
+}
+
+@PostMapping("update")
+public String update(@Valid AccountUpdateForm form, BindingResult result,
+ **@ModelAttribute(binding=false)** Account account) {
+
+ // ...
+}
+----
+
In addition to data binding you can also invoke validation using your own custom
validator passing the same `BindingResult` that was used to record data binding errors.
That allows for data binding and validation errors to be accumulated in one place and
@@ -1686,7 +1824,7 @@ subsequently reported back to the user:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
+ @PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
new PetValidator().validate(pet, result);
@@ -1705,7 +1843,7 @@ annotation:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
+ @PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@Valid @ModelAttribute("pet") Pet pet**, BindingResult result) {
if (result.hasErrors()) {
@@ -1721,6 +1859,7 @@ See <<validation-beanvalidation>> and <<validation>> for details on how to confi
use validation.
+
[[mvc-ann-sessionattrib]]
==== Using @SessionAttributes to store model attributes in the HTTP session between requests
@@ -1744,6 +1883,49 @@ attribute name:
----
+[[mvc-ann-sessionattrib-global]]
+==== Using @SessionAttribute to access pre-existing global session attributes
+
+If you need access to pre-existing session attributes that are managed globally,
+i.e. outside the controller (e.g. by a filter), and may or may not be present
+use the `@SessionAttribute` annotation on a method parameter:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @RequestMapping("/")
+ public String handle(**@SessionAttribute** User user) {
+ // ...
+ }
+----
+
+For use cases that require adding or removing session attributes consider injecting
+`org.springframework.web.context.request.WebRequest` or
+`javax.servlet.http.HttpSession` into the controller method.
+
+For temporary storage of model attributes in the session as part of a controller
+workflow consider using `SessionAttributes` as described in
+<<mvc-ann-sessionattrib>>.
+
+
+[[mvc-ann-requestattrib]]
+==== Using @RequestAttribute to access request attributes
+
+Similar to `@SessionAttribute` the `@RequestAttribute` annotation can be used to
+access pre-existing request attributes created by a filter or interceptor:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @RequestMapping("/")
+ public String handle(**@RequestAttribute** Client client) {
+ // ...
+ }
+----
+
+
+
+
[[mvc-ann-form-urlencoded-data]]
==== Working with "application/x-www-form-urlencoded" data
@@ -1898,8 +2080,8 @@ binding directly within your controller class. `@InitBinder` identifies methods
initialize the `WebDataBinder` that will be used to populate command and form object
arguments of annotated handler methods.
-Such init-binder methods support all arguments that `@RequestMapping` supports, except
-for command/form objects and corresponding validation result objects. Init-binder
+Such init-binder methods support all arguments that `@RequestMapping` methods support,
+except for command/form objects and corresponding validation result objects. Init-binder
methods must not have a return value. Thus, they are usually declared as `void`.
Typical arguments include `WebDataBinder` in combination with `WebRequest` or
`java.util.Locale`, allowing code to register context-specific editors.
@@ -1914,7 +2096,7 @@ The following example demonstrates the use of `@InitBinder` to configure a
public class MyFormController {
**@InitBinder**
- public void initBinder(WebDataBinder binder) {
+ protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
@@ -1937,7 +2119,7 @@ controller-specific tweaking of the binding rules.
public class MyFormController {
**@InitBinder**
- public void initBinder(WebDataBinder binder) {
+ protected void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
@@ -1969,13 +2151,13 @@ PropertyEditors required by several of the PetClinic controllers.
</bean>
----
-`@InitBinder` methods can also be defined in an ++@ControllerAdvice++-annotated class in
+`@InitBinder` methods can also be defined in an ``@ControllerAdvice``-annotated class in
which case they apply to matching controllers. This provides an alternative to using a
`WebBindingInitializer`. See the <<mvc-ann-controller-advice>> section for more details.
[[mvc-ann-controller-advice]]
-==== Advising controllers with @ControllerAdvice
+==== Advising controllers with @ControllerAdvice and @RestControllerAdvice
The `@ControllerAdvice` annotation is a component annotation allowing implementation
classes to be auto-detected through classpath scanning. It is automatically enabled when
@@ -1986,8 +2168,10 @@ Classes annotated with `@ControllerAdvice` can contain `@ExceptionHandler`,
`@RequestMapping` methods across all controller hierarchies as opposed to the controller
hierarchy within which they are declared.
-The `@ControllerAdvice` annotation can also target a subset of controllers with its
-attributes:
+`@RestControllerAdvice` is an alternative where `@ExceptionHandler` methods
+assume `@ResponseBody` semantics by default.
+
+Both `@ControllerAdvice` and `@RestControllerAdvice` can target a subset of controllers:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -2026,7 +2210,7 @@ the view class or interface to be used:
@RestController
public class UserController {
- @RequestMapping(path = "/user", method = RequestMethod.GET)
+ @GetMapping("/user")
@JsonView(User.WithoutPasswordView.class)
public User getUser() {
return new User("eric", "7!jd#h23");
@@ -2078,7 +2262,7 @@ to the model:
@Controller
public class UserController extends AbstractController {
- @RequestMapping(path = "/user", method = RequestMethod.GET)
+ @GetMapping("/user")
public String getUser(Model model) {
model.addAttribute("user", new User("eric", "7!jd#h23"));
model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class);
@@ -2126,7 +2310,7 @@ is an example of such a controller method:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(method=RequestMethod.POST)
+ @PostMapping
public Callable<String> processUpload(final MultipartFile file) {
return new Callable<String>() {
@@ -2357,7 +2541,7 @@ For applications configured with a `web.xml` be sure to update to version 3.0:
----
Asynchronous support must be enabled on the `DispatcherServlet` through the
-`<async-supported>true</async-supported>` web.xml sub-element. Additionally
+`<async-supported>true</async-supported>` sub-element in `web.xml`. Additionally
any `Filter` that participates in asyncrequest processing must be configured
to support the ASYNC dispatcher type. It should be safe to enable the ASYNC
dispatcher type for all filters provided with the Spring Framework since they
@@ -2396,7 +2580,7 @@ Below is some example web.xml configuration:
If using Servlet 3, Java based configuration for example via `WebApplicationInitializer`,
you'll also need to set the "asyncSupported" flag as well as the ASYNC dispatcher type
just like with `web.xml`. To simplify all this configuration, consider extending
-`AbstractDispatcherServletInitializer` or
+`AbstractDispatcherServletInitializer`, or better
`AbstractAnnotationConfigDispatcherServletInitializer` which automatically
set those options and make it very easy to register `Filter` instances.
@@ -2442,7 +2626,7 @@ don't need to do that because the `RequestMappingHandlerMapping` automatically l
all `HandlerMapping` classes extending from `AbstractHandlerMapping` have the following
properties that you can use to customize their behavior:
-* `interceptors` List of interceptors to use. ++HandlerInterceptor++s are discussed in
+* `interceptors` List of interceptors to use. ``HandlerInterceptor``s are discussed in
<<mvc-handlermapping-interceptor>>.
* `defaultHandler` Default handler to use, when this handler mapping does not result in
a matching handler.
@@ -2519,7 +2703,7 @@ the example below:
<property name="openingTime" value="9"/>
<property name="closingTime" value="18"/>
</bean>
- <beans>
+ </beans>
----
[source,java,indent=0]
@@ -2823,7 +3007,7 @@ through `Model` nor `RedirectAttributes`. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/files/{path}", method = RequestMethod.POST)
+ @PostMapping("/files/{path}")
public String upload(...) {
// ...
return "redirect:files/{path}";
@@ -2995,7 +3179,7 @@ application/atom+xml is shown below.
private List<SampleContent> contentList = new ArrayList<SampleContent>();
- @RequestMapping(path="/content", method=RequestMethod.GET)
+ @GetMapping("/content")
public ModelAndView getContent() {
ModelAndView mav = new ModelAndView();
mav.setViewName("content");
@@ -3143,11 +3327,11 @@ Spring MVC also provides a mechanism for building links to controller methods. F
@RequestMapping("/hotels/{hotel}")
public class BookingController {
- @RequestMapping("/bookings/{booking}")
+ @GetMapping("/bookings/{booking}")
public String getBooking(@PathVariable Long booking) {
// ...
-
+ }
}
----
@@ -3249,7 +3433,7 @@ You can prepare a link from a JSP as follows:
----
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
...
-<a href="${s:mvcUrl(''PAC#getAddress'').arg(0,''US'').buildAndExpand(''123'')}">Get Address</a>
+<a href="${s:mvcUrl('PAC#getAddress').arg(0,'US').buildAndExpand('123')}">Get Address</a>
----
The above example relies on the `mvcUrl` JSP function declared in the Spring tag library
@@ -3318,7 +3502,7 @@ maximum age. Find below an example of defining a `CookieLocaleResolver`.
<property name="cookieName" value="clientlanguage"/>
<!-- in seconds. If set to -1, the cookie is not persisted (deleted when browser shuts down) -->
- <property name="cookieMaxAge" value="100000">
+ <property name="cookieMaxAge" value="100000"/>
</bean>
----
@@ -3447,9 +3631,9 @@ defined in the previous example to customize the look and feel:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
- <link rel="stylesheet" href="<spring:theme code=''styleSheet''/>" type="text/css"/>
+ <link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type="text/css"/>
</head>
- <body style="background=<spring:theme code=''background''/>">
+ <body style="background=<spring:theme code='background'/>">
...
</body>
</html>
@@ -3608,7 +3792,7 @@ use `MultipartHttpServletRequest` or `MultipartFile` in the method parameters:
@Controller
public class FileUploadController {
- @RequestMapping(path = "/form", method = RequestMethod.POST)
+ @PostMapping("/form")
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) {
@@ -3637,7 +3821,7 @@ the method parameter:
@Controller
public class FileUploadController {
- @RequestMapping(path = "/form", method = RequestMethod.POST)
+ @PostMapping("/form")
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("file") Part file) {
@@ -3695,7 +3879,7 @@ multipart:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping(path = "/someUrl", method = RequestMethod.POST)
+ @PostMapping("/someUrl")
public String onSubmit(**@RequestPart("meta-data") MetaData metadata,
@RequestPart("file-data") MultipartFile file**) {
@@ -3754,7 +3938,7 @@ may be more convenient to directly set the status of the response and optionally
error content to the body of the response.
You can do that with `@ExceptionHandler` methods. When declared within a controller such
-methods apply to exceptions raised by `@RequestMapping` methods of that contoroller (or
+methods apply to exceptions raised by `@RequestMapping` methods of that controller (or
any of its sub-classes). You can also declare an `@ExceptionHandler` method within an
`@ControllerAdvice` class in which case it handles exceptions from `@RequestMapping`
methods from many controllers. Below is an example of a controller-local
@@ -3802,7 +3986,7 @@ raised the status code may indicate a client error (4xx) or a server error (5xx)
The `DefaultHandlerExceptionResolver` translates Spring MVC exceptions to specific error
status codes. It is registered by default with the MVC namespace, the MVC Java config,
-and also by the the `DispatcherServlet` (i.e. when not using the MVC namespace or Java
+and also by the `DispatcherServlet` (i.e. when not using the MVC namespace or Java
config). Listed below are some of the exceptions handled by this resolver and the
corresponding status codes:
@@ -4205,7 +4389,6 @@ responsible for this, along with conditional headers such as `'Last-Modified'` a
The `'Cache-Control'` HTTP response header advises private caches (e.g. browsers) and
public caches (e.g. proxies) on how they can cache HTTP responses for further reuse.
-mvc-config-static-resources
An http://en.wikipedia.org/wiki/HTTP_ETag[ETag] (entity tag) is an HTTP response header
returned by an HTTP/1.1 compliant web server used to determine change in content at a
given URL. It can be considered to be the more sophisticated successor to the
@@ -4305,14 +4488,14 @@ This involves calculating a lastModified `long` and/or an Etag value for a given
comparing it against the `'If-Modified-Since'` request header value, and potentially returning
a response with status code 304 (Not Modified).
-As described in <<mvc-ann-httpentity>>, Controllers can interact with the request/response using
+As described in <<mvc-ann-httpentity>>, controllers can interact with the request/response using
`HttpEntity` types. Controllers returning `ResponseEntity` can include HTTP caching information
in responses like this:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
- @RequestMapping("/book/{id}")
+ @GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id) {
Book book = findBook(id);
@@ -4353,17 +4536,24 @@ This can be achieved as follows:
----
There are two key elements here: calling `request.checkNotModified(lastModified)` and
-returning `null`. The former sets the response status to 304 before it returns `true`.
+returning `null`. The former sets the appropriate response status and headers
+before it returns `true`.
The latter, in combination with the former, causes Spring MVC to do no further
processing of the request.
Note that there are 3 variants for this:
* `request.checkNotModified(lastModified)` compares lastModified with the
-`'If-Modified-Since'` request header
-* `request.checkNotModified(eTag)` compares eTag with the `'ETag'` request header
+`'If-Modified-Since'` or `'If-Unmodified-Since'` request header
+* `request.checkNotModified(eTag)` compares eTag with the `'If-None-Match'` request header
* `request.checkNotModified(eTag, lastModified)` does both, meaning that both
-conditions should be valid for the server to issue an `HTTP 304 Not Modified` response
+conditions should be valid
+
+When receiving conditional `'GET'`/`'HEAD'` requests, `checkNotModified` will check
+that the resource has not been modified and if so, it will result in a `HTTP 304 Not Modified`
+response. In case of conditional `'POST'`/`'PUT'`/`'DELETE'` requests, `checkNotModified`
+will check that the resource has not been modified and if it has been, it will result in a
+`HTTP 409 Precondition Failed` response to prevent concurrent modifications.
[[mvc-httpcaching-shallowetag]]
@@ -4376,14 +4566,15 @@ ETags, more about that later).The filter caches the content of the rendered JSP
other content), generates an MD5 hash over that, and returns that as an ETag header in
the response. The next time a client sends a request for the same resource, it uses that
hash as the `If-None-Match` value. The filter detects this, renders the view again, and
-compares the two hashes. If they are equal, a `304` is returned. This filter will not
-save processing power, as the view is still rendered. The only thing it saves is
-bandwidth, as the rendered response is not sent back over the wire.
+compares the two hashes. If they are equal, a `304` is returned.
Note that this strategy saves network bandwidth but not CPU, as the full response must be
computed for each request. Other strategies at the controller level (described above) can
save network bandwidth and avoid computation.
-mvc-config-static-resources
+
+This filter has a `writeWeakETag` parameter that configures the filter to write Weak ETags,
+like this: `W/"02a2d595e6ed9a0b24f027f2b63b134d6"`, as defined in
+https://tools.ietf.org/html/rfc7232#section-2.3[RFC 7232 Section 2.3].
You configure the `ShallowEtagHeaderFilter` in `web.xml`:
@@ -4393,6 +4584,12 @@ You configure the `ShallowEtagHeaderFilter` in `web.xml`:
<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
+ <!-- Optional parameter that configures the filter to write weak ETags
+ <init-param>
+ <param-name>writeWeakETag</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ -->
</filter>
<filter-mapping>
@@ -4453,7 +4650,9 @@ implementation is detected and automatically used to initialize any Servlet 3 co
An abstract base class implementation of `WebApplicationInitializer` named
`AbstractDispatcherServletInitializer` makes it even easier to register the
`DispatcherServlet` by simply overriding methods to specify the servlet mapping and the
-location of the `DispatcherServlet` configuration:
+location of the `DispatcherServlet` configuration.
+
+This is recommended for applications that use Java-based Spring configuration:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -4478,8 +4677,7 @@ location of the `DispatcherServlet` configuration:
}
----
-The above example is for an application that uses Java-based Spring configuration. If
-using XML-based Spring configuration, extend directly from
+If using XML-based Spring configuration, you should extend directly from
`AbstractDispatcherServletInitializer`:
[source,java,indent=0]
@@ -4547,9 +4745,9 @@ the MVC Java config and the MVC XML namespace.
The MVC Java config and the MVC namespace provide similar default configuration that
overrides the `DispatcherServlet` defaults. The goal is to spare most applications from
-having to having to create the same configuration and also to provide higher-level
-constructs for configuring Spring MVC that serve as a simple starting point and require
-little or no prior knowledge of the underlying configuration.
+having to create the same configuration and also to provide higher-level constructs for
+configuring Spring MVC that serve as a simple starting point and require little or no
+prior knowledge of the underlying configuration.
You can choose either the MVC Java config or the MVC namespace depending on your
preference. Also as you will see further below, with the MVC Java config it is easier to
diff --git a/src/asciidoc/web-portlet.adoc b/src/asciidoc/web-portlet.adoc
index 91d75608..b93a642e 100644
--- a/src/asciidoc/web-portlet.adoc
+++ b/src/asciidoc/web-portlet.adoc
@@ -333,7 +333,7 @@ action request, handling a render request, and returning a model and a view.
=== AbstractController and PortletContentGenerator
Of course, just a `Controller` interface isn't enough. To provide a basic
-infrastructure, all of Spring Portlet MVC's ++Controller++s inherit from
+infrastructure, all of Spring Portlet MVC's ``Controller``s inherit from
`AbstractController`, a class offering access to Spring's `ApplicationContext` and
control over caching.
@@ -542,7 +542,7 @@ The rest of this section describes three of Spring Portlet MVC's most commonly u
handler mappings. They all extend `AbstractHandlerMapping` and share the following
properties:
-* `interceptors`: The list of interceptors to use. ++HandlerInterceptor++s are discussed
+* `interceptors`: The list of interceptors to use. ``HandlerInterceptor``s are discussed
in <<portlet-handlermapping-interceptor>>.
* `defaultHandler`: The default handler to use, when this handler mapping does not
result in a matching handler.
@@ -1006,7 +1006,7 @@ register any custom property editor because there is no type conversion to be pe
[[portlet-exceptionresolver]]
== Handling exceptions
-Just like Servlet MVC, Portlet MVC provides ++HandlerExceptionResolver++s to ease the
+Just like Servlet MVC, Portlet MVC provides ``HandlerExceptionResolver``s to ease the
pain of unexpected exceptions that occur while your request is being processed by a
handler that matched the request. Portlet MVC also provides a portlet-specific, concrete
`SimpleMappingExceptionResolver` that enables you to take the class name of any
@@ -1462,8 +1462,8 @@ The following example demonstrates the use of `@InitBinder` for configuring a
public class MyFormController {
@InitBinder
- public void initBinder(WebDataBinder binder) {
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ protected void initBinder(WebDataBinder binder) {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
diff --git a/src/asciidoc/web-view.adoc b/src/asciidoc/web-view.adoc
index a62ed593..3735a8d3 100644
--- a/src/asciidoc/web-view.adoc
+++ b/src/asciidoc/web-view.adoc
@@ -34,12 +34,12 @@ is another view technology, supported by Spring. This template engine is a templ
aimed at generating XML-like markup (XML, XHTML, HTML5, ...​), but that can be used to generate any
text based content.
-This requires Groovy 2.3.1+ on the the classpath.
+This requires Groovy 2.3.1+ on the classpath.
[[view-groovymarkup-configuration]]
=== Configuration
-Configuring the Groovy Markup Teplate Engine is quite easy:
+Configuring the Groovy Markup Template Engine is quite easy:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -106,6 +106,13 @@ applications. The languages are quite similar and serve similar needs and so are
considered together in this section. For semantic and syntactic differences between the
two languages, see the http://www.freemarker.org[FreeMarker] web site.
+[NOTE]
+====
+As of Spring Framework 4.3, Velocity support has been deprecated due to six years
+without active maintenance of the Apache Velocity project. We recommend Spring's
+FreeMarker support instead, or Thymeleaf which comes with Spring support itself.
+====
+
[[view-velocity-dependencies]]
@@ -292,13 +299,10 @@ directly, the files are called spring.vm / spring.ftl and are in the packages
[[view-simple-binding]]
==== Simple binding
-In your html forms (vm / ftl templates) that act as the 'formView' for a Spring form
+In your HTML forms (vm / ftl templates) which act as a form view for a Spring MVC
controller, you can use code similar to the following to bind to field values and
display error messages for each input field in similar fashion to the JSP equivalent.
-Note that the name of the command object is "command" by default, but can be overridden
-in your MVC configuration by setting the 'commandName' bean property on your form
-controller. Example code is shown below for the `personFormV` and `personFormF` views
-configured earlier;
+Example code is shown below for the `personFormV`/`personFormF` views configured earlier:
[source,xml,indent=0]
[subs="verbatim,quotes"]
@@ -308,7 +312,7 @@ configured earlier;
...
<form action="" method="POST">
Name:
- #springBind( "command.name" )
+ #springBind("myModelObject.name")
<input type="text"
name="${status.expression}"
value="$!status.value"/><br>
@@ -331,10 +335,10 @@ configured earlier;
...
<form action="" method="POST">
Name:
- <@spring.bind "command.name"/>
+ <@spring.bind "myModelObject.name"/>
<input type="text"
name="${spring.status.expression}"
- value="${spring.status.value?default("")}"/><br>
+ value="${spring.status.value?html}"/><br>
<#list spring.status.errorMessages as error> <b>${error}</b> <br> </#list>
<br>
...
@@ -818,7 +822,7 @@ The preceding JSP assumes that the variable name of the form backing object is
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
- <form:form commandName="user">
+ <form:form modelAttribute="user">
<table>
<tr>
<td>First Name:</td>
@@ -1390,6 +1394,7 @@ The HTML would look like:
<input type="submit" value="Save Changes"/>
</td>
</tr>
+ </table>
</form>
----
diff --git a/src/asciidoc/web-websocket.adoc b/src/asciidoc/web-websocket.adoc
index 9a2b8087..2776f53c 100644
--- a/src/asciidoc/web-websocket.adoc
+++ b/src/asciidoc/web-websocket.adoc
@@ -1359,7 +1359,8 @@ The return value from an `@MessageMapping` method is converted with a
of a new message that is then sent, by default, to the `"brokerChannel"` with
the same destination as the client message but using the prefix `"/topic"` by
default. An `@SendTo` message level annotation can be used to specify any
-other destination instead.
+other destination instead. It can also be set a class-level to share a common
+destination.
An `@SubscribeMapping` annotation can also be used to map subscription requests
to `@Controller` methods. It is supported on the method level, but can also be
@@ -1529,13 +1530,13 @@ This connection is used for messages originating from the server-side applicatio
only, not for receiving messages. You can configure the STOMP credentials
for this connection, i.e. the STOMP frame `login` and `passcode` headers. This
is exposed in both the XML namespace and the Java config as the
-++systemLogin++/++systemPasscode++ properties with default values ++guest++/++guest++.
+``systemLogin``/``systemPasscode`` properties with default values ``guest``/``guest``.
The STOMP broker relay also creates a separate TCP connection for every connected
WebSocket client. You can configure the STOMP credentials to use for all TCP
connections created on behalf of clients. This is exposed in both the XML namespace
-and the Java config as the ++clientLogin++/++clientPasscode++ properties with default
-values ++guest++/++guest++.
+and the Java config as the ``clientLogin``/``clientPasscode`` properties with default
+values ``guest``/``guest``.
[NOTE]
====
@@ -1699,7 +1700,8 @@ than their name and the generic destination. This is also supported through an
annotation as well as a messaging template.
For example, a message-handling method can send messages to the user associated with
-the message being handled through the `@SendToUser` annotation:
+the message being handled through the `@SendToUser` annotation (also supported on
+the class-level to share a common destination):
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -1882,41 +1884,40 @@ to access information about the message.
[[websocket-stomp-client]]
=== STOMP Client
-Spring provides STOMP/WebSocket client and STOMP/TCP client support with the
-following built-in choices (other libraries can be adapted):
+Spring provides a STOMP over WebSocket client and a STOMP over TCP client.
-* `WebSocketStompClient` built on the Spring WebSocket API with
- support for standard JSR-356 WebSocket, Jetty 9, as well as SockJS
- for HTTP-based WebSocket emulation (see <<websocket-fallback-sockjs-client>>).
-* `Reactor11TcpStompClient` built on `NettyTcpClient` from the reactor-net project.
-
-To begin, create and configure the client:
+To begin create and configure `WebSocketStompClient`:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
-WebSocketClient transport = new StandardWebSocketClient();
-WebSocketStompClient stompClient = new WebSocketStompClient(transport);
+WebSocketClient webSocketClient = new StandardWebSocketClient();
+WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setMessageConverter(new StringMessageConverter());
-stompClient.setTaskScheduler(taskScheduler); // for heartbeats, receipts
+stompClient.setTaskScheduler(taskScheduler); // for heartbeats
----
-Then connect to the WebSocket and provide a handler for the STOMP session:
+In the above example `StandardWebSocketClient` could be replaced with `SockJsClient`
+since that is also an implementation of `WebSocketClient`. The `SockJsClient` can
+use WebSocket or HTTP-based transport as a fallback. For more details see
+<<websocket-fallback-sockjs-client>>.
+
+Next establish a connection and provide a handler for the STOMP session:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
String url = "ws://127.0.0.1:8080/endpoint";
-StompSessionHandler handler = ... ;
-stompClient.connect(url, handler);
+StompSessionHandler sessionHandler = new MyStompSessionHandler();
+stompClient.connect(url, sessionHandler);
----
-When the session is ready for use, the handler is notified:
+When the session is ready for use the handler is notified:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MySessionHandler extends StompSessionHandlerAdapter {
+public class MyStompSessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
@@ -1925,7 +1926,8 @@ public class MySessionHandler extends StompSessionHandlerAdapter {
}
----
-Send any Object as the payload and it will be serialized with a `MessageConverter`:
+Once the session is established any payload can be sent and that will be
+serialized with the configured `MessageConverter`:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -1933,10 +1935,10 @@ Send any Object as the payload and it will be serialized with a `MessageConverte
session.send("/topic/foo", "payload");
----
-The subscribe methods take a `StompFrameHandler` for messages on the subscription
-and return a `Subscription` handle for unsubscribing. For each received message,
-the handler must help to select the target type and then handle the
-deserialized payload:
+You can also subscribe to destinations. The `subscribe` methods require a handler
+for messages on the subscription and return a `Subscription` handle that can be
+used to unsubscribe. For each received message the handler can specify the target
+Object type the payload should be deserialized to:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -1956,11 +1958,19 @@ session.subscribe("/topic/foo", new StompFrameHandler() {
});
----
-STOMP supports heartbeats. To use this feature simply configure the
-`WebSocketStompClient` with a `TaskScheduler` and if desired customize the
-default heartbeat intervals (10, 10 seconds respectively by default) for
-write inactivity which causes a heartbeat to be sent and for read
-inactivity which closes the connection.
+To enable STOMP heartbeat configure `WebSocketStompClient` with a `TaskScheduler`
+and optionally customize the heartbeat intervals, 10 seconds for write inactivity
+which causes a heartbeat to be sent and 10 seconds for read inactivity which
+closes the connection.
+
+[NOTE]
+====
+When using `WebSocketStompClient` for performance tests to simulate thousands
+of clients from the same machine consider turning off heartbeats since each
+connection schedules its own heartbeat tasks and that's not optimized for a
+a large number of clients running on the same machine.
+====
+
The STOMP protocol also supports receipts where the client must add a "receipt"
header to which the server responds with a RECEIPT frame after the send or
@@ -2000,7 +2010,7 @@ public class MyController {
}
----
-It is also possible to declare a Spring-managed bean in the `"websocket"` scope.
+It is also possible to declare a Spring-managed bean in the `websocket` scope.
WebSocket-scoped beans can be injected into controllers and any channel interceptors
registered on the "clientInboundChannel". Those are typically singletons and live
longer than any individual WebSocket session. Therefore you will need to use a
@@ -2010,7 +2020,7 @@ scope proxy mode for WebSocket-scoped beans:
[subs="verbatim,quotes"]
----
@Component
-@Scope(name = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
+@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyBean {
@PostConstruct
diff --git a/src/asciidoc/web.adoc b/src/asciidoc/web.adoc
index debdaa66..e6388258 100644
--- a/src/asciidoc/web.adoc
+++ b/src/asciidoc/web.adoc
@@ -9,7 +9,7 @@ for WebSocket-style messaging in web applications.
Spring Framework's own web framework, <<mvc,Spring Web MVC>>, is covered in the
first couple of chapters. Subsequent chapters are concerned with Spring Framework's
-integration with other web technologies, such as <<jsf,JSF>> and.
+integration with other web technologies, such as <<jsf,JSF>>.
Following that is coverage of Spring Framework's MVC <<portlet,portlet framework>>.
diff --git a/src/asciidoc/whats-new.adoc b/src/asciidoc/whats-new.adoc
index 5ad8910d..bb1cb1e5 100644
--- a/src/asciidoc/whats-new.adoc
+++ b/src/asciidoc/whats-new.adoc
@@ -276,7 +276,7 @@ Spring 4.1 also improves its own caching abstraction significantly:
common settings to be shared at the class level **without** enabling any cache operation.
* Better exception handling of cached methods using `CacheErrorHandler`
-Spring 4.1 also has a breaking change in the `CacheInterface` as a new `putIfAbsent`
+Spring 4.1 also has a breaking change in the `Cache` interface as a new `putIfAbsent`
method has been added.
=== Web Improvements
@@ -368,9 +368,9 @@ method has been added.
* Test property sources which automatically override system and application property
sources can be configured via the new `@TestPropertySource` annotation.
** See <<testcontext-ctx-management-property-sources>> for details.
-* Default ++TestExecutionListener++s can now be automatically discovered.
+* Default ``TestExecutionListener``s can now be automatically discovered.
** See <<testcontext-tel-config-automatic-discovery>> for details.
-* Custom ++TestExecutionListener++s can now be automatically merged with the default
+* Custom ``TestExecutionListener``s can now be automatically merged with the default
listeners.
** See <<testcontext-tel-config-merging>> for details.
* The documentation for transactional testing support in the TestContext framework has
@@ -597,13 +597,13 @@ public @interface MyTestConfig {
subsequent release.
* `@Sql` now supports execution of _inlined SQL statements_ via a new
`statements` attribute.
-* The `ContextCache` that is used for caching ++ApplicationContext++s
+* The `ContextCache` that is used for caching ``ApplicationContext``s
between tests is now a public API with a default implementation that
can be replaced for custom caching needs.
* `DefaultTestContext`, `DefaultBootstrapContext`, and
`DefaultCacheAwareContextLoaderDelegate` are now public classes in the
`support` subpackage, allowing for custom extensions.
-* ++TestContextBootstrapper++s are now responsible for building the
+* ``TestContextBootstrapper``s are now responsible for building the
`TestContext`.
* In the Spring MVC Test framework, `MvcResult` details can now be logged
at `DEBUG` level or written to a custom `OutputStream` or `Writer`. See
@@ -616,9 +616,125 @@ public @interface MyTestConfig {
definition profiles.
* Embedded databases can now be automatically assigned a unique name,
allowing common test database configuration to be reused in different
- ++ApplicationContext++s within a test suite.
+ ``ApplicationContext``s within a test suite.
** See <<jdbc-embedded-database-unique-names>> for details.
* `MockHttpServletRequest` and `MockHttpServletResponse` now provide better
support for date header formatting via the `getDateHeader` and `setDateHeader`
methods.
+
+
+[[new-in-4.3]]
+== New Features and Enhancements in Spring Framework 4.3
+
+=== Core Container Improvements
+
+* Core container exceptions provide richer metadata to evaluate programmatically.
+* Java 8 default methods get detected as bean property getters/setters.
+* It is no longer necessary to specify the `@Autowired` annotation if the target
+ bean only defines one constructor.
+* `@Configuration` classes support constructor injection.
+* Any SpEL expression used to specify the `condition` of an `@EventListener` can
+ now refer to beans (e.g. `@beanName.method()`).
+* _Composed annotations_ can now override array attributes in meta-annotations
+ with a single element of the component type of the array. For example, the
+ `String[] path` attribute of `@RequestMapping` can be overridden with
+ `String path` in a composed annotation.
+* `@Scheduled` and `@Schedules` may now be used as _meta-annotations_ to create
+ custom _composed annotations_ with attribute overrides.
+* `@Scheduled` is properly supported on beans of any scope.
+
+=== Data Access Improvements
+
+* `jdbc:initialize-database` and `jdbc:embedded-database` support a configurable
+ separator to be applied to each script.
+
+=== Caching Improvements
+
+Spring 4.3 allows concurrent calls on a given key to be synchronized so that the
+value is only computed once. This is an opt-in feature that should be enabled via
+the new `sync` attribute on `@Cacheable`. This features introduces a breaking
+change in the `Cache` interface as a `get(Object key, Callable<T> valueLoader)`
+method has been added.
+
+Spring 4.3 also improves the caching abstraction as follows:
+
+* SpEL expressions in caches-related annotations can now refer to beans (i.e.
+ `@beanName.method()`).
+* `ConcurrentMapCacheManager` and `ConcurrentMapCache` now support the serialization
+ of cache entries via a new `storeByValue` attribute.
+* `@Cacheable`, `@CacheEvict`, `@CachePut`, and `@Caching` may now be used as
+ _meta-annotations_ to create custom _composed annotations_ with attribute overrides.
+
+=== JMS Improvements
+
+* `@SendTo` can now be specified at the class level to share a common reply destination.
+* `@JmsListener` and `@JmsListeners` may now be used as _meta-annotations_ to create
+ custom _composed annotations_ with attribute overrides.
+
+=== Web Improvements
+
+* Built-in support for <<mvc-ann-requestmapping-head-options,HTTP HEAD and HTTP OPTIONS>>.
+* New `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, and `@PatchMapping`
+ _composed annotations_ for `@RequestMapping`.
+** See <<mvc-ann-requestmapping-composed,Composed @RequestMapping Variants>> for details.
+* New `@RequestScope`, `@SessionScope`, and `@ApplicationScope` _composed annotations_
+ for web scopes.
+** See <<beans-factory-scopes-request,Request scope>>,
+ <<beans-factory-scopes-session,Session scope>>, and
+ <<beans-factory-scopes-application,Application scope>> for details.
+* New `@RestControllerAdvice` annotation with combined `@ControllerAdvice` with `@ResponseBody` semantics.
+* `@ResponseStatus` is now supported at the class level and inherited by all methods.
+* New `@SessionAttribute` annotation for access to session attributes (see <<mvc-ann-sessionattrib-global, example>>).
+* New `@RequestAttribute` annotation for access to request attributes (see <<mvc-ann-requestattrib, example>>).
+* `@ModelAttribute` allows preventing data binding via `binding=false` attribute (see <<mvc-ann-modelattrib-method-args, reference>>).
+* Consistent exposure of Errors and custom Throwables to MVC exception handlers.
+* Consistent charset handling in HTTP message converters, including a UTF-8 default for multipart text content.
+* Static resource handling uses the configured `ContentNegotiationManager` for media type determination.
+* `RestTemplate` and `AsyncRestTemplate` support strict URI variable encoding via `DefaultUriTemplateHandler`.
+* `AsyncRestTemplate` supports request interception.
+
+=== WebSocket Messaging Improvements
+
+* `@SendTo` and `@SendToUser` can now be specified at class-level to share a common destination.
+
+=== Testing Improvements
+
+* The JUnit support in the _Spring TestContext Framework_ now requires JUnit 4.12 or higher.
+* New `SpringRunner` _alias_ for the `SpringJUnit4ClassRunner`.
+* Test related annotations may now be declared on interfaces -- for example, for use with
+ _test interfaces_ that make use of Java 8 based interface default methods.
+* An empty declaration of `@ContextConfiguration` can now be completely omitted if default
+ XML files, Groovy scripts, or `@Configuration` classes are detected.
+* `@Transactional` test methods are no longer required to be `public` (e.g., in TestNG and JUnit 5).
+* `@BeforeTransaction` and `@AfterTransaction` methods are no longer required to be `public`
+ and may now be declared on Java 8 based interface default methods.
+* The `ApplicationContext` cache in the _Spring TestContext Framework_ is now bounded with a
+ default maximum size of 32 and a _least recently used_ eviction policy. The maximum size
+ can be configured by setting a JVM system property or Spring property called
+ `spring.test.context.cache.maxSize`.
+* New `ContextCustomizer` API for customizing a test `ApplicationContext` _after_ bean
+ definitions have been loaded into the context but _before_ the context has been refreshed.
+ Customizers can be registered globally by third parties, foregoing the need to implement a
+ custom `ContextLoader`.
+* `@Sql` and `@SqlGroup` may now be used as _meta-annotations_ to create custom _composed
+ annotations_ with attribute overrides.
+* `ReflectionTestUtils` now automatically unwraps proxies when setting or getting a field.
+* Server-side Spring MVC Test supports expectations on response headers with multiple values.
+* Server-side Spring MVC Test parses form data request content and populates request parameters.
+* Server-side Spring MVC Test supports mock-like assertions for invoked handler methods.
+* Client-side REST test support allows indicating how many times a request is expected and
+ whether the order of declaration for expectations should be ignored (see <<spring-mvc-test-client>>).
+* Client-side REST Test supports expectations for form data in the request body.
+
+=== Support for new library and server generations
+
+* Hibernate ORM 5.2 (still supporting 4.2/4.3 and 5.0/5.1 as well, with 3.6 deprecated now)
+* Jackson 2.8 (minimum raised to Jackson 2.6+ as of Spring 4.3)
+* OkHttp 3.x (still supporting OkHttp 2.x side by side)
+* Netty 4.1
+* Undertow 1.4
+* Tomcat 8.5.2 as well as 9.0 M6
+
+Furthermore, Spring Framework 4.3 embeds the updated ASM 5.1 and Objenesis 2.4 in
+`spring-core.jar`.