We now implement the newly introduced ImportBeanDefinitionRegistrar overload additional provided with a BeanNameGenerator configured for the import scanning. We forward this into our bean name generation infrastructure as fallback.
Related tickets: spring-projects/spring-framework#22591
We now expose a TypedSort that can use method handles to define properties to sort by.
Sort.sort(Person.class).by(Person::getName).ascending();
Related tickets: DATACMNS-1449.
Introduced MethodInvocationRecorder to record method invocations on types to obtain the property traversal those invocations represent.
Recorded<ZipCode> recorded = MethodInvocationRecorder.forProxyOf(Person.class)
.record(Person::getAddress)
.record(Address::getZipCode);
assertThat(recorded.getPropertyPath)).hasValue("address.zipCode");
We now explicitly check for the target type to be assignable to Streamable to opt into conversion. Without that check, every collection returned from a method declaring Iterable as return type would've been converted into a Streamable by accident.
Related ticket: DATACMNS-1430.
Various fast returns and the use of Class instead of TypeDescriptor led to e.g. List<BigDecimal> not getting properly converted to List<Integer> leading to unexpected ClassCastExceptions when the collection elements where accessed.
We now consider more than 16 immutable and nullable Kotlin properties per bucket in generated PropertyAccessors.
Previously only the first 16 properties were considered due to truncation of the defaulting bitmap. We used SIPUSH to render the defaulting mask in bytecode which is intended for 16 bit integers (short). Migrating to LDC (runtime constants) preserves the actual constant value of 32 bits and so we're considering now full buckets.
Extended copyright years. More reasonable defaults in the mock implementation of ImplementationDetectionConfiguration in case someone might want to reuse it in other test cases.
Original pull request: #325.
We now use Java Beans Introspector during default bean name derivation from class names. Previously, we used String.decapitalize(…) which decapitalizes always the first character. Java Beans do not decapitalize upper case sequences so a class name com.acme.UDPRepository translates to a bean name with UDPRepository instead of uDPRepository.
Original pull request: #325.
If multiple repositories pointing to a single domain type are found we now favor the one registered as primary bean definition. This allows allows reliable disambiguation on which repository is supposed to be used for generic repository interactions.
Related tickets: DATAREST-923.
Added Streamable.toStreamable() and ….toStreamable(Collector) to allow the creation of a Streamable from streams wither using a default List-based intermediate collector (former) or providing an explicit one (latter).
We now use StringUtils.hasLength(…) in the check whether to drop request elements from binding instead of ….hasText(…) as the latter drops blank strings so that's impossible to search for properties that contain a blank.
Extended IterableToStreamableConverter in use in QueryExecutionConverters so that it can not only return Streamable instances but also instances of types that have a factory method or constructor taking a Streamable (by making use of the ObjectToObjectConverter in a default ConversionService).
We now fall back to reflection-based PropertyAccessor/EntityInstantiator strategies when framework types are not visible by the entity's ClassLoader.
Typically, we use class generation to create and load PropertyAccessor and EntityInstantiator classes to bypass reflection. Generated types are injected into the ClassLoader that has loaded the actual entity. Generated classes implement framework types such as ObjectInstantiator and these interfaces must be visible to the ClassLoader that hosts the generated class. Some arrangements, such as OSGi isolate class repositories so the OSGi class loader cannot load our own types which prevents loading the generated class.
Original pull request: #324.
We now inspect all methods that match the wither method pattern (name, accepting a single argument) to find the most specific method returning the actual entity type.
Previously, we attempted to find a method only considering name and argument properties and not the return type. This lookup strategy could find a method returning the entity super type that isn't assignable to the entity type.
Original pull request: #323.
We now correctly calculate the number of defaulting masks used to represent constructor arguments. Previously, we've been one off which caused that Kotlin classes with 32/33 parameters weren't able to be instantiated.
We also now reuse KotlinDefaultMask to apply defaulting calculation and removed code duplicates.
We now use the primary constructor of Kotlin classes to discover the copy method. We use the primary constructor args to compare signatures and only use the copy method that takes all parameters in the constructor args order. This allows to find the appropriate copy method in case the class declares multiple copy methods.
We now also cache the copy method (KCallable) to reduce lookups in BeanWrapper.
Original pull request: #312.
We now avoid using a Lambda to provide a default ObjectMapper instance in the code that's reflectively guarded against Jackson not being present. The lambda causes a method to be generated for the class that will require ObjectMapper to be present on reflection inspection of that method. Switching to a method reference to ObjectMapper's constructor resolves that problem as the indirection via the additional, offending method is not needed.
Further reading: https://www.javabullets.com/how-lambdas-and-anonymous-inner-classesaic-work/
One of the constructors of Pageable wasn't properly checking for assignability of Pageable parameters to detect them but was expecting Pageable itself being used under all circumstances. This has now been opened up by an assignability check.
We now reject reactive repository metadata by RepositoryConfigurationExtensionSupport.useRepositoryConfiguration(…) assuming that Spring Data modules provide only imperative repository support by default. Reactive store modules are required to override useRepositoryConfiguration(…) anyway to not accidentally implement imperative repositories with a reactive Repository extension.
We now attempt to use private MethodHandles lookup as the first mechanism to resolve a MethodHandle for default interface methods and fall back to reflection-based Lookup construction if private lookup is not available. Reflective availability is checked lazily to prevent illegal access on enum constant construction. This approach prevents an illegal access which was logged by attempting a reflection-based lookup first.
We also introduced a FALLBACK mechanism to split encapsulated access from a fallback mechanism.
Original pull request: #307.
We now use Spring's ReflectUtils.defineClass(…) to load generated EntityInstantiators which uses internally either MethodHandles.Lookup.defineClass(…) (on Java 9 and higher) or reflective defineClass invocation on the originating ClassLoader. Class injection into the originating ClassLoader assigns the ClassLoader of the entity to the generated class which allows optimized instantiation of package-protected classes and constructors.
Original pull request: #308.
Previously, ConvertingPropertyAccessor did not override PersistentPropertyAccessor.setProperty(PersistentPropertyPath, Object), so that the target value had to be of the leaf property's type. We now implement that method and convert it into that type before invoking the super method.