Javaslang's collection and map types can now be used on repository query methods and get adapted similarly to nullable wrapper types (like JDK's Optional). Also made TypeInformation infrastructure aware of the map type so that a value type lookup gets handle correctly.
Previously, calls to ParameterizedTypeInformation.getMapValueType() caused an infinite recursion when invoked on a type information that was not a map type. This lead to a StackOverflowError.
We now call the super method doGetMapValueType() instead of calling the entry super method getMapValueType() and return by that null in case the map value type is not resolvable.
Original pull request: #176.
If the same generic type was used on recursively nested generics declarations, like this:
class GenericType<T> {}
class Nested extends GenericType<String> {}
class Concrete extends GenericType<Nested> {}
our traversal of the generics discovered T bound to String in Nested and as that is extending GenericType as well, the T detected here is the same instance as the T within the map discovered for Concrete. As we previously added the nested types after we added the original entry, the nested discovery overwrote the more local one.
We now make sure the detected nested type variable mappings don't overwrite already existing ones.
The translation of the list of actual type parameters into an array now uses the loop index correctly. Previously, it always used the first type parameter.
Added proper equals(…) and hashCode() methods to SyntheticParameterizedType to make sure instances created for the same type information and type parameters are considered equal.
If the type lookup from the store source returns a raw generic type (e.g. resolving the value of a generic property against a value of that generic type - i.e. not a more concrete type binding the generic information) in the context of a generic property, we previously did not apply the generics information of the contextual instance to that very raw type.
We now expose a TypeInformation.specialize(ClassTypeInformation) which applies the current generics context to the given raw type and basically creates a synthetic parameterized TypeInformation instance.
DefaultTypeMapper applies this specialization by default now with ClassTypeInformation simply returning the given type as is so that we don't create any resolution overhead in case no generics are involved in the first place.
Extended Version value object to correctly dump a non-numeric last segment of a version string to parse. Incorrect source version strings now raise an IllegalArgumentException better explaining the cause.
Related tickets: DATACMNS-496.
In case we create a ParameterizedTypeInformation for a property we now also analyze the field-local generics information and add the discovered type mappings to the type variable map.
RepositoryFactorySupport now exposes a setRepositoryBaseClass(…) to take a custom type that instances will be created reflectively for. This removes the need for a boilerplate repository factory and FactoryBean implementation to hook custom repository base class implementations into the infrastructure.
RepositoryFactorySupport now exposes a getTargetRepositoryViaReflection(…) method to allow sub-classes to create repository instances and consider customized repository base classes nonetheless. getTargetRepository(…) needs a tiny signature change which unfortunately requires imple
Fixed schema registration for version 1.8 schema. Added new XSD containing a base-class attribute on the <repositories /> element to customize the repository base class via XML.
Removed outdated section of how to create a custom base repository class from the reference documentation and replaced it with new simplified instructions.
Deprecated usage of factory-class attribute in configuration. Point users to newly introduced way of configuring a base class directly to avoid the need for a boilerplate repository factory and factory bean implementation.
DefaultRepositoryInformation now makes target class methods assignable before caching and returning them, so that they can always be invoked reflectively. Made this aspect part of the contract of RepositoryInformation.getTargetClassMethod(…).
Added stream to the list of supported query method prefixes. Allow Stream to be used as return type for paginating queries, too.
Renamed Java8StreamUtils to StreamUtils. Some additional JavaDoc.
Original pull request: #116.
A CloseableIterator abstracts the underlying result with support for releasing the associated resources via close() which can be transparently be used with try-with-resources in Java 7 since Closeable implements AutoCloseable from Java 7 on upwards. Added detector methods to QueryMethod to check whether the current method returns a Stream.
Introduced ReflectionUtils.isJava8StreamType to safely detect whether the given type is assignable to a Java 8 Stream. Introduced CloseableIteratorDisposingRunnable that can be registered as a cleanup action on a Stream.
Original pull request: #116.
We now make the field detected by the callback accessible so that the value lookup doesn't fail for private fields. Added a few more unit tests to verify behavior.
The initial setup of the type variable map now unfolds the detected types in the map to make sure we detect all type variables present in the current scope.
Added caching of component and map value TypeInformation instances to avoid repeated creation.
So far, the lookup of the type variable map was preferring the type variable maps detected on parent types in nested structures. This caused the concrete type variables in nested types not being considered correctly which caused the type resolution to fall back to the generic bounds.
We now accumulate the type variable maps to avoid having to lookup a certain map in the nesting hierarchy. The core fix is in ParentTypeAwareTypeInformation's constructor and mergeMaps(…) respectively. Simplified the handling of type variable maps and made proper use of generics throughout the class hierarchy.
The equals(…) and hashCode() methods of TypeVariableTypeInformation previously tried to evaluate the unresolved context of the type variable. This can cause issues in recursive type definitions as set up in the according test case. We now implement the methods based on the resolved type to makes sure we break the recursive lookup of PersistentEntity instances in AbstractMappingContext.
The erroneous lookup was actually caused by unresolved base types being added to the mapping context within the JPA project as the JPA meta-model also returns those types as managed types.
Related pull request: #84.
Version parsing failed when given version contained non-numeric parts (like 2.0.0-rc1). We now strip everything after the first non numeric part to create a logical version equivalent of the source String.
Original pull request: #81.
Previously, ParameterizedTypeInformation.hashCode() had been inconsistent to equals in case of a fully resolved parameterized type. This is now fixed by not including the parent reference in case a parameterized type is resolved completely.
Also, TypeDiscoverer.getActualType() does not return the component type for non-collection/non-maps anymore to make sure we don't accidentally unwrap parameterized types.
Added AnnotatedTypeScanner to easily scan for annotated types within a set of base packages. Picks up interfaces by default which had to be customized when using ClassPathScanningCanidateComponentProvider.
Added DirectFieldAccessFallbackBeanWrapper that will use direct field access for beans in case no accessor method can be found. This allows to easily implement bean property values through accessors first but using the field directly if the accessors aren't available.
Introduced AnnotationDetectionMethodCallback to easily find methods equipped with a given annotation.
Previously the map value type resolving algorithm checked the value type to be of type Map again to shortcut the resolution. We now weakened this to an assignment check and eagerly resolve the generic type if its bound on exactly that level already. If no concrete type argument can be found, we fall back to the general generics resolution mechanism.
In case of an unresolvable generic parameter in TypeDiscoverer's getTypeArgument(…) we check for a generic super type for the given bound and fall back to Object in case we find a parameterized type.
As of Spring 4, the GenericTypeResolver is more consistent in detecting raw types. It now returns null for both resolveTypeArguments(Set.class, Set.class) as well as resolveTypeArguments(Set.class, Iterable.class). The latter returns an array of Object.class in 3.x.
As this shouldn't make a pratical difference to actual clients (as they need to check for null anyway, we loosen the test case to be able to build Spring Data Commons against both Spring 3 and Spring 4.
Some polishing in the version detection in integration tests. Moved the Servlet 3.0 dependency into the Spring 4 profile.
We're now rejecting invalid constructor arguments handed to ClassTypeInformation, Part, PartTree and PropertyPath. Beyond that we skip the creation of a Part for an empty path segment, so that you don't end up with an invalid Part instance for a findAllByOrderByFooAsc.
So far the property lookup of a nested property path (e.g. "foo.bar") failed in cases the head property was not cached already. We now recursively resolve the type information even for an unpopulated cache.