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-9179
JDK7 changed its reflections API in order to resolve
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041784
In short, JDK 5 and 6 (wrongly) return GenericArrayTypes in certain
reflection scenarios, whereas JDK 7 changed this to return a normal
array type. For Jaxb2Marshaller, this meant that marshaling byte arrays
was not supported under JDK 7.
This change fixes that, so that Jaxb2Marhsaller supports marshalling
byte arrays again (under JDK 5, 6 or 7).
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-9161
- Rename customized .wrapper to default gradle/wrapper directory for
out of the box compatibility with STS Gradle tooling
- Add .settings/gradle directory to capture defaults when using STS
Gradle tooling to import projects
Prior to this change, before a bean is created by EhCacheFactoryBean,
its #getObjectType would return only an Ehcache interface. This caused
unwanted wiring issues as described in the related JIRA issue.
This fix makes use of EhCacheFactoryBean's configuration to determine
the specific Ehcache object type even before it's created, such that
the container is provided with as much information as possible when
resolving dependencies. Nevertheless, users are advised to code to
the Ehcache interface.
Issue: SPR-7843
ORA-00054 is already mapped to CannotAcquireLockException and is
described as
"resource busy and acquire with NOWAIT specified"
As pointed out in the associated JIRA issue, ORA-30006 is quite similar
being described as
"resource busy; acquire with WAIT timeout expired"
This commit maps ORA-30006 to CannotAcquireLockException as well.
Issue: SPR-9141
Changes in commit 41ade68b50b39485b3cf02b9c6fb8eb74962146b 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, SPR-9127
* 3.1.x:
Warn re Environment construction and instance vars
Disallow empty @PropertySource(value = {})
Fix @PropertySource bug with multiple values
final preparations for 3.1.1 release
added "receive-timeout" attribute to "jms:listener-container" element
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
* 3.1.x:
Demonstrate use of @Configuration as meta-annotation
Prune dead code from JmsTransactionManager#doBegin
Apply @Configuration BeanNameGenerator consistently
Improve @Configuration bean name discovery
Fix infinite recursion bug in nested @Configuration
Polish static imports
Minor fix in ServletResponseMethodArgumentResolver
extracted ResourceUtils.useCachesIfNecessary(URLConnection) method (SP
prepared for 3.1.1 release
CustomSQLExceptionTranslatorRegistry/Registrar etc
revised CustomSQLExceptionTranslatorRegistry/Registrar method naming
use custom InputStream traversal instead of a full byte array (SPR-911
PathMatchingResourcePatternResolver preserves caching for JNLP jar con
Resource "contentLength()" implementations work with OSGi bundle resou
fixed MethodInvokingJobDetailFactoryBean for compatibility with Quartz
fixed MethodInvokingJobDetailFactoryBean for compatibility with Quartz
Since the introduction of the AnnotationConfig(Web)ApplicationContext
types in Spring 3.0, it has been possible to specify a custom
bean name generation strategy via the #setBeanNameGenerator methods
available on each of these classes.
If specified, that BeanNameGenerator was delegated to the underlying
AnnotatedBeanDefinitionReader and ClassPathBeanDefinitionScanner. This
meant that any @Configuration classes registered or scanned directly
from the application context, e.g. via #register or #scan methods would
respect the custom name generation strategy as intended.
However, for @Configuration classes picked up via @Import or implicitly
registered due to being nested classes would not be aware of this
strategy, and would rather fall back to a hard-coded default
AnnotationBeanNameGenerator.
This change ensures consistent application of custom BeanNameGenerator
strategies in the following ways:
- Introduction of AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR
singleton
If a custom BeanNameGenerator is specified via #setBeanNameGenerator
the AnnotationConfig* application contexts will, in addition to
delegating this object to the underlying reader and scanner, register
it as a singleton bean within the enclosing bean factory having the
constant name mentioned above.
ConfigurationClassPostProcessor now checks for the presence of this
singleton, falling back to a default AnnotationBeanNameGenerator if
not present. This singleton-based approach is necessary because it is
otherwise impossible to parameterize CCPP, given that it is
registered as a BeanDefinitionRegistryPostProcessor bean definition
in AnnotationConfigUtils#registerAnnotationConfigProcessors
- Introduction of ConfigurationClassPostProcessor#setBeanNameGenerator
As detailed in the Javadoc for this new method, this allows for
customizing the BeanNameGenerator via XML by dropping down to direct
registration of CCPP as a <bean> instead of using
<context:annotation-config> to enable @Configuration class
processing.
- Smarter defaulting for @ComponentScan#beanNameGenerator
Previously, @ComponentScan's #beanNameGenerator attribute had a
default value of AnnotationBeanNameGenerator. The value is now the
BeanNameGenerator interface itself, indicating that the scanner
dedicated to processing each @ComponentScan should fall back to an
inherited generator, i.e. the one originally specified against the
application context, or the original default provided by
ConfigurationClassPostProcessor. This means that name generation
strategies will be consistent with a single point of configuration,
but that individual @ComponentScan declarations may still customize
the strategy for the beans that are picked up by that particular
scanning.
Issue: SPR-9124
Prior to this commit, and based on earlier changes supporting SPR-9023,
ConfigurationClassBeanDefinitionReader employed a simplistic strategy
for extracting the 'value' attribute (if any) from @Configuration in
order to determine the bean name for imported and nested configuration
classes. An example case follows:
@Configuration("myConfig")
public class AppConfig { ... }
This approach is too simplistic however, given that it is possible in
'configuration lite' mode to specify a @Component-annotated class with
@Bean methods, e.g.
@Component("myConfig")
public class AppConfig {
@Bean
public Foo foo() { ... }
}
In this case, it's the 'value' attribute of @Component, not
@Configuration, that should be consulted for the bean name. Or indeed if
it were any other stereotype annotation meta-annotated with @Component,
the value attribute should respected.
This kind of sophisticated discovery is exactly what
AnnotationBeanNameGenerator was designed to do, and
ConfigurationClassBeanDefinitionReader now uses it in favor of the
custom approach described above.
To enable this refactoring, nested and imported configuration classes
are no longer registered as GenericBeanDefinition, but rather as
AnnotatedGenericBeanDefinition given that AnnotationBeanNameGenerator
falls back to a generic strategy unless the bean definition in question
is assignable to AnnotatedBeanDefinition.
A new constructor accepting AnnotationMetadata
has been added to AnnotatedGenericBeanDefinition in order to support
the ASM-based approach in use by configuration class processing. Javadoc
has been updated for both AnnotatedGenericBeanDefinition and its now
very similar cousin ScannedGenericBeanDefinition to make clear the
semantics and intention of these two variants.
Issue: SPR-9023
Prior to this commit, an infinite recursion would occur if a
@Configuration class were nested within its superclass, e.g.
abstract class Parent {
@Configuration
static class Child extends Parent { ... }
}
This is because the processing of the nested class automatically
checks the superclass hierarchy for certain reasons, and each
superclass is in turn checked for nested @Configuration classes.
The ConfigurationClassParser implementation now prevents this by
keeping track of known superclasses, i.e. once a superclass has been
processed, it is never again checked for nested classes, etc.
Issue: SPR-8955
Prior to changes in commit 57851de88e,
AbstractResource#getFilename threw IllegalStateException unless
overridden by a subclass. Following that change, this method now throws
null instead, but ResourceTests#testAbstractResourceExceptions had not
been updated to reflect, resulting in a false negative failure. This has
now been fixed.
Issue: SPR-9043
Eclipse allows autoboxing on type inference; Sun javac does not. This
means that variables assigned from calls to
AnnotationAttributes#getNumber should consistently use object wrappers
as opposed to number primitives. There was only one such instance
anyway, and has now been updated accordingly.
* 3.1.x: (61 commits)
Compensate for changes in JDK 7 Introspector
Avoid 'type mismatch' errors in ExtendedBeanInfo
Polish ExtendedBeanInfo and tests
Infer AnnotationAttributes method return types
Minor fix in MVC reference doc chapter
Hibernate 4.1 etc
TypeDescriptor equals implementation accepts annotations in any order
"setBasenames" uses varargs now (for programmatic setup; SPR-9106)
@ActiveProfiles mechanism works with @ImportResource as well (SPR-8992
polishing
clarified Resource's "getFilename" method to consistently return null
substituteNamedParameters detects and unwraps SqlParameterValue object
Replace spaces with tabs
Consider security in ClassUtils#getMostSpecificMethod
Adding null check for username being null.
Improvements for registering custom SQL exception translators in app c
SPR-7680 Adding QueryTimeoutException to the DataAccessException hiera
Minor polish in WebMvcConfigurationSupport
Detect overridden boolean getters in ExtendedBeanInfo
Polish ExtendedBeanInfoTests
...
Prior to JDK 7, java.beans.Introspector registered indexed write methods
irrespective of return type, for example either of the following methods
were legal
void setFoo(int i, Foo foo)
Object setFoo(int i, Foo foo)
This was considered a bug and disallowed starting with JDK 7, such that
only the former signature is a candidate.
Supporting non-void returning setter methods is exactly what
ExtendedBeanInfo was designed to do, and prior to this commit, the
implementation of ExtendedBeanInfo assumed this (somewhat surprising)
behavior from the underlying Introspector, and because it worked out of
the box, took no extra steps to recognize and register these methods.
For this reason, non-void returning indexed write methods were not
registered under JDK 7+, causing test failures in ExtendedBeanInfoTests.
Now the implementation is careful to detect these methods without any
assumption about Introspector behavior, such that they are registered in
exactly the same fashion across JDK versions.
Issue: SPR-9014
Prior to this commit, ExtendedBeanInfo would add non-indexed write
methods without consideration for the presence of indexed read/write
methods, which is invalid per the JavaBeans spec and per the behavior
of java.beans.Introspector. That is, a method with the signature
void setFoo(Foo foo)
Should never be registered as a write method if the following method
signature is also present in the class
void setFoo(int i, Foo foo)
In most cases, this oversight caused no problems, but in certain
situations where a bean actually contains such a mismatch of methods,
"type mismatch" errors were thrown when ExtendedBeanInfo attempted the
illegal addition against the underlying property descriptor.
The implementation is now more careful about checking the parameter type
of write methods -- if the property descriptor in question is an
IndexedPropertyDescriptor, i.e. has an indexed write method, then any
non-indexed write method candidate must have a single *array* parameter,
which conforms to the spec and to Introspector behavior.
Issue: SPR-8937
- Drop 'expectedType' parameter from #getClass and #getEnum methods and
rely on compiler inference based on type of assigned variable, e.g.
public @interface Example {
Color color();
Class<? extends UserType> userType();
int order() default 0;
}
AnnotationAttributes example =
AnnotationUtils.getAnnotationAttributes(Example.class, true, true);
Color color = example.getEnum("color");
Class<? extends UserType> userType = example.getClass("userType");
or in cases where there is no variable assignment (and thus no
inference possible), use explicit generic type, e.g.
bean.setColor(example.<Color>getEnum("color"));
- Rename #get{Int=>Number} and update return type from int to
<N extends Number>, allowing invocations such as:
int order = example.getNumber("order");
These changes reduce the overall number of methods exposed by
AnnotationAttributes, while at the same time providing comprehensive
access to all possible annotation attribute types -- that is, instead of
requiring explicit #getInt, #getFloat, #getDouble methods, the
single #getNumber method is capabable of handling them all, and without
any casting required. And the obvious additional benefit is more concise
invocation as no redundant 'expectedType' parameters are required.