Commit Graph

727 Commits

Author SHA1 Message Date
Oliver Gierke
d8cea8ba1c DATACMNS-1208 - AbstractMappingContext.hasPersistentEntityFor(…) now properly considers cached absence.
AbstractMappingContext.hasPersistentEntityFor(…) now also properly consideres the empty Optional as non-presence as that is held to allow to distinguish between a type completely unkown to the context, or already known but not considered a persistent entity.

Related pull request: #258.
2017-11-14 10:01:32 +01:00
Oliver Gierke
48db42ced8 DATACMNS-1180 - Polishing.
Avoid premature resolution of type in TypeDiscoverer.createInfo(…) and thereby simplify constructor in ParameterizedTypeInformation.
2017-10-27 10:47:20 +02:00
Oliver Gierke
baee26e5e7 DATACMNS-1180 - Fixed accessor lookup for generic properties.
In AbstractPersistentProperty, we now resolve the potentially generic return and parameter types of getters and setters. To achieve that Property has now been made aware of the actual owning type.
2017-10-27 10:40:38 +02:00
Mark Paluch
a13fc238d3 DATACMNS-1201 - Support generated property accessors for types in default packages.
We now support generated property accessors for types that reside in the default package.

Original pull request: #256.
2017-10-24 22:34:30 +02:00
Oliver Gierke
4bd8a3cfc3 DATACMNS-1199 - Added PropertyPath.nested(…).
This allows to obtain a nested property path based on a currently available one.
2017-10-19 12:40:53 +02:00
Oliver Gierke
b3e1601bc6 DATACMNS-1198 - Added PropertyPath.getLeafType() to expose leaf-property type. 2017-10-19 12:25:00 +02:00
Mark Paluch
78bd8fb0f7 DATACMNS-1200 - Guard casts to primitive type in ClassGeneratingEntityInstantiator.
We now insert assertions for primitive types before passing these to the actual constructor to prevent NullPointerExceptions. We also output the index/parameter name if the parameter was null.

Original pull request: #255.
2017-10-19 12:01:06 +02:00
Mark Paluch
634d8cbbd6 DATACMNS-1197 - Resolve Kotlin interface properties for nullability inspection.
We now resolve Kotlin interface properties to inspect these for nullability. Kotlin-reflect does not resolve interface property accessors yet so we need to handle this aspect ourselves.

Related ticket: https://youtrack.jetbrains.com/issue/KT-20768.
Original pull request: #254.
2017-10-13 17:32:41 +02:00
Oliver Gierke
8ce79c1810 DATACMNS-1196 - Fixed generics lookup for nested generics in ParameterizedTypeInformation.
We now eagerly resolve a generics declaration chain, which we previously - erroneously - expected GenericTypeResolver to do for us. Simplified TypeVariableTypeInformation implementation. Renamed ParameterizedTypeUnitTests to ParameterizedTypeInformationUnitTests.
2017-10-12 18:18:18 +02:00
Oliver Gierke
8da9679fc1 DATACMNS-1172 - Removed ability to use scanning all packages for repository implementations again.
Kept in a separate commit, so that it's easy to add again by reverting this commit. Removed, as the new behavior is effectively what had been documented as intended behavior all the time.

Original pull request: #248.
2017-09-27 16:09:12 +02:00
Oliver Gierke
da88163141 DATACMNS-1172 - Extracted fragment setup into value object.
We now use FragmentMetadata to control the way fragement interfaces and base packages to scan are calculated. Refactored RepositoryConfiguration.getImplementationBasePackages() to not take a parameter.

Original pull request: #248.
2017-09-27 16:09:11 +02:00
Mark Paluch
3bae636e2f DATACMNS-1172 - Limit repository custom implementation scanning by default to repository interface packages.
Custom repository implementation scan defaults to the repository interface package and its subpackages and no longer scans all configured base packages. Scan for fragment implementations defaults to the fragment interface package. Using the interface package for scanning aligns the behavior with the documentation.

This default can be changed with @Enable…Repositories annotations that support the limitImplementationBasePackages parameter to scan in repository base packages for custom implementations:

@EnableJpaRepositories(limitImplementationBasePackages = false)
@Configuration
class AppConfiguration {
  // …
}

Declaring the implementation along with the interface in the same package is an established design pattern allowing to limit the scanning scope. A limited scope improves scanning performance as it can skip elements on the classpath, that do not provide that particular package.

Previously, we scanned for implementations using the configured base packages that were also used to discover repository interfaces. These base packages can be broader for applications that spread repository interfaces across multiple packages.
2017-09-27 16:09:11 +02:00
Jens Schauder
79709629ef DATACMNS-1177 - Parameter.isDynamicProjectionParameter() now uses unwrapped type instead of actual type.
When trying to determine if a parameter is a dynamic projection parameter, i.e. the parameter of type Class that determines the projection to use, now the type parameter of that method parameter gets compared with the unwrapped return type. Therefore this works now not only for Maps and Collections but also for the various wrappers defined in QueryExecutionConverters.

Moved the method for unwrapping the return type from AbstractRepositoryMetadata to QueryExecutionConverters in order to make it available to every class needing it. This also puts it closer to the data it is working on.

Original pull request: #250.
2017-09-27 11:40:55 +02:00
Mark Paluch
2b4ef1a555 DATACMNS-1175 - Remove argument array caching from EntityInstantiators.
We no longer cache argument arrays in our EntityInstantiators to prevent changes to shared mutable state caused by reentrant calls.

Previously, a re-entrant call requesting an argument array of the same size as a previous call in the call stack reused the same array instance. Changes to this shared mutable state by multiple invocations caused an invalid state rendering wrong parameters for object instantiation. Removing the caching and only reusing an empty array for zero-arg constructors is the only safe approach for now.

Re-instantiation of object allocations results in a higher GC pressure but guarantee side effect-free instantiation and should be on-par with previous versions performance profile.

Original pull request: #247.
2017-09-27 10:55:34 +02:00
Mark Paluch
cc0ab54c38 DATACMNS-1171 - Do not create PersistentEntity for unsupported Kotlin classes.
We now reject unsupported Kotlin classes from the MappingContext by default by not creating persistent entities.

Original pull request: #245.
2017-09-25 12:23:35 +02:00
Mark Paluch
d9d0d594e5 DATACMNS-1171 - Limit Kotlin reflection support to regular classes.
We now only inspect regular Kotlin classes with inspection to adapt Kotlin-specific behavior. Multipart-, synthetic and unknown classes are not supported. In such cases we fall back to the JVM reflection mechanism.

Non-regular classes are typically synthetic stubs, lambdas and SAM conversion which do not represent typical domain objects but rather technical bridge code.

Original pull request: #245.
2017-09-25 12:23:30 +02:00
Oliver Gierke
65e21344ac DATACMNS-1173 - Fixed value lookup of AnnotationRevisionMetadata.
Fixed handling of absent values. Minor refactorings. More unit tests.
2017-09-25 09:56:31 +02:00
Jens Schauder
ea03388a7c DATACMNS-1161 - Renamed PersistentProperty.getPersitentEntityType(…) to ….getPersitentEntityTypes(…).
The new name currently delegates to old version, so classes only implementing the old method still work. Old name is deprecated.

Original pull request: #243.
2017-09-21 17:46:28 +02:00
Oliver Gierke
404610ebb4 DATACMNS-1168 - QuerydslPredicateBuilder now returns empty predicate by default. 2017-09-21 16:23:40 +02:00
Mark Paluch
fcf97e1e71 DATACMNS-1157 - Enforce nullable/non-null API constraints on repository query methods.
We now validate query method invocations to check method parameters whether they accept null values and reject execution if null values are not supported. We derive nullability support from repository interfaces declared using Kotlin and Spring's NonNullApi/Nullable annotations.

We also check whether a query method can return null. If a query method returns null which isn't supposed to do so, then we throw EmptyResultDataAccessException to prevent null return values.

interface UserRepository extends Repository<User, String> {

  List<User> findByLastname(@Nullable String firstname);

  @Nullable
  User findByFirstnameAndLastname(String firstname, String lastname);
}

interface UserRepository : Repository<User, String> {

  fun findByLastname(username: String?): List<User>

  fun findByFirstnameAndLastname(firstname: String, lastname: String): User?
}

Original pull request: #241.
2017-09-21 10:23:47 +02:00
Oliver Gierke
e7ae4a8bb8 DATACMNS-1165 - Added support for Streamable as repository return type.
We now allow users to use our own Streamable interface as query method return types to easily invoke ….stream() on everything that returns an Iterable using non-parallel streaming by default.
2017-09-20 16:31:29 +02:00
Oliver Gierke
1a199847cd DATACMNS-1162 - Improved support for immutable aggregates.
AbstractAggregateRoot is now generified to be able to use its concrete type on methods returning an instance of itself. Added new methods andEvent(…) and andEventsFrom(…) to easily transfer events from another aggregate instance. Added unit tests for fundamental functionality of the base class.
2017-09-20 11:45:37 +02:00
Oliver Gierke
72b927ea2c DATACMNS-1163 - EventPublishingInterceptor now prefers arguments over return values for event publication.
We now prefer to inspect the arguments handed to save(…) methods over inspecting the return value as the invocation of the actual method is free to exchange the instance handed into it and return a completely new one with the events contained in the parameter completely wiped.
2017-09-20 11:09:25 +02:00
Mark Paluch
a8cc4783bf DATACMNS-1159 - Upgrade to OpenWebBeans 2.0.1. 2017-09-18 15:05:47 +02:00
Oliver Gierke
2cfd6b8966 DATACMNS-1152 - Setup of ProjectingJackson2HttpMessageConverter now tries to use unique ObjectMapper from ApplicationContext.
We're now trying to look up a uniquely available ObjectMapper instance from the application context falling back to a simple new instance in case none can be found.
2017-09-06 17:11:51 +02:00
Oliver Gierke
4b323eca11 DATACMNS-1150 - Projection methods with SpEL expressions can now use method parameters.
We now forward method parameters of methods on projection interfaces to the expression evaluation. The parameters are exposed via an array named "args".
2017-09-04 19:15:04 +02:00
Mark Paluch
3a2b6b601b DATACMNS-1141 - Add missing NonNullApi and Nullable annotations.
Add Nullable annotation to ParsingUtils, Sort.Order and PropertyValueProvider.

Add getRequiredAnnotation(…) to PersistentEntity and PersistentProperty to provide methods returning required, non-null annotations.
2017-08-28 13:32:15 +02:00
Mark Paluch
d657b17e74 DATACMNS-1147 - Do not consider @NoRepositoryBean interfaces as fragment interfaces.
We filter interfaces annotated with @NoRepositoryBean from fragment interface candidates and not longer scan for implementations of these.

Extending a base repository usually requires an interface which is used as base interface instead of Repository/CrudRepository in user repositories. If the naming scheme of the extended interface and the implementation fits to fragment interfaces, then we previously registered the class additionally as fragment implementation. The bean registration caused container startup failures because of unsatisfied dependencies or would shadow the base repository implementation.

Original pull request #239.
2017-08-28 12:54:17 +02:00
Mark Paluch
22b37800ec DATACMNS-1126 - Add class-generating entity instantiation support for Kotlin.
We now discover Kotlin constructors and apply parameter defaulting to allow construction of immutable value objects. Constructor discovery uses primary constructors by default and considers PersistenceConstructor annotations.

KotlinClassGeneratingEntityInstantiator can instantiate Kotlin classes with default parameters by resolving the synthetic constructor. Null values translate to parameter defaults.

class Person(val firstname: String = "Walter") {
}

class Address(val street: String, val city: String) {

	@PersistenceConstructor
	constructor(street: String = "Unknown", city: String = "Unknown", country: String) : this(street, city)
}

Original pull request: #233.
2017-08-25 13:04:28 +02:00
Oliver Gierke
d018757995 DATACMNS-1144 - @JsonPath now supports multiple path expressions.
Path expressions are now evaluated one by one with the first one actually available in the payload being used for value lookup. Also tweaked the default behavior to return null in case of an single, invalid path.
2017-08-24 12:56:19 +02:00
Oliver Gierke
fb9d38d79c DATACMNS-1139 - AbstractPersistentProperty.getRawType() now correctly resolves generics.
We're now favoring the generic TypeInformation over trying to resolve the property type via field or PropertyDescriptor as only the former does proper generic type resolution.
2017-08-14 14:06:16 +02:00
Oliver Gierke
fab854c906 DATACMNS-1138 - TypeInformation.specialize(…) now only specializes unresolved parameterized types.
Type specialization - i.e. enrichment of a raw type with a current generic context - is now only done if the current type is not yet resolved completely. This allows wildcarded target references to just fall back to the type to specialize, which will then by definition carry more generics information than the one to be specialized.
2017-08-11 16:15:54 +02:00
Oliver Gierke
756396a065 DATACMNS-1135 - Fixed generics lookup for recursively nested container references.
Revert the merging of a parent type's type variable map and only apply the locally available declared generics in case of parameterized types. Moved that augmentation into ParameterizedTypeInformation.
2017-08-03 15:39:54 +02:00
Oliver Gierke
6f44a40ecb DATACMNS-1129 - Polishing.
Formatting.
2017-07-25 13:52:16 +02:00
Oliver Gierke
7960786083 DATACMNS-1129 - A PartTree is now an empty iterable if no predicate is given. 2017-07-25 13:52:16 +02:00
Oliver Gierke
af56889e72 DATACMNS-1123 - Upgraded to XmlBeam 1.4.12 and tweaked HttpMessageConverter implementation.
XmlBeam 1.4.11 accidentally removed ProjectionFactory as public interface. Adapted our HttpMessageConverter implementation to make sure we still work on those versions.

Related ticket: https://github.com/SvenEwald/xmlbeam/issues/45
2017-07-24 14:17:36 +02:00
Oliver Gierke
049970874d DATACMNS-1114 - Introduced usage of nullable annotations for API validation.
Marked all packages with Spring Frameworks @NonNullApi. Added Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fixed Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances.

Removed null handling from converters for JodaTime and ThreeTenBP. Introduced factory methods Page.empty() and Page.empty(Pageable). Introduced default methods getRequiredGetter(), …Setter() and …Field() on PersistentProperty to allow non-nullable lookups of members. The same for TypeInformation.getrequiredActualType(), …SuperTypeInformation().

Tweaked PersistentPropertyCreator.addPropertiesForRemainingDescriptors() to filter unsuitable PropertyDescriptors before actually trying to create a Property instance from them as the new stronger nullability requirements would cause exceptions downstream.

Lazy.get() now expects a non-null return value. Clients being able to cope with null need to call ….orElse(…).

Original pull request: #232.
2017-07-24 10:47:28 +02:00
Mark Paluch
86945f81d1 DATACMNS-1122 - Improve message for absent required property in PersistentEntity.getRequiredPersistentProperty(…).
Exception message now contains the property name.
2017-07-21 08:54:39 +02:00
Oliver Gierke
51f099306d DATACMNS-1121 - ProxyProjectionFactory now returns instance as is if it implements the target.
If you previously asked ProxyProjectionFactory for a proxy of an interface which the target instance already implements, it created a proxy although it could've returned the instance as is. It's now actually doing that avoiding superfluous proxy creation.
2017-07-20 14:29:54 +02:00
Oliver Gierke
5e4cac308e DATACMNS-1120 - Introduced caching of PropertyPath instances. 2017-07-20 13:38:43 +02:00
Oliver Gierke
7ee5ae446b DATACMNS-1117 - Fixed creation of RepositoryInformation in RepositoryFactoryBeanSupport.
RepositoryFactoryBeanSupport.getRepositoryInformation() previously didn't consider any store-specific compositions (incl. store-specific fragments like the Querydsl support) as it just handed a fragment with the custom implementation to RepositoryFactorySupport.

This is now fixed by improving the API in RepositoryFactorySupport which now exposes a getRepositoryInformation(RepositoryMetadata, RepositoryFragments) which creates a fresh RepositoryComposition from the given RepositoryMetadata. Intermediate setup methods are still kept around but private as RepositoryFactorySupport.getRepository(…) still needs to forward the base RepositoryComposition to method interceptors for query result mapping.
2017-07-20 10:14:57 +02:00
Oliver Gierke
dfcb9f77a4 DATACMNS-1116 - AbstractMappingContext now caches PersistentPropertyPaths.
As the calculation of a PersistentPropertyPath instances is rather expensive and they're heavily used in downstream mapping operations (e.g. query and fields mapping in MongoDB) we now cache the instances created per base type and property path.
2017-07-19 13:45:41 +02:00
Oliver Gierke
d692702663 DATACMNS-1115 - Improve RepositoryBeanNameGenerator to properly resolve bean names for indexed BeanDefinitions.
Previously, RepositoryBeanNameGenerator applied the custom bean name lookup if the BeanDefinition given was not a ScannedGenericBeanDefinition. That in turn had been the case for custom implementation classes that were obtained through classpath scanning. With Spring 5 an index file can be used by the scanner, which in turn will cause AnnotatedGenericBeanDefinition instances being returned. That caused the code path to lookup the first constructor argument to kick in (usually used to obtain the repository interface from repository factory beans) and cause a NullPointerException.

We now forward AnnotatedBeanDefinitions as is and only apply the custom lookup for everything else, i.e. the bean definitions used for the factories.
2017-07-19 01:28:58 +02:00
Oliver Gierke
6a6d995eab DATACMNS-1109 - Reinstantiate support for all date/time APIs in auditing.
Re-enabled test cases for handling of different date/time APIs in auditing. Tweaked the lookup of the last modified value to try to convert to LocalDateTime as well in case it's a subtype of the type requested. In combination with two newly introduced converters for local date type times in JodaTime and ThreeTenBP, this allows us to still convert legacy JodaTime and ThreeTenBP types to be used as well.
2017-07-12 19:17:23 +02:00
Oliver Gierke
d4b79ea8f2 DATACMNS-1112 - Cache instances of ReturnedType to avoid repeated reflection inspection.
We now keep instances of ReturnedType around to avoid the repeated reflection inspection for constructor and parameter name detection for class types and projection information for interfaces.
2017-07-12 17:09:39 +02:00
Oliver Gierke
8026e9ff72 DATACMNS-1106 - Removed deprecations in ProjectionFactory.
Removed the deprecated implementation of ResourceLoaderAware in favor of BeanClassLoaderAware. Removed deprecated ProjectionFactory.getInputProperties() in favor of ….getProjectionInformation(). Removed the Java conditional to add a MethodInterceptor for default methods. Adapted test cases.
2017-07-11 11:18:18 +02:00
Jens Schauder
1fc25727cf DATACMNS-1097 - Move classes to better matching packages.
Introduced new ExampleMatcherAccessor in data.support in favor of the now deprecated one in data.repository.core to avoid a dependency into the repositories subsystem to work with examples in general.

Added Degraph based test in order to avoid future cyclic package dependency violations.

Original pull request: #230.
Related ticket: DATAMONGO-1721.
2017-07-06 11:38:12 +02:00
Oliver Gierke
f44255b9a8 DATACMNS-1102 - Reuse ConversionService in ProjectingMethodInterceptors created by ProxyProjectionFactory.
Applied the same to internals of MapDataBinder.
2017-07-05 09:41:21 +02:00
Mark Paluch
3dbbb15672 DATACMNS-1101 - Use dedicated type to cache custom conversion targets without requested target type.
We now use a marker interface to store cache hits for conversion targets without requesting a conversion target in the conversion query. The dedicated marker type has an individual cache view and does not interfere with other types.

Previously we used Object as cache key which caused false positives due to assignability checks. If an earlier conversion query with a requested target type yielded a hit (e.g. negative hit), subsequent queries without a target type received the same answer. This might happen although the non-cached answer would return a different result.
2017-07-04 14:30:45 +02:00
Christoph Strobl
f6a6565638 DATACMNS-1101 - Remove getPersistentProperties/Associations from PersistentEntity.
Remove lately introduced getPersistentProperties / getAssociations and rather extend Iterable<? extends PersistentProperty<P>>
2017-07-04 14:30:45 +02:00