After considering JSR-310 types to be simple we map these types primarily to java.util.Date as the majority of stores does not natively support JSR-310 types. Converters referencing JSR-310 types are now properly annotated with Reading/WritingConverter annotations to distinguish between reading and writing intents.
Othwerise, converters between JSR-310/java.util types and Joda/ThreeTenBackport to JSR-310 types interfere with conversion as regular java.util.Date types would convert to e.g. LocalDateTime.
To prevent repeated failing calls to ClassUtils.forName(…) we now also cache the failed attempt and simply eagerly return null as subsequent similar attempts to resolve a class are going to fail anyway.
Original pull request: #286.
To prevent repeated failing calls to ClassUtils.forName(…) we now also cache the failed attempt and simply eagerly return null as subsequent similar attempts to resolve a class are going to fail anyway.
Previously a custom Iterable implementation would've caused QueryMethod.isCollectionQuery() to return true. We now solely rely on TypeInformation.isCollectionLike() (which checks for exact Iterable, Collection assignability and arrays) after handling potential wrapper types.
Instead of a simple check for assignability from Iterable, we now properly use TypeInformation.isCollectionLike(), which checks for Iterable equality or assignability of collections or arrays as well as an explicit check for Slice as that is needed to properly unwrap Page instances and Slices themselves. That prevents custom domain types implementing Iterable from being unwrapped into their element types.
We now provide MethodsMetadataReader to read method metadata from a class file. MethodMetadata is read for all user-declared methods except for constructors (which are technically methods, too).
MethodsMetadataReaderFactory factory = new MethodsMetadataReaderFactory();
MethodsMetadataReader metadataReader = factory.getMetadataReader("com.acme.Foo");
MethodsMetadata metadata = metadataReader.getMethodsMetadata();
This new API is now used by DefaultProjectionInformation to make sure the order of input properties is based on the declaration order in the projection interfaces. Previously that order could not be guaranteed to be stable.
Original pull request: #263.
Related tickets: DATACMNS-1206.
Original commit: 9e013d3.
We now consider property annotations as merged annotations when initially scanning for annotations in a property declaration. Composed annotations such as declared outside our code are captured correctly because they use an own type that is not queried by users of PersistentProperty. Own, revised annotations, using @AliasFor providing an alias for annotation values require merged annotation processing.
Previously, annotations were cached as-is without resolving @AliasFor. This caused a later lookup via findAnnotation(…) to return the cached annotation without aliasing. Because the annotation was cached, no further lookup via AnnotatedElementUtils.findMergedAnnotation(…) was attempted.
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD })
public @interface RevisedAnnnotationWithAliasFor {
@AliasFor("value")
String name() default "";
@AliasFor("name")
String value() default "";
}
public class Person {
@RevisedAnnnotationWithAliasFor(value = "spring")
String firstname;
}
PersistentProperty firstname = …
property.findAnnotation(…) returned previously @RevisedAnnnotationWithAliasFor(value = "spring", name = "")
now we return @RevisedAnnnotationWithAliasFor(value = "spring", name = "spring")
Original ticket: DATACMNS-981.
Java 6 compatible backport of 2da5acc553.
We now make sure that type expressions cannot be used in SpEL expressions handled by MapDataBinder. They're gonna be rejected by considering the property not writable. SpEL expression evaluation errors are now forwarded as NotWritablePropertyException to make sure the failure gets handled as if the property referred to doesn't exist.
If a query method now uses e.g. a Vavr Set as return type, we now also use a potential source List as input for the LinkedHashSet, even if that changes the characteristics (duplicate policy etc.) of the result. This is consistent with our general handling of collections as we're using a Spring ConversionService for collection mapping anyway.
In general the new conversion algorithm is driven by the expected target type first:
- i.v.c.Seq -> i.v.c.List
- i.v.c.Set -> i.v.c.LinkedHashSet
- i.v.c.Map -> i.v.c.LinkedHashMap
If none of the declared types is assignable we fall back to the previous algorithm choosing an implementation as close as possible to the original source value:
- j.u.List -> i.v.c.List
- j.u.Set -> i.v.c.LinkedHashSet
- j.u.Map -> i.v.c.LinkedHashMap
Applied the same fixes to the deprecated Javaslang support. Removed some obsolete full qualifications of types.
We now prevent the superfluous creation of a MethodParameter and TypeDescriptor instance in repository method execution in case the value to be returned already is an instance of the expected method return type.
In CustomRepositoryImplementationDetector, we now immediately hand the Environment to the constructor of ClassPathScanningCandidateComponentProvider instead of setting it afterwards. This prevents a default StandardEnvironment from being created in the previously used constructor.
We now deploy a custom BeanPostProcessor to customize RequestMappingHandlerAdapter instances by prepending a ProxyingHandlerMethodArgumentResolver (requiring a @ModelAttribute) to the list of resolved HandlerMethodArgumentResolvers to make sure the settings defined in the annotation are applied but the projecting way of data binding is still used.