When using the Spring TestContext Framework (TCF) to load a
WebApplicationContext and the Spring MVC Test Framework (MockMvc) to
test a controller, two instances of MockHttpServletRequest will be
created. Due to an ordering issue with regard to population of the
RequestAttributes, it is therefore possible that a filter accesses the
mocked request managed by the TCF, while the controller accesses the
mocked request managed by MockMvc, and this leads to test failures if
the controller expects data from the filter to be present in the
request.
This commit fixes this bug by ensuring that the RequestAttributes
backed by the mocked request managed by MockMvc are stored in the
RequestContextHolder before any filters are invoked by MockMvc.
Issue: SPR-13217
This commit adds additional tests to RequestContextHolderTests that
verify proper support for the MockHttpServletRequest managed by Spring
MVC Test in the following scenarios:
- request-scoped service invoked by controller
- session-scoped service invoked by controller
- custom filter that sets request attributes
Issue: SPR-13211
SPR-12429 introduced various `BEFORE_*` modes in `@DirtiesContext`. To
support these new modes, `DirtiesContextTestExecutionListener` (DCTEL)
was updated to support both `BEFORE_*` and `AFTER_*` modes. However,
there is a problem with having DCTEL support `BEFORE_*` modes since it
is typically configured to execute after the
`DependencyInjectionTestExecutionListener` (DITEL), and this leads to
several undesired side effects:
- The test's `ApplicationContext` is closed by DCTEL *after*
dependencies have been injected into the test instance.
- Injected dependencies may therefore attempt to interact with an
`ApplicationContext` that is no longer _active_.
- If a test has its `ApplicationContext` injected as a dependency,
interaction with the context will likely fail since the context has
been closed.
- Any `TestExecutionListeners` registered after DCTEL will get a _new_
`ApplicationContext` if they invoke `getApplicationContext()` on the
`TestContext`.
This commit fixes these issues by introducing a new
`DirtiesContextBeforeModesTestExecutionListener` (DCBMTEL) that is
registered by default before DITEL. The previous support for `BEFORE_*`
modes has been moved from DCTEL to DCBMTEL. In addition, an
`AbstractDirtiesContextTestExecutionListener` has been extracted from
DCTEL in order to avoid code duplication.
Issue: SPR-13180
Prior to this commit, the Spring MVC Test framework only provided
support for printing debug information about the MvcResult to STDOUT.
This commit introduces support for logging `MvcResult` details at
`DEBUG` level via the Apache Commons Logging API. In addition, this
commit introduces additional `print(..)` variants for printing debug
information to custom output streams and writers.
Specifically, `MockMvcResultHandlers` has been augmented with the
following new static methods:
- `log()`
- `print(OutputStream)`
- `print(Writer)`
Issue: SPR-13171
Prior to this commit, when rendering cookies via `andDo(print())` in
Spring MVC Test, the output for the `MockHttpServletResponse` would
look something like the following:
Cookies = [javax.servlet.http.Cookie@25084a1e]
The reason is that the Cookie class in javax.servlet-api-3.0.1.jar does
not implement toString(). Consequently, nothing about the cookie's
name, value, etc., is displayed, thereby making the debug output for
cookies next to useless.
This commit improves on this by implementing custom toString() logic
for cookies in debug output in Spring MVC Test. For example, the output
now looks like this (without the newlines):
Cookies = [[Cookie@47faa49c name = 'enigma', value = '42', \\
comment = [null], domain = [null], maxAge = -1, \\
path = [null], secure = false, version = 0, \\
httpOnly = false]]
In addition, this commit fixes a minor bug for FlashMap debug output if
the FlashMap is empty.
Issue: SPR-13168
Prior to this commit, it was only possible to declare SQL statements
via @Sql within external script resources (i.e., classpath or file
system resources); however, many developers have inquired about the
ability to inline SQL statements with @Sql analogous to the support for
inlined properties in @TestPropertySource.
This commit introduces support for declaring _inlined SQL statements_
in `@Sql` via a new `statements` attribute. Inlined statements are
executed after statements in scripts.
Issue: SPR-13159
This commit introduces a convenience method in AnnotationUtils for
synthesizing an annotation from its default attribute values.
TransactionalTestExecutionListener has been refactored to invoke this
new convenience method.
Issue: SPR-13087
Prior to this commit, the implementation of getRepeatableAnnotation()
in Spring's AnnotationUtils complied neither with the contract of
getAnnotationsByType() nor with the contract of
getDeclaredAnnotationsByType() as defined in AnnotatedElement in Java 8.
Specifically, unexpected results can be encountered when using Spring's
support for @Repeatable annotations: either annotations show up in the
returned set in the wrong order, or annotations are returned in the set
that should not even be found based on the semantics of @Repeatable.
This commit remedies this problem by deprecating the existing
getRepeatableAnnotation() methods and replacing them with new
getRepeatableAnnotations() and getDeclaredRepeatableAnnotations()
methods that comply with the contracts of Java's getAnnotationsByType()
and getDeclaredAnnotationsByType(), respectively.
Issue: SPR-13068
The initial support for synthesizing an annotation from a Map (or
AnnotationAttributes) introduced in SPR-13067 required that the map
contain key-value pairs for every attribute defined by the supplied
annotationType. However, there are use cases that would benefit from
being able to supply a reduced set of attributes and still have the
annotation synthesized properly.
This commit refines the validation mechanism in
MapAnnotationAttributeExtractor so that a reduced set of attributes may
be supplied. Specifically, if an attribute is missing in the supplied
map the attribute will be set either to value of its alias (if an alias
value configured via @AliasFor exists) or to the value of the
attribute's default value (if defined), and otherwise an exception will
be thrown.
Furthermore, TransactionalTestExecutionListener has been refactored to
take advantage of this new feature by synthesizing an instance of
@TransactionConfiguration solely from the default values of its
declared attributes.
Issue: SPR-13087
Prior to this change, `XpathResultMatchers` and more generally the
`MockHttpServletResponse` would default to ISO-8859-1 encoding even when
it's not supposed to. The Servlet/HTTP specs mention this encoding
for all `text/*` mime types when decoding bodies to Strings, but this
issue is about XML Parsers.
XML Parsers should use the encoding:
* defined in the `Content-Type` response header (if available)
* written in the XML declaration of the document
* "guessed" by a built-in auto-detection mechanism
This commit changes the following:
* XPathMatchers now feed the XML parser with byte arrays instead of
decoded Strings
* the response should be written to `MockHttpServletResponse` using
its OutputStream, and not a PrintWriter which defaults to ISO-8859-1
Issue: SPR-12676
Ever since @ActiveProfiles was introduced, the declared active profiles
for integration tests have been sorted in order to support unique cache
key generation; however, there are use cases for which the original
ordering should be retained.
For example, Spring Boot's ConfigFileApplicationListener loads
configuration files for active profiles in the order returned by
Environment.getActiveProfiles(), with the assumption that the ordering
matches the order in which the developer declared the active profiles.
This commit maintains the uniqueness of active profiles declared via
@ActiveProfiles but no longer sorts them.
Issue: SPR-12492
In AnnotatedElementUtils, all methods pertaining to merging annotation
attributes have been renamed to "getMerged*()" and "findMerged*()"
accordingly. Existing methods such as getAnnotationAttributes(..) have
been deprecated in favor of the more descriptive "merged" variants.
This aligns the naming conventions in AnnotatedElementUtils with those
already present in AnnotationReadingVisitorUtils.
The use of "annotationType" as a variable name for the fully qualified
class name of an annotation type has been replaced with
"annotationName" in order to improve the readability and intent of the
code base.
In MetaAnnotationUtils.AnnotationDescriptor, getMergedAnnotation() has
been renamed to synthesizeAnnotation(), and the method is now
overridden in UntypedAnnotationDescriptor to always throw an
UnsupportedOperationException in order to avoid potential run-time
ClassCastExceptions.
Issue: SPR-11511
The modifications to DefaultMockMvcBuilder performed in conjunction
with SPR-12553 introduced a breaking change: the WebApplicationContext
supplied to DefaultMockMvcBuilder's constructor was *always* stored in
the ServletContext as the root WebApplicationContext, overwriting a
root WebApplicationContext that had been set by the user or by the
Spring TestContext Framework (TCF) -- for example, in
AbstractGenericWebContextLoader. Consequently, the changes in SPR-12553
cause tests that use @ContextHierarchy to fail if web components rely
on the correct WebApplicationContext being stored under the
WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key.
This commit reverts the breaking changes introduced in SPR-12553: if
the root WebApplicationContext has already been set in the
ServletContext of the WebApplicationContext supplied to
DefaultMockMvcBuilder, no action is taken.
Furthermore, this commit introduces new code to address the initial
intent of SPR-12553. Specifically, if the root WebApplicationContext
has NOT been set in the ServletContext of the WebApplicationContext
supplied to DefaultMockMvcBuilder, the application context hierarchy
will be traversed in search of the root WebApplicationContext, and the
root WebApplicationContext will then be stored under the
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key.
Issue: SPR-13075, SPR-12553
Spring Framework 4.2 RC1 introduced support for synthesizing an
annotation from an existing annotation in order to provide additional
functionality above and beyond that provided by Java. Specifically,
such synthesized annotations provide support for @AliasFor semantics.
As luck would have it, the same principle can be used to synthesize an
annotation from any map of attributes, and in particular, from an
instance of AnnotationAttributes.
The following highlight the major changes in this commit toward
achieving this goal.
- Introduced AnnotationAttributeExtractor abstraction and refactored
SynthesizedAnnotationInvocationHandler to delegate to an
AnnotationAttributeExtractor.
- Extracted code from SynthesizedAnnotationInvocationHandler into new
AbstractAliasAwareAnnotationAttributeExtractor and
DefaultAnnotationAttributeExtractor implementation classes.
- Introduced MapAnnotationAttributeExtractor for synthesizing an
annotation that is backed by a map or AnnotationAttributes instance.
- Introduced a variant of synthesizeAnnotation() in AnnotationUtils
that accepts a map.
- Introduced findAnnotation(*) methods in AnnotatedElementUtils that
synthesize merged AnnotationAttributes back into an annotation of the
target type.
The following classes have been refactored to use the new support for
synthesizing AnnotationAttributes back into an annotation.
- ApplicationListenerMethodAdapter
- TestAnnotationUtils
- AbstractTestContextBootstrapper
- ActiveProfilesUtils
- ContextLoaderUtils
- DefaultActiveProfilesResolver
- DirtiesContextTestExecutionListener
- TestPropertySourceAttributes
- TestPropertySourceUtils
- TransactionalTestExecutionListener
- MetaAnnotationUtils
- MvcUriComponentsBuilder
- RequestMappingHandlerMapping
In addition, this commit also includes changes to ensure that arrays
returned by synthesized annotations are properly cloned first.
Issue: SPR-13067
This commit introduces first-class support for aliases for annotation
attributes. Specifically, this commit introduces a new @AliasFor
annotation that can be used to declare a pair of aliased attributes
within a single annotation or an alias from an attribute in a custom
composed annotation to an attribute in a meta-annotation.
To support @AliasFor within annotation instances, AnnotationUtils has
been overhauled to "synthesize" any annotations returned by "get" and
"find" searches. A SynthesizedAnnotation is an annotation that is
wrapped in a JDK dynamic proxy which provides run-time support for
@AliasFor semantics. SynthesizedAnnotationInvocationHandler is the
actual handler behind the proxy.
In addition, the contract for @AliasFor is fully validated, and an
AnnotationConfigurationException is thrown in case invalid
configuration is detected.
For example, @ContextConfiguration from the spring-test module is now
declared as follows:
public @interface ContextConfiguration {
@AliasFor(attribute = "locations")
String[] value() default {};
@AliasFor(attribute = "value")
String[] locations() default {};
// ...
}
The following annotations and their related support classes have been
modified to use @AliasFor.
- @ManagedResource
- @ContextConfiguration
- @ActiveProfiles
- @TestExecutionListeners
- @TestPropertySource
- @Sql
- @ControllerAdvice
- @RequestMapping
Similarly, support for AnnotationAttributes has been reworked to
support @AliasFor as well. This allows for fine-grained control over
exactly which attributes are overridden within an annotation hierarchy.
In fact, it is now possible to declare an alias for the 'value'
attribute of a meta-annotation.
For example, given the revised declaration of @ContextConfiguration
above, one can now develop a composed annotation with a custom
attribute override as follows.
@ContextConfiguration
public @interface MyTestConfig {
@AliasFor(
annotation = ContextConfiguration.class,
attribute = "locations"
)
String[] xmlFiles();
// ...
}
Consequently, the following are functionally equivalent.
- @MyTestConfig(xmlFiles = "test.xml")
- @ContextConfiguration("test.xml")
- @ContextConfiguration(locations = "test.xml").
Issue: SPR-11512, SPR-11513
In order to simplify configuration of the SpringMethodRule and to ensure
that the correct TestContextManager is always retrieved for the
currently executing test class, this commit introduces a static
TestContextManager cache in SpringClassRule.
In addition, since it is not foreseen that SpringClassRule and
SpringMethodRule should be able to be subclassed, their internal methods
are now private instead of protected.
Issue: SPR-7731
Since Spring Framework 2.5, support for integrating the Spring
TestContext Framework (TCF) into JUnit 4 based tests has been provided
via the SpringJUnit4ClassRunner, but this approach precludes the
ability for tests to be run with alternative runners like JUnit's
Parameterized or third-party runners such as the MockitoJUnitRunner.
This commit remedies this situation by introducing @ClassRule and @Rule
based alternatives to the SpringJUnit4ClassRunner. These rules are
independent of any Runner and can therefore be combined with
alternative runners.
Due to the limitations of JUnit's implementation of rules, as of JUnit
4.12 it is currently impossible to create a single rule that can be
applied both at the class level and at the method level (with access to
the test instance). Consequently, this commit introduces the following
two rules that must be used together.
- SpringClassRule: a JUnit TestRule that provides the class-level
functionality of the TCF to JUnit-based tests
- SpringMethodRule: a JUnit MethodRule that provides the
instance-level and method-level functionality of the TCF to
JUnit-based tests
In addition, this commit also introduces the following new JUnit
Statements for use with rules:
- RunPrepareTestInstanceCallbacks
- ProfileValueChecker
Issue: SPR-7731
This commit updates code that previously used getAnnotationAttributes()
in AnnotatedElementUtils to use findAnnotationAttributes(), where
appropriate.
Issue: SPR-12738
This commit introduces support in the spring-test module for obtaining a
reference to the underlying target object hidden behind one or more
proxies.
Specifically this commit introduces AopTestUtils with two methods:
- getTargetObject(Object)
- getUltimateTargetObject(Object)
Issue: SPR-13005
Prior to this commit it was possible for two @BootstrapWith annotations
to be 'present' on a test class -- for example, via competing custom
composed annotations. However, only one of the annotations will ever be
used to bootstrap the TestContext Framework. Thus, in such scenarios
one of the annotations will be silently ignored.
This commit introduces a check for such scenarios. BootstrapUtils'
resolveTestContextBootstrapper() method now throws an
IllegalStateException if more than one @BootstrapWith annotation is
'present' on a given test class.
Issue: SPR-12602
Previously MockHttpServletRequestBuilder merge method would append the
parent's (default) RequestPostProcessor implementations to the end. This
means that the default RequestPostProcessor implementations would override
values set by previous RequestPostProcessor implementations.
This commit ensures that the default RequestPostProcessor are preformed
first so that additional RequestPostProcessor implementations override
the defaults.
Issue: SPR-12945
This commit introduces support for finding annotations on abstract,
bridge, and interface methods in AnnotatedElementUtils.
- Introduced dedicated findAnnotationAttributes() methods in
AnnotatedElementUtils that provide first-class support for
processing methods, class hierarchies, interfaces, bridge methods,
etc.
- Introduced find/get search algorithm dichotomy in
AnnotatedElementUtils which is visible in the public API as well as
in the internal implementation. This was necessary in order to
maintain backwards compatibility with the existing API (even though
it was undocumented).
- Reverted all recent changes made to the "get semantics" search
algorithm in AnnotatedElementUtils in order to ensure backwards
compatibility, and reverted recent changes to
JtaTransactionAnnotationParser and SpringTransactionAnnotationParser
accordingly.
- Documented internal AnnotatedElementUtils.Processor<T> interface.
- Enabled failing tests and introduced
findAnnotationAttributesFromBridgeMethod() test in
AnnotatedElementUtilsTests.
- Refactored ApplicationListenerMethodAdapter.getCondition() and
enabled failing test in TransactionalEventListenerTests.
- AnnotationUtils.isInterfaceWithAnnotatedMethods() is now package
private.
Issue: SPR-12738, SPR-11514, SPR-11598
Prior to this commit, AnnotationAttributes retrieved from
MetaAnnotationUtils's AnnotationDescriptor could contain attributes
from the wrong annotation if an inherited annotation shadowed a locally
declared composed annotation.
This commit addresses this issue by invoking the new
getAnnotationAttributes() method in AnnotatedElementUtils that provides
a flag to control whether superclasses should be searched -- which
coincidentally processes local annotations before searching the class
hierarchy.
Issue: SPR-12749, SPR-11598
Since the ContextCache is now a published SPI, it and its collaborators
have been moved to a dedicated 'org.sfw.test.context.cache' subpackage.
Issue: SPR-12683
This commit adds an assertion to DefaultTestContext's
getApplicationContext() method to ensure that a context loaded by the
Spring TestContext Framework (TCF) or retrieved from the ContextCache
is still active. This extra check helps to avoid situations where
developers manually close a cached context instead of relying on the
@DirtiesContext support.
Issue: SPR-12932
The changes made in 0cb22fc8f3 would
result in contexts not being properly closed if evicted from the
ConcurrentReferenceHashMap by the Garbage Collector.
This commit reverts those changes and returns to using standard
ConcurrentHashMaps for the time being.
Issue: SPR-7687
- DefaultBootstrapContext and DefaultCacheAwareContextLoaderDelegate
are now public classes in the 'support' subpackage.
- Introduced getCacheAwareContextLoaderDelegate() in
AbstractTestContextBootstrapper as an extension point for configuring
custom ContextCache support.
- Introduced reflection-based createBootstrapContext() utility method
in BootstrapUtils; TestContextManager now delegates to BootstrapUtils
in order to avoid package cycles.
- Introduced logStatistics() method in the ContextCache API and defined
statistics logging category as a constant.
- DefaultCacheAwareContextLoaderDelegate now delegates to
ContextCache.logStatistics().
Issue: SPR-12683
This commit moves the responsibility of building a TestContext from the
TestContextManager to a TestContextBootstrapper.
In addition, DefaultTestContext is now a public class residing in the
"support" subpackage.
Issue: SPR-12683
Prior to this commit, the ContextCache in the Spring TestContext
Framework (TCF) cached ApplicationContexts in a ConcurrentHashMap using
strong references. This practice can occasionally lead to
OutOfMemoryErrors when running a large number of tests in a test suite
with varying context configuration since the context cache becomes
overpopulated over time.
This commit addresses this issue by using Spring's
ConcurrentReferenceHashMap which uses SoftReferences for both the keys
(i.e., MergedContextConfiguration instances) and values (i.e.,
ApplicationContexts) stored in the map that backs the ContextCache.
Issue: SPR-7687
Prior to this commit, ClassLevelDirtiesContextTests existed for
verifying the expected behavior of @DirtiesContext declared at the
class level in conjunction with JUnit and SpringJUnit4ClassRunner.
This commit introduces analogous tests for TestNG in the new
ClassLevelDirtiesContextTestNGTests class.
Furthermore, ContextCacheTestUtils and TrackingTestNGTestListener have
been introduced to reduce code duplication across the test suite.
Issue: SPR-12918
This commit increases the extensibility of
AbstractTestContextBootstrapper by making the resolveContextLoader()
and resolveExplicitContextLoaderClass() methods protected instead of
private.
Furthermore, resolveContextLoader() now throws an IllegalStateException
if getDefaultContextLoaderClass() returns null.
Issue: SPR-12682
Prior to this commit it was possible to set or get a static field using
ReflectionTestUtils but only if an instance of the target class was
available.
This commit introduces dedicated support for setting and getting static
fields in ReflectionTestUtils when only the target class is available.
Furthermore, this commit increases the robustness of
ReflectionTestUtilsTests regarding expected exceptions and simplifies
the Javadoc for ReflectionTestUtils.
Issue: SPR-6792
Since SPR-11792, Last-Modified and ETag headers are also written in
`HTTP 304 Not Modified` responses. This is expected as per
https://tools.ietf.org/html/rfc7232#section-4.1 .
Those tests expected "Last-Modified" to be missing in case of HTTP 304
responses, which is not the case anymore since 953608ec .
Issue: SPR-11792
Prior to this commit, @DirtiesContext could only be used to close a
test ApplicationContext after an entire test class or after a test
method; however, there are some use cases for which it would be
beneficial to close a test ApplicationContext before a given test class
or test method -- for example, if some rogue (i.e., yet to be
determined) test within a large test suite has corrupted the original
configuration for the ApplicationContext.
This commit provides a solution to such testing challenges by
introducing the following modes for @DirtiesContext.
- MethodMode.BEFORE_METHOD: configured via the new methodMode attribute
- ClassMode.BEFORE_CLASS and ClassMode.BEFORE_EACH_TEST_METHOD: both
configured via the existing classMode attribute
Issue: SPR-12429
This commit updates the Spr8849Tests test suite to include XML
configuration that guarantees that a unique database name is always
automatically generated (via the new 'generate-name' attribute that was
introduced in SPR-8849) while reusing the same bean name (i.e.,
'dataSource').
Issue: SPR-8849
This commit refactors the XML configuration used by the tests in the
Spr8849Tests test suite so that a unique database name is always
generated (via the new 'database-name' attribute that was introduced in
SPR-12835) while reusing the same bean name (i.e., 'dataSource').
This is a much more robust alternative to the previous work-around
since the name of the DataSource does not randomly change across
application contexts, thus allowing proper autowiring by name and bean
referencing within XML configuration.
Issue: SPR-8849
This commit simplifies the implementations of loadBeanDefinitions() in
GenericGroovyXmlContextLoader and GenericGroovyXmlWebContextLoader.
Due to the recent bug fix for GroovyBeanDefinitionReader regarding full
support for XML config files, these Groovy context loaders can now
simply use a GroovyBeanDefinitionReader instead of a
GroovyBeanDefinitionReader plus an XmlBeanDefinitionReader.
Issue: SPR-12769
Prior to this commit, it was impossible to use all features of XML
configuration (e.g., the <qualifier> tag) in web-based integration
tests (loaded using @WebAppConfiguration, @ContextConfiguration, etc.)
if the Groovy library was on the classpath. The reason is that the
GroovyBeanDefinitionReader used internally by
GenericGroovyXmlWebContextLoader disables XML validation for its
internal XmlBeanDefinitionReader, and this prevents some XML
configuration features from working properly. For example, the default
value for the 'type' attribute (defined in the spring-beans XSD) of the
<qualifier> tag gets ignored, resulting in an exception when the
application context is loaded.
This commit addresses this issue by refactoring the implementation of
loadBeanDefinitions() in GenericGroovyXmlWebContextLoader to use an
XmlBeanDefinitionReader or GroovyBeanDefinitionReader depending on the
file extension of the resource location from which bean definitions
should be loaded. This aligns the functionality of
GenericGroovyXmlWebContextLoader with the existing functionality of
GenericGroovyXmlContextLoader.
Issue: SPR-12768
- Added assertions for pre-conditions on method arguments for all
public utility methods.
- Introduced additional tests in TestPropertySourceUtilsTests to verify
the new pre-conditions.
- Introduced INLINED_PROPERTIES_PROPERTY_SOURCE_NAME constant for the
name of the MapPropertySource created from inlined properties; the
name therefore no longer contains the inlined properties, but the
original values of the inlined properties can now be logged at debug
level.
- Simplified tests in InlinedPropertiesTestPropertySourceTests.
Issue: SPR-12721
Spring Framework 4.1 introduced support for @TestPropertySource;
however, the utilities used to parse inlined properties and add test
property sources to the environment are currently private which
prevents reuse by third-party frameworks like Spring Boot.
This commit addresses this issue by making such utilities public.
- TestPropertySourceUtils is now a public class.
- Various utility methods in TestPropertySourceUtils have been made
public.
- addResourcePropertySourcesToEnvironment() has been renamed to
addPropertiesFilesToEnvironment().
- extractEnvironmentProperties() has been renamed to
convertInlinedPropertiesToMap().
- All public methods in TestPropertySourceUtils are now fully
documented.
Issue: SPR-12721
The initial implementation for adding inlined properties configured via
@TestPropertySource to the context's environment did not preserve the
order in which the properties were physically declared. This makes
@TestPropertySource a poor testing facility for mimicking the
production environment's configuration if the property source mechanism
used in production preserves ordering of property names -- which is the
case for YAML-based property sources used in Spring Boot, Spring Yarn,
etc.
This commit addresses this issue by ensuring that the ordering of
inlined properties declared via @TestPropertySource is preserved.
Specifically, the original functionality has been refactored. extracted
from AbstractContextLoader, and moved to TestPropertySourceUtils where
it may later be made public for general purpose use in other frameworks.
Issue: SPR-12710
This commit introduces further regression tests to ensure proper parsing
of inlined properties configured via @TestPropertySource. Specifically,
these additional tests ensure that we do not introduce a bug like the
one raised in Spring Boot issue #1110 [0].
[0] https://github.com/spring-projects/spring-boot/issues/1110
Issue: SPR-12710
Add support for annotation-based event listeners. Enabled automatically
when using Java configuration or can be enabled explicitly via the
regular <context:annotation-driven/> XML element. Detect methods of
managed beans annotated with @EventListener, either directly or through
a meta-annotation.
Annotated methods must define the event type they listen to as a single
parameter argument. Events are automatically filtered out according to
the method signature. When additional runtime filtering is required, one
can specify the `condition` attribute of the annotation that defines a
SpEL expression that should match to actually invoke the method for a
particular event. The root context exposes the actual `event`
(`#root.event`) and method arguments (`#root.args`). Individual method
arguments are also exposed via either the `a` or `p` alias (`#a0` refers
to the first method argument). Finally, methods arguments are exposed via
their names if that information can be discovered.
Events can be either an ApplicationEvent or any arbitrary payload. Such
payload is wrapped automatically in a PayloadApplicationEvent and managed
explicitly internally. As a result, users can now publish and listen
for arbitrary objects.
If an annotated method has a return value, an non null result is actually
published as a new event, something like:
@EventListener
public FooEvent handle(BarEvent event) { ... }
Events can be handled in an aynchronous manner by adding `@Async` to the
event method declaration and enabling such infrastructure. Events can
also be ordered by adding an `@Order` annotation to the event method.
Issue: SPR-11622
Spring Framework 4.0 introduced support for using test-related
annotations as meta-annotations in the Spring TestContext Framework
(TCF) in order to create custom composed annotations within a test
suite; however, the detection of default @Configuration classes in test
classes was not updated to search for @Configuration declared as a
meta-annotation. Specifically, AnnotationConfigContextLoaderUtils
invokes Class.isAnnotated() which only searches for annotations
declared directly on the class in question.
This commit addresses this issue by refactoring the
isDefaultConfigurationClassCandidate() method in
AnnotationConfigContextLoaderUtils so that it uses
AnnotationUtils.findAnnotation() instead of Class.isAnnotated() for
detecting the presence of the @Configuration annotation, either
directly or as a meta-annotation.
Issue: SPR-12659
Various parts of the reference manual as well as the Javadoc for
AnnotationConfigContextLoaderUtils improperly refer to "static inner
classes" even though this terminology does not exist in Java. The Java
Language Specification explicitly refers to such classes as "static
nested classes." An "inner class" must be non-static by definition.
In order to allow DefaultActiveProfilesResolver to be reused (e.g., via
extension or delegation), the check which asserts that the 'resolver'
attribute of @ActiveProfiles is not set to a customer resolver class
has been removed.
Issue: SPR-12611