Rename ExceptionHandlerSupport to ResponseEntityExceptionHandler and
emphasize the contrast to DefaultHandlerExceptionResovler -- i.e.
one returns a ResponseEntity and relies on message converters while
the other returns a ModelAndView and relies on view resolution.
Issue: SPR-9290
Before this commit, the CachedIntrospectionResults was hard-coded to
create ExtendedBeanInfos for bean classes. The ExtendedBeanInfo support
the JavaBeans property contract only.
This commit introduces the BeanInfoFactory, a strategy for creating
BeanInfos. Through this strategy, it is possible to support
beans that do not necessarily implement the JavaBeans contract (i.e.
have a different getter or setter style).
BeanInfoFactories are are instantiated by the
CachedIntrospectionResults, which looks for
'META-INF/spring.beanInfoFactories' files on the class path. These files
contain one or more BeanInfoFactory class names. When a BeanInfo is to
be created, the CachedIntrospectionResults will iterate through the
factories, asking it to create a BeanInfo for the given bean class. If
none of the factories support it, an ExtendedBeanInfo is created as a
default.
This commit also contains a change to Property, allowing BeanWrapperImpl
to specify the property name at construction time (as opposed to using
Property#resolveName(), which supports the JavaBeans contract only).
Issue: SPR-9677
This change makes it possible to declare an @RequestBody argument with
a generic type (e.g. List<Foo>). If a GenericHttpMessageConverter
implementation supports the method argument, then the request will be
converted to the apropiate target type.
The new GenericHttpMessageConverter is implemented by the
MappingJacksonHttpMessageConverter and also by a new
Jaxb2CollectionHttpMessageConverter that can read read a generic
Collection where the generic type is a JAXB type annotated with
@XmlRootElement or @XmlType.
Issue: SPR-9570
This change makes it possible to use the RestTemplate to read an HTTP
response into a target generic type object. The RestTemplate has three
new exchange(...) methods that accept ParameterizedTypeReference -- a
new class that enables capturing and passing generic type info.
See the Javadoc of the three new methods in RestOperations for a
short example.
To support this feature, the HttpMessageConverter is now extended by
GenericHttpMessageConverter, which adds a method for reading an
HttpInputMessage to a specific generic type. The new interface
is implemented by the MappingJacksonHttpMessageConverter and also by a
new Jaxb2CollectionHttpMessageConverter that can read read a generic
Collection where the generic type is a JAXB type annotated with
@XmlRootElement or @XmlType.
Issue: SPR-7023
The target parameters for a FlashMap must be decoded to be able to
match them to the parameters of incoming requests given that the
HttpServletRequest returns decoded request parameters.
SPR-9657
An @RequestBody or an @RequestPart argument can now be followed by an
Errors/BindingResult argument making it possible to handle validation
errors (as a result of an @Valid annotation) locally within the
@RequestMapping method.
Issue: SPR-7114
The new class is functionally equivalent to the
DefaultHandlerExceptionResolver (i.e. it translates Spring MVC
exceptions to various status codes) but uses an @ExceptionHandler
returning a ResponseEntity<Object>, which means it can be customized to
write error content to the body of the response.
Issue: SPR-9290
Starting with Spring 3.1 applications can specify
contextInitializerClasses via context-param and init-param in web.xml;
however, there is currently no way to have such initializers invoked in
integration testing scenarios without writing a custom
SmartContextLoader. For comprehensive integration testing it should
therefore be possible to re-use ApplicationContextInitializers in the
Spring TestContext Framework as well.
This commit makes this possible at the @ContextConfiguration level by
allowing an array of ACI types to be specified, and the out-of-the-box
SmartContextLoader implementations invoke the declared initializers at
the appropriate time.
- Added initializers and inheritInitializers attributes to
@ContextConfiguration.
- Introduced support for ApplicationContextInitializers in
ContextConfigurationAttributes, MergedContextConfiguration, and
ContextLoaderUtils.
- MergedContextConfiguration stores context initializer classes as a
Set and incorporates them into the implementations of hashCode() and
equals() for proper context caching.
- ApplicationContextInitializers are invoked in the new
prepareContext(GenericApplicationContext, MergedContextConfiguration)
method in AbstractGenericContextLoader, and ordering declared via the
Ordered interface and @Order annotation is honored.
- Updated DelegatingSmartContextLoader to support initializers.
Specifically, a test class may optionally declare neither XML
configuration files nor annotated classes and instead declare only
application context initializers. In such cases, an attempt will
still be made to detect defaults, but their absence will not result
an an exception.
- Documented support for application context initializers in Javadoc
and in the testing chapter of the reference manual.
Issue: SPR-9011
The MVC Java config method to implement is
WebMvcConfigurer.configureAsyncSupport(AsyncSupportConfigurer)
The MVC namespace element is:
<mvc:annotation-driven>
<mvc:async-support default-timeout="2500" task-executor="myExecutor" />
</mvc:annotation-driven>
Issue: SPR-9694
Methods returning DeferredResult can now specify a timeout value
through constructor arg while methods returning a Callable can wrap it
in an AsyncTask that also accepts a timeout and a specific task
executor.
Issue: SPR-9399
DeferredResult now has a setErrorResult method that can be set to an
Exception or an error object, error view, etc.
The new isSetOrExpired() method can be used to check pro-actively if
the DeferredResult is still usable or not.
The setDeferredResultHandler method is now public so tests may use it.
Issue: SPR-9690, SPR-9689
The invalidate() method in MockHttpSession is currently implemented
incorrectly. According to the Servlet specification, the method should
throw an IllegalStateException if it is invoked on an already
invalidated session. However, invoking invalidate() on the same
MockHttpSession instance multiple times does not throw an exception.
This commits addresses this issue by checking the invalid field and
throwing an IllegalStateException if it has already been set to true.
Issue: SPR-9686
Classes with this annotation can contain @ExceptionHandler,
@InitBinder, and @ModelAttribute methods that apply to all controllers.
The new annotation is also a component annotation allowing
implementations to be discovered through component scanning.
Issue: SPR-9112
spring-core, spring-aop and spring-context each have compile-time
dependencies on classes in the aspectjweaver jar. Prior to this commit,
only spring-core declared an optional dependency on it; now all three
do.
Issue: SPR-9683
Historically spring-orm has had an optional dependency on spring-web,
primarily in support of OpenSessionInView functionality. This optional
dependency was inadvertently made required when porting the build to
Gradle. This commit simply reintroduces the optional setting.
Issue: SPR-9632
XStreamMarshaller now supports writing to OutputStreams and reading from
InputStreams directly, as opposed to wrapping streams in a
OutputStreamWriter or InputStreamReader.
Issue: SPR-9663
Prior to this change, the repackaged spring-asm and spring-cglib jars
were being included wholesale in the spring-core jar, whereas the
intention was to include the unzipped classfiles.
This change ensures that spring-asm and spring-cglib jars are unzipped
on the fly when creating the spring-core jar.
Issue: SPR-9669
ReflectionTestUtils.setField() implicitly calls toString() on the target
object when arguments for a call to Assert.notNull() are built. This can
have undesirable side effects, for example if the toString() invocation
results in a thrown exception or access to an external system (e.g., a
database).
This commit addresses this issue by inlining the Assert.notNull() code,
thereby avoiding accidental invocation of toString() on a non-null
target.
Issue: SPR-9571
The default set of TestExecutionListeners is sufficient in most
integration testing scenarios; however, the TestContextManager
nonetheless logs an INFO message if the @TestExecutionListeners
annotation is not present on an integration test class.
In order to avoid flooding the logs with messages about the absence of
@TestExecutionListeners, this commit reduces the log level for such
messages from INFO to DEBUG.
Issue: SPR-8645
CGLIB 3 has been released in order to depend on ASM 4, which Spring now
depends on internally (see previous commit).
This commit eliminates spring-beans' optional dependency on cglib-nodep
v2.2 and instead repackages net.sf.cglib => org.springframework.cglib
much in the same way we have historically done with ASM.
This change is beneficial to users in several ways:
- Eliminates the need to manually add CGLIB to the application
classpath; especially important for the growing number of
@Configuration class users. Java-based configuration functionality,
along with proxy-target-class and method injection features now
work 'out of the box' in Spring 3.2.
- Eliminates the possibility of conflicts with other libraries that
may dependend on differing versions of CGLIB, e.g. Hibernate
3.3.1.ga and its dependency on CGLIB 2.1.3 would easily cause a
conflict if the application were depending on CGLIB 3 for
Spring-related purposes.
- Picks up CGLIB 3's changes to support ASM 4, meaning that CGLIB is
that much less likely to work well in a Java 7 environment due to
ASM 4's support for transforming classes with invokedynamic
bytecode instructions.
On CGLIB and ASM:
CGLIB's own dependency on ASM is also transformed along the way to
depend on Spring's repackaged org.springframework.asm, primarily to
eliminate unnecessary duplication of ASM classfiles in spring-core and
in the process save around 100K in the final spring-core JAR file size.
It is coincidental that spring-core and CGLIB currently depend on the
exact same version of ASM (4.0), but it is also unlikely to change any
time soon. If this change does occur and versions of ASM drift, then
the size optimization mentioned above will have to be abandoned. This
would have no compatibility impact, however, so this is a reasonable
solution now and for the forseeable future.
On a mysterious NoClassDefFoundError:
During the upgrade to CGLIB 3.0, Spring test cases began failing due to
NoClassDefFoundErrors being thrown from CGLIB's DebuggingClassWriter
regarding its use of asm-util's TraceClassVisitor type. previous
versions of cglib-nodep, particularly 2.2, did not cause this behavior,
even though cglib-nodep has never actually repackaged and bundled
asm-util classes. The reason for these NoClassDefFoundErrors occurring
now is still not fully understood, but appears to be due to subtle JVM
bytecode preverification rules. The hypothesis is that due to minor
changes in DebuggingClassWriter such as additional casts, access to
instance variables declared in the superclass, and indeed a change in
the superclass hierarchy, preverification may be kicking in on the
toByteArray method body, at which point the reference to the missing
TraceClassVisitor type is noticed and the NCDFE is thrown. For this
reason, a dummy implementation of TraceClassVisitor has been added to
spring-core in the org.springframework.asm.util package. This class
simply ensures that Spring's own tests never result in the NCDFE
described above, and more importantly that Spring's users never
encounter the same.
Other changes include:
- rename package-private Cglib2AopProxy => CglibAopProxy
- eliminate all 'cglibAvailable' checks, warnings and errors
- eliminate all 'CGLIB2' language in favor of 'CGLIB'
- eliminate all mention in reference and java docs of needing to add
cglib(-nodep) to one's application classpath
Issue: SPR-9669
ASM 4.0 is generally compatibile with Java 7 classfiles, particularly
including 'invokedynamic' instructions. This is important when
considering that Spring's component-scanning support is internally
ASM-based and it is increasingly likely that component classes having
invokedynamic instructions may be encountered and read by ASM.
This upgrade, then, is primarily preventive in nature.
Changes include:
- upgrade from ASM 2.2.3 to ASM 4.0
- adapt to ASM API changes as necessary throughout spring-core,
resulting in no impact to the public Spring API.
- remove dedicated spring-asm module
- use new :spring-core:asmRepackJar task to repackage
org.objectweb.asm => org.springframework.asm as per usual and write
repackaged classes directly into spring-core jar
The choice to eliminate the spring-asm module altogether and instead
inline the repackaged classes directly into spring-core is first to
eliminate an otherwise unnecessary second jar. spring-core has a
non-optional dependency on spring-asm meaning it is always on the
application classpath. This change simplifies that situation by
consoliding two jars into one. The second reason for this choice is in
anticipation of upgrading CGLIB to version 3 and inlining it into
spring-core as well. See subsequent commit for details.
Issue: SPR-9669
JarJar 1.3 now uses ASM 4 in order to be compatible with Java 7
'invokedynamic' instructions. This is not an immediate concern for
the classes that we use JarJar to repackage and transform, but is a
timely upgrade in anticipation of the subsequent commits in which we
upgrade Spring's own dependency on ASM from 2.2.3 to 4.0 and Spring's
dependency on CGLIB from 2.2 to 3.0 (which in turn depends on ASM 4.0).
See https://code.google.com/p/jarjar/wiki/ChangeLog
Issue: SPR-9669
Attempting to register a custom MethodFilter with a
StandardEvaluationContext after invoking setMethodResolvers() with a
custom list of MethodResolver instances results in a
NullPointerException. Based on the current documentation in
StandardEvaluationContext it is unclear what the expected behavior
should be, but either the implementation is broken, or the use case is
unsupported. In either case, allowing a NullPointerException to be
thrown is inappropriate.
This commit documents the fact that the SpEL MethodFilter is intended to
be used with the ReflectiveMethodResolver. Furthermore,
StandardEvaluationContext.registerMethodFilter() now throws an
IllegalStateException if the user attempts to set a filter after having
registered a custom set of resolvers.
Issue: SPR-9621
The Spring Expression Language currently supports nested single quotes
within expressions but not nested double quotes.
The SpEL tokenizer has been modified to support nested double quotes in
the same way it supports single quotes. A sequence of two double quotes
will now be replaced by one when evaluated.
Extra error handling has also been added to report when invalid escaping
is encountered, since SpEL does not support escaping with backslash.
Issue: SPR-9620
SpEL typically supports logical operators for boolean expressions
consistent with standard Java language syntax. However, the operators
for logical AND and logical OR are currently only supported as textual
operators. In other words, SpEL does not support the use of && and || as
logical operators.
The SpEL tokenizer has now been modified to recognize && and || as
symbolic boolean operators. The parser has been modified to allow the
use of either the textual or symbolic operators.
Issue: SPR-9614
- renamed resolveParameterizedReturnType() to
resolveReturnTypeForGenericMethod()
- fleshed out Javadoc for resolveReturnType() and
resolveReturnTypeForGenericMethod() regarding declaration of formal
type variables
- improved wording in log statements and naming of local variables
within resolveReturnTypeForGenericMethod()
Issue: SPR-9493
Prior to this commit null literals in SpEL expressions had to be
specified as "null" (i.e., all lowercase).
With this commit null literals in SpEL expressions are interpreted in a
case-insensitive manner, analogous to the current support for boolean
literals.
Issue: SPR-9613