java.util.concurrent's ScheduledExecutorService and its #schedule*
methods allow for an 'initialDelay' parameter in milliseconds.
Similarly, Spring's TaskExecutor abstraction allows for a concrete
'startTime' expressed as a Date. However, Spring's <task:scheduled> XML
element and @Scheduled annotation have, to date, not allowed for an
initial delay parameter that can be propagated down to the underlying
TaskScheduler/ScheduledExecutorService.
This commit introduces initial-delay and #initialDelay attributes to
task:scheduled and @Scheduled respectively, both indicating the number
of milliseconds to wait before the first invocation of the method in
question. Specifying a delay in this fashion is only valid in
conjunction with fixed-rate and fixed-delay tasks (i.e. not with cron
or trigger tasks).
The principal changes required to support these new attributes lie in
ScheduledTaskRegistrar, which previously supported registration of
tasks in the form of a Runnable and a Long parameter indicating (in the
case of fixed-rate and fixed-delay tasks), the interval with which the
task should be executed. In order to accommodate a third (and optional)
'initialDelay' parameter, the IntervalTask class has been added as a
holder for the Runnable to be executed, the interval in which to run
it, and the optional initial delay. For symmetry, a TriggerTask and
CronTask have also been added, the latter subclassing the former. And a
'Task' class has been added as a common ancestor for all the above.
One oddity of the implementation is in the naming of the new
setters in ScheduledTaskRegistrar. Prior to this commit, the setters
were named #setFixedDelayTasks, #setFixedRateTasks, etc, each accepting
a Map<Runnable, long>. In adding new setters for each task type, each
accepting a List<IntervalTask>, List<CronTask> etc, naturally the
approach would be to use method overloading and to introduce methods
of the same name but with differing parameter types. Unfortunately
however, Spring does not support injection against overloaded methods
(due to fundamental limitations of the underlying JDK Introspector).
This is not a problem when working with the ScheduledTaskRegistrar
directly, e.g. from within a @Configuration class that implements
SchedulingConfigurer, but is a problem from the point of view of the
ScheduledTasksBeanDefinitionParser which parses the <task:scheduled>
element - here the ScheduledTaskRegistrar is treated as a Spring bean
and is thus subject to these limitations. The solution to this problem
was simply to avoid overloading altogether, thus the naming of the new
methods ending in "List", e.g. #setFixedDelayTasksList, etc. These
methods exist primarily for use by the BeanDefinitionParser and are
not really intended for use by application developers. The Javadoc for
each of the new methods makes note of this.
Issue: SPR-7022
In anticipation of substantive changes required to implement "initial
delay" support in the <task:scheduled> element and @Scheduled
annotation, the following updates have been made to the components and
infrastructure supporting scheduled task execution:
- Fix code style violations
- Fix compiler warnings
- Add Javadoc where missing, update to use {@code} tags, etc.
- Organize imports to follow conventions
This commit introduces three abstract WebApplicationInitializers, to be
used in the typical setup of a Spring-based web application.
- AbstractContextLoaderInitializer provides an abstract base class for
registering a ContextLoaderListener.
- AbstractDispatcherServletInitializer provides an abstract base class
for registering a DispatcherServlet, with an optional root context.
- AbstractAnnotationConfigDispatcherServletInitializer provides an
abstract base class for registering a DispatcherServlet and optional
ContextLoaderListener based on annotated (e.g. @Configuration)
classes.
Issue: SPR-9300
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-6847
The reference manual previously did not mention the applicability of
JSR-250 lifecycle annotations within the TestContext framework. The
lacking documentation here has lead to misunderstandings of the support
provided for @PostConstruct and @PreDestroy in test classes.
The testing chapter of the reference manual has therefore been updated
to explicitly define the limited support for these annotations.
Also introduced Jsr250LifecycleTests for empirical verification of the
expected behavior.
Issue: SPR-4868
Updated the testing chapter of the reference manual to refer to
'annotated classes' instead of 'configuration classes' where
appropriate.
Also revised the content and examples in the @ContextConfiguration
annotation section, mentioned Gradle, and reformatted the entire text.
Issue: SPR-9401
When URL decoding is turned off in AbstractHandlerMapping, the
extracted path variables are also not encoded. Turning off URL decoding
may be necessary for request mapping to work correctly when the path
may contain the (encoded) special character '/'. At the same time there
is no good reason not to leave path variables encoded. This change
ensures path variables are encoded when URL decoding is turned off.
Issue: SPR-9098
MappingJackson2JsonView and MappingJacksonJsonView now provide an
option that will set the Content-Length header of JSON responses.
Use of the option implies buffering of the response and it must be
enabled explicitly.
Issue: SPR-7866
This change makes it possible to provide a custom MessageCodesResolver
through the MVC Java config whether using @EnableWebMvc and extending
WebMVcConfigurerAdapter or sub-classing directly from
WebMvcConfigurationSupport.
Issue: SPR-9223
The new property can be used to ignore specific exceptions that may
otherwise be matched by the "exceptionMappings" property or resolved
through the defaultErrorView.
Issue: SPR-5193
When @ResponseStatus has a reason and servletResponse.sendError() is
called, the response is committed and should no longer be written to.
After this change, the ServletInvocableHandlerMethod will mark the
response fully handled and will ignore any non-null return values.
Issue: SPR-9159
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
The MappingJacksonHttpMessageConverter now catches all IOException
types raised while reading JSON and translates them into
HttpMessageNotReadableException.
Issue: SPR-9238
Previously RequestMappingHandlerMapping detected @RequestMapping
methods through an initApplicationContext() hook. However, the
HandlerMapping may not have been fully set up with all its
dependencies at that point including settings like useSuffixPattern
and others.
This change moves the detection @RequestMapping methods to an
InitializingBean.afterPropertiesSet() hook.
Issue: SPR-9371
The ErrorsMethodArgumentResolver expects the preceding @ModelAttribute
in the controller method signature to be the last one added in the
model -- an assumption that can break if a model attribute is added
earlier (e.g. through a @ModelAttribute method) and more attributes
are added as well. This fix ensures when an @ModelAttribute is resolved
as a controller method argument it has the highest index in the model.
Issue: SPR-9378
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
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
From a programming model perspective, @RequestMapping methods now
support two new return value types:
* java.util.concurrent.Callable - used by Spring MVC to obtain the
return value asynchronously in a separate thread managed transparently
by Spring MVC on behalf of the application.
* org.springframework.web.context.request.async.DeferredResult - used
by the application to produce the return value asynchronously in a
separate thread of its own choosing.
The high-level idea is that whatever value a controller normally
returns, it can now provide it asynchronously, through a Callable or
through a DeferredResult, with all remaining processing --
@ResponseBody, view resolution, etc, working just the same but
completed outside the main request thread.
From an SPI perspective, there are several new types:
* AsyncExecutionChain - the central class for managing async request
processing through a sequence of Callable instances each representing
work required to complete request processing asynchronously.
* AsyncWebRequest - provides methods for starting, completing, and
configuring async request processing.
* StandardServletAsyncWebRequest - Servlet 3 based implementation.
* AsyncExecutionChainRunnable - the Runnable used for async request
execution.
All spring-web and spring-webmvc Filter implementations have been
updated to participate in async request execution.
The open-session-in-view Filter and interceptors implementations in
spring-orm will be updated in a separate pull request.
Issue: SPR-8517
- Spring remains compatible against AJ version 1.6.8, but is now
compiling and testing against 1.6.12
- Encountered what appears to be an AJ bug introduced in 1.6.10: an
assertion in org.aspectj.weaver.UnresolvedType causes a false
negative failure when encountering org.springframework.io.Resource
arrays, e.g. "[org.springframework.io.Resource@xxx". This problem
has been reported to the AJ team and in the meantime, the recommended
workaround is to disable assertions either completely, or at least
selectively with
-disableassertions:org.aspectj.weaver.UnresolvedType
Issue: SPR-7989, SPR-9272
The new @MVC support classes select a HandlerMethodArgumentResolver
and a HandlerMethodReturnValueHandler statically, i.e. based on
the signature of the method, which means that a controller method
can't declare a more general return type like Object but actually
return a more specific one, e.g. String vs RedirectView, and
expect the right handler to be used.
The fix ensures that a HandlerMethodReturnValueHandler is selected
based on the actual return value type, which is something that was
supported with the old @MVC support classes. One consequence
of the change is the selected HandlerMethodReturnValueHandler can
no longer be cached but that matches the behavior of the old
@MVC support classes.
Issues: SPR-9218
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-9148
Before this change bean scopes chapter in Spring reference documentation
had a note which mentioned that creating a scoped proxy for singleton-
or prototype-scoped beans will throw BeanCreationException.
This is no longer the case and this change removes the mentioned note.
Issue: SPR-7940
Each spring-* subproject now has sourcesJar and javadocJar tasks
- Ignore subproject overview.html files for now (not all have one)
- Ensure @author attribution occurs
- Javadoc 'header' is project description
spring-asm is a special case
- source jar is created, but empty (to comply with entry rules for
Maven Central)
- add package-info.java explaining the nature of spring-asm
this is nice, because it shows up in the public API docs now.
- add SpringAsmInfo in the org.springframework.asm package as a
placeholder allowing the generation of javadocs (see link to bug)
- add explicit 'repackageAsm' Gradle task allowing for easy testing
and merging of jar containing bundlor manifest as well as jar
containing repackaged ASM classes.
- Add 'api' gradle task to generate project-wide API Javadoc
results in <root>/build/api
- Add docsZip task including api and reference documentation
suitable for publication to
http://static.springframework.org/docs/spring-framework
- Add schemaZip task including all spring-* XSD files
suitable for publication to http://static.springframework.org/schema
- Add distZip task to include all libs, docs and schema
- filter src/dist/*.txt for ${copyright} and ${version}
- copy legal (notice, license) dynamically into individual jar files
- copy legal and readme files into root of distribution zip
- Refactor location of 'wrapper' task
Each of the zip tasks (docsZip, schemaZip, distZip) have been added to
the 'archives' configuration, meaning that (a) they will be built
automatically with `gradle build` and (b) will be published
automatically to artifactory when using the Artifactory Gradle plugin
and/or Artifactory Bamboo integration.
Prior to this change, license.txt and notice.txt files were duplicated
across every subproject in their respective src/main/resources/META-INF
directories.
This commit centralizes these files under the root project at src/dist,
along with the changelog and readme files. The definition of the 'jar'
task has been been extended to include the license and notice files in
module jars as they are created.
The directory is named src/dist because these files are all related to
distribution - the readme is different than the one you see at the root
of the source tree - the intended audience is for users who download
the spring-framework distribution zip. A task to create that
distribution zip will be added in subsequent commits.
Problems
- Eliminate — in favor of —
— was causing 'no such entity' errors during docbook
processing; — produces the equivalent output.
- Fix column issues in appendices
column counts were set to 3, when they are in fact 4. This passed
under DocBook 4 and Spring Build for unknown reasons, but caused a
hard stop under DocBook 5 and the docbook-reference-plugin.
- Add jdbc callout section in docbook 5-friendly style
use <co/> tags as advertised in DocBook documentation.
- Set correct widths for PDF ref doc images
images were rendering larger than the PDF page; just set all to
width=400 and everything looks good.
Polish
- Update reference doc copyright to 2012
- Remove "work-in-progress" language from ref docs
- Update maven URLs to repo.springsource.org
- Update javadoc urls from 3.0.x/javadoc-api => current/api
- Replace hardcoded "3.1" with ${version} in ref doc
It was determined (through painful trial and error) that after the
upgrade to DocBook 5 and the gradle-docbook-reference plugin, that
<emphasis> elements embedded within <programlisting> elements causes
NullPointerExceptions during processing.
This change eliminates these <emphasis> elements to work around the
problem. This means a slight degradation in presentation for the
affected areas of the reference documentation. After some research,
it is not clear what other workarounds may be possible that leave
the text actually emphasized.
This change eliminates the spring-framework-reference subproject, moving
these sources into the root project's own src directory.
This makes sense because the reference docs span all submodules, and
also because api Javadoc is created at the root project level as well.
This means that both api and reference documentation output will now
reside in the root project's 'build' directory. This is more consistent
and easy to discover.
This commit eliminates the 'integration-tests' subproject in favor of
managing these sources under the root project's own 'src' directory.
This helps to avoid special-case handling for integration-tests in the
Gradle build, e.g. avoiding publication of jars to Artifactory /
Maven Central.
It is also semantically more correct. This is not a Spring Framework
subproject so much as it is a collection of integration tests that
span functionality across many subprojects. In this way, it makes
sense to place them directly under the root project.
Issue: SPR-8116
Branch in question is 'env' branch from git://git.springsource.org/sandbox/cbeams.git; merged into
git-svn repository with:
git merge -s recursive -Xtheirs --no-commit env
No merge conflicts, but did need to
git rm spring-build
prior to committing.
With this change, Spring 3.1.0 development is now happening on SVN
trunk. Further commits to the 3.0.x line will happen in an as-yet
uncreated SVN branch. 3.1.0 snapshots will be available
per the usual nightly CI build from trunk.