Prior to this change, Spring's @Async annotation support was tied to a
single AsyncTaskExecutor bean, meaning that all methods marked with
@Async were forced to use the same executor. This is an undesirable
limitation, given that certain methods may have different priorities,
etc. This leads to the need to (optionally) qualify which executor
should handle each method.
This is similar to the way that Spring's @Transactional annotation was
originally tied to a single PlatformTransactionManager, but in Spring
3.0 was enhanced to allow for a qualifier via the #value attribute, e.g.
@Transactional(ptm1)
public void m() { ... }
where ptm1 is either the name of a PlatformTransactionManager bean or
a qualifier value associated with a PlatformTransactionManager bean,
e.g. via the <qualifier> element in XML or the @Qualifier annotation.
This commit introduces the same approach to @Async and its relationship
to underlying executor beans. As always, the following syntax remains
supported
@Async
public void m() { ... }
indicating that calls to #m will be delegated to the default executor,
i.e. the executor provided to
<task:annotation-driven executor=.../>
or the executor specified when authoring a @Configuration class that
implements AsyncConfigurer and its #getAsyncExecutor method.
However, it now also possible to qualify which executor should be used
on a method-by-method basis, e.g.
@Async(e1)
public void m() { ... }
indicating that calls to #m will be delegated to the executor bean
named or otherwise qualified as e1. Unlike the default executor
which is specified up front at configuration time as described above,
the e1 executor bean is looked up within the container on the first
execution of #m and then cached in association with that method for the
lifetime of the container.
Class-level use of Async#value behaves as expected, indicating that all
methods within the annotated class should be executed with the named
executor. In the case of both method- and class-level annotations, any
method-level #value overrides any class level #value.
This commit introduces the following major changes:
- Add @Async#value attribute for executor qualification
- Introduce AsyncExecutionAspectSupport as a common base class for
both MethodInterceptor- and AspectJ-based async aspects. This base
class provides common structure for specifying the default executor
(#setExecutor) as well as logic for determining (and caching) which
executor should execute a given method (#determineAsyncExecutor) and
an abstract method to allow subclasses to provide specific strategies
for executor qualification (#getExecutorQualifier).
- Introduce AnnotationAsyncExecutionInterceptor as a specialization of
the existing AsyncExecutionInterceptor to allow for introspection of
the @Async annotation and its #value attribute for a given method.
Note that this new subclass was necessary for packaging reasons -
the original AsyncExecutionInterceptor lives in
org.springframework.aop and therefore does not have visibility to
the @Async annotation in org.springframework.scheduling.annotation.
This new subclass replaces usage of AsyncExecutionInterceptor
throughout the framework, though the latter remains usable and
undeprecated for compatibility with any existing third-party
extensions.
- Add documentation to spring-task-3.2.xsd and reference manual
explaining @Async executor qualification
- Add tests covering all new functionality
Note that the public API of all affected components remains backward-
compatible.
Issue: SPR-9443
Backport-Issue: SPR-6847
Backport-Commit: ed0576c181
In anticipation of substantive changes required to implement @Async
executor qualification, the following updates have been made to the
components and infrastructure supporting @Async functionality:
- Fix trailing whitespace and indentation errors
- Fix generics warnings
- Add Javadoc where missing, update to use {@code} tags, etc.
- Avoid NPE in AopUtils#canApply
- Organize imports to follow conventions
- Remove System.out.println statements from tests
- Correct various punctuation and grammar problems
Issue: SPR-9443
Backport-Issue: SPR-6847
Backport-Commit: 3fb11870d9
TransactionAspectUtils contains a number of methods useful in
retrieving a bean by type+qualifier. These methods are functionally
general-purpose save for the hard coding of PlatformTransactionManager
class literals throughout.
This commit generifies these methods and moves them into
BeanFactoryUtils primarily in anticipation of their use by async method
execution interceptors and aspects when performing lookups for qualified
executor beans e.g. via @Async(qualifier).
The public API of TransactionAspectUtils remains backward compatible;
all methods within have been deprecated, and all calls to those methods
throughout the framework refactored to use the new BeanFactoryUtils
variants instead.
Issue: SPR-9443
Backport-Issue: SPR-6847
Backport-Commit: 096693c46f
Previously, DatabasePopulatorUtils#execute looked up a Connection from
the given DataSource directly which resulted in the executed statements
not being executed against a transactional connection (if any) which in
turn resulted in the statements executed by the populator potentially
not being rolled back.
Now DataSourceUtils#getConnection is used to transparently take part in
any active transaction and #releaseConnection is used to ensure the
connection is closed if appropriate.
Issue: SPR-9465
Backport-Issue: SPR-9457
Backport-Commit: 49c9a2a915
@EnableSpringConfigured and its @Import'ed
SpringConfiguredConfiguration @Configuration class inadvertently
established a package cycle between beans.factory.aspectj and
context.annotation due to SpringConfiguredConfiguration's
dependency on annotations such as @Configuration, @Bean and @Role.
This commit fixes this architecture bug by moving
@EnableSpringConfigured and SpringConfiguredConfiguration from the
beans.factory.aspectj package to the context.annotation package where
they belong.
This change is assumed to be very low impact as @EnableSpringConfigured
was introduced in 3.1.0 and relocation is happening as quickly as
possible in 3.1.2. @EnableSpringConfigured is assumed to be infrequently
used at this point, and for those that are the migration path
is straightforward. When upgrading from Spring 3.1.0 or 3.1.1, update
import statements in any affected @Configuration classes to reflect the
new packaging.
Backporter's note: this change causes Bundlor warnings in
org.springframework.aspect as its manifest now "imports and exports the
package org.springframework.context.annotation". To 'solve' this
problem, `fail.on.warnings=false` has been added to build.properties.
This means that future Bundlor-based warnings may go unnoticed.
Issue: SPR-9442
Backport-Issue: SPR-9441
Backport-Commit: 5327a7a37d
Changes introduced in Spring 3.1 for Environment support inadvertently
established a cyclic dependency between the
org.springframework.web.context and
org.springframework.web.context.support packages, specifically through
web.context.ContextLoader's invocation of
web.context.support.WebApplicationContextUtils#initServletPropertySources.
This commit introduces ConfigurableWebEnvironment to break this cyclic
dependency. All web.context.ConfigurableWebApplicationContext types now
return web.context.ConfigurableWebEnvironment from their #getEnvironment
methods; web.context.support.StandardServletEnvironment now implements
ConfigurableWebEnvironment and makes the call to
web.context.support.WebApplicationContextUtils#initServletPropertySources
within its implementation of #initPropertySources. This means that
web.context.ContextLoader now invokes
web.context.ConfigurableWebEnvironment#initPropertySources instead of
web.context.support.WebApplicationContextUtils#initServletPropertySources
and thus the cycle is broken.
Issue: SPR-9440
Backport-Issue: SPR-9439
Backport-Commit: 2a2b6eef91
Prior to this change, AbstractApplicationContext#setParent replaced the
child context's Environment with the parent's Environment if available.
This has the negative effect of potentially changing the type of the
child context's Environment, and in any case causes property sources
added directly against the child environment to be ignored. This
situation could easily occur if a WebApplicationContext child had a
non-web ApplicationContext set as its parent. In this case the parent
Environment type would (likely) be StandardEnvironment, while the child
Environment type would (likely) be StandardServletEnvironment. By
directly inheriting the parent environment, critical property sources
such as ServletContextPropertySource are lost entirely.
This commit introduces the concept of merging an environment through
the new ConfigurableEnvironment#merge method. Instead of replacing the
child's environment with the parent's,
AbstractApplicationContext#setParent now merges property sources as
well as active and default profile names from the parent into the
child. In this way, distinct environment objects are maintained with
specific types and property sources preserved. See #merge Javadoc for
additional details.
Issue: SPR-9446
Backport-Issue: SPR-9444, SPR-9439
Backport-Commit: 9fcfd7e827
Previously (since Spring 3.1.1) RecursiveAnnotationAttributesVisitor
logs at level WARN when ASM parsing encounters an annotation or an (enum
used within an annotation) that cannot be classloaded. This is not
necessarily indicative of an error, e.g. JSR-305 annotations such as
@Nonnull may be used only for static analysis purposes, but because
these annotations have runtime retention, they remain present in the
bytecode. Per section 9.6.1.2 of the JLS, "An annotation that is present
in the binary may or may not be available at run-time via the reflective
libraries of the Java platform."
This commit lowers the log level of these messages from warn to debug,
but leaves at warn level other messages dealing with the ability
reflectively read enum values from within annotations.
Issue: SPR-9447
Backport-Issue: SPR-9233
Backport-Commit: f55a4a1ac5
The fromUri method of UriComponentsBuilder used uri.getXxx() methods,
which decode the URI parts causing URI parsing issues. The same method
now uses uri.getRawXxx().
Issue: SPR-9317
Backport-Issue: SPR-9549
Backport-Commit: a33fe6fa0a
HttpStatus cannot be created with an unknown status code. If a server
returns a status code that's not in the HttpStatus enum values, an
IllegalArgumentException is raised. Rather than allowing it to
propagate as such, this change ensures the actual exception raised is
a RestClientException.
Issue: SPR-9406
Backport-Issue: SPR-9502
As of Spring 3.1 URI variables can be used for data binding purposes in
addition to request parameters (including query string and form params)
In some cases URI variables and request params can overlap (e.g. form
contains a child entity with an entityId as hidden form input while the
URI contains the entityId of the parent entity) and that can lead to
surprises if the application already exists.
This change ensures that request parameters are used first and URI
vars are added only if they don't overlap. Ideally however an
application should not use the same uri variable name as the name of
a request parameter where they don't refer to the same value.
Issue: SPR-9349
Backport-Issue: SPR-9432
Backport-Commit: 4027b38903
Before this fix the q-value of media types in the Accept header were
ignored when using the new RequestMappingHandlerAdapter in combination
with @ResponseBody and HttpMessageConverters.
Issue: SPR-9160
Backport-Issue: SPR-9168
Backport-Commit: 982cb2f258
The MappingJacksonHttpMessageConverter now catches all IOException
types raised while reading JSON and translates them into
HttpMessageNotReadableException.
Issue: SPR-9238
Backport-Issue: SPR-9397
Backport-Commit: 816c1f47a4
Jackson 2 uses completely new package names and new maven artifact ids.
This change adds Jackson 2 as an optional dependency and also provides
MappingJackson2HttpMessageConverter and MappingJackson2JsonView for use
with the new version.
The MVC namespace and the MVC Java config detect and use
MappingJackson2HttpMessageConverter if Jackson 2 is present.
Otherwise if Jackson 1.x is present,
then MappingJacksonHttpMessageConverter is used.
Issue: SPR-9302
Backport-Issue: SPR-9507
Backport-Commit: e63ca04fdb
This was supported in DefaultAnnotationHandlerMapping but not in the
RequestMappingHandlerMapping. The specific scenario where this matters
is a controller decorated with a JDK proxy. In this scenario the
HandlerMapping looks at interfaces only to decide if the bean is a
controller. The @Controller annotation is better left (and required)
on the class.
Issue: SPR-9374
Backport-Issue: SPR-9384
Backport-Commit: f61f4a960e
Invalid Content-Type or Accept header values previously resulted in the
IllegalArgumentException getting propagated. After this change such
errors are detected and generally treated as a "no match", which
may for example result in a 406 in the case of the Accept header.
Issue: SPR-9142
Backport-Issue: SPR-9148
Backport-Commit: ca8b98e947
A custom RequestCondition which can be provided by overriding methods
in RequestMappingHandlerMapping worked only for conditions that match
and did not return null (as it should have) for conditions that don't
match.
Issue: SPR-9134
Backport-Issue: SPR-9146
Backport-Commit: 64ee5e579a
Add missing id attributes to <section> elements in the reference
documentation to ensure stable anchor links in HTML output.
Issue: SPR-9410
Backport-Issue: SPR-9346
Backport-Commit: 2a75c57d3c
It is now advised that destroyMethod="shutdown" should be used
on @Bean methods returning an ExecutorService.
Backport-Issue: SPR-9280
Backport-Commit: 6da03a61b22696283c2c5c79f8f88b5c36480560
The contents of this file could be problematic as they were generated
by spring-build with "org.springframework.core.jar" EBR-style naming,
but this naming is incorrect when dealing with Maven-central style
artifacts, e.g. spring-core.jar.
While a well-formed INDEX.LIST may speed up classloading, the simplest
solution to the issues listed below is simply to eliminate the file.
This also means consistent treatment across 3.1.x and 3.2.x artifacts,
as the new Gradle build in 3.2.x does not create these index files.
Issue: SPR-6383, SPR-9208
Prior to this commit, MutablePropertySources#get(String) would throw
IndexArrayOutOfBoundsException if the named property source does not
actually exist. This is a violation of the PropertySource#get contract
as described in its Javadoc.
The implementation now correctly checks for the existence of the named
property source, returning null if non-existent and otherwise returning
the associated PropertySource.
Other changes
- Rename PropertySourcesTests => MutablePropertySourcesTests
- Polish MutablePropertySourcesTests for style, formatting
- Refactor MutablePropertySources for consistency
Issue: SPR-9185
Backport-Issue: SPR-9179
Backport-Commit: 15d1d824b5
Due to changes made in commit 2fa87a71 for SPR-9118,
AbstractResource#contentLength would fall into an infinite loop unless
the method were overridden by a subclass (which it is in the majority of
use cases).
This commit:
- fixes the infinite recursion by refactoring to a while loop
- asserts that the value returned from #getInputStream is not null in
order to avoid NullPointerException
- tests both of the above
- adds Javadoc to the Resource interface to clearly document that the
contract for any implementation is that #getInputStream must not
return null
Issue: SPR-9163
Backport-Issue: SPR-9161
Backport-Commit: 7ca5fba05f
Changes in commit 41ade68b50 introduced
a regression causing all but the first location in the
@PropertySource#value array to be ignored during ${...} placeholder
resolution. This change ensures that all locations are processed and
replaced as expected.
Issue: SPR-9133
Backport-Issue: SPR-9127
Backport-Commit: 4df2a14b13
Previously, a user could specify an empty array of resource locations
to the @PropertySource annotation, which amounts to a meaningless no-op.
ConfigurationClassParser now throws IllegalArgumentException upon
encountering any such misconfiguration.
Prior to this commit, specifying a named @PropertySource with multiple
values would not work as expected. e.g.:
@PropertySource(
name = "ps",
value = { "classpath:a.properties", "classpath:b.properties" })
In this scenario, the implementation would register a.properties with
the name "ps", and subsequently register b.properties with the name
"ps", overwriting the entry for a.properties.
To fix this behavior, a CompositePropertySource type has been introduced
which accepts a single name and a set of PropertySource objects to
iterate over. ConfigurationClassParser's @PropertySource parsing routine
has been updated to use this composite approach when necessary, i.e.
when both an explicit name and more than one location have been
specified.
Note that if no explicit name is specified, the generated property
source names are enough to distinguish the instances and avoid
overwriting each other; this is why the composite wrapper is not used
in these cases.
Issue: SPR-9127