Add RepositoryMetadataAccess.
Repositories that detect fragment implementations implementing RepositoryMetadataAccess enable metadata exposure regardless of the exposeMetadata flag. See: #3090 Original Pull Request: #3145
This commit is contained in:
committed by
Christoph Strobl
parent
b99db0cf01
commit
f7895eb306
@@ -127,10 +127,16 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
* retrieval via the {@code RepositoryMethodContext} class. This is useful if an advised object needs to obtain
|
||||
* repository information.
|
||||
* <p>
|
||||
* Default is {@literal "false"}, in order to avoid unnecessary extra interception. This means that no guarantees are provided
|
||||
* that {@code RepositoryMethodContext} access will work consistently within any method of the advised object.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* Default is {@literal "false"}, in order to avoid unnecessary extra interception. This means that no guarantees are
|
||||
* provided that {@code RepositoryMethodContext} access will work consistently within any method of the advised
|
||||
* object.
|
||||
* <p>
|
||||
* Repository method metadata is also exposed if implementations within the {@link RepositoryFragments repository
|
||||
* composition} implement {@link RepositoryMetadataAccess}.
|
||||
*
|
||||
* @since 3.4
|
||||
* @see RepositoryMethodContext
|
||||
* @see RepositoryMetadataAccess
|
||||
*/
|
||||
public void setExposeMetadata(boolean exposeMetadata) {
|
||||
this.exposeMetadata = exposeMetadata;
|
||||
@@ -345,7 +351,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
result.addAdvice(new MethodInvocationValidator());
|
||||
}
|
||||
|
||||
if (this.exposeMetadata) {
|
||||
if (this.exposeMetadata || shouldExposeMetadata(fragments)) {
|
||||
result.addAdvice(new ExposeMetadataInterceptor(metadata));
|
||||
result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
}
|
||||
@@ -616,6 +622,16 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
return Lazy.of(() -> getProjectionFactory(this.classLoader, this.beanFactory));
|
||||
}
|
||||
|
||||
private static boolean shouldExposeMetadata(RepositoryFragments fragments) {
|
||||
|
||||
for (RepositoryFragment<?> fragment : fragments) {
|
||||
if (fragment.getImplementation().filter(RepositoryMetadataAccess.class::isInstance).isPresent()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method interceptor that calls methods on the {@link RepositoryComposition}.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.repository.core.support;
|
||||
|
||||
/**
|
||||
* Marker for repository fragment implementation that intend to access repository method invocation metadata.
|
||||
* <p>
|
||||
* Note that this is a marker interface in the style of {@link java.io.Serializable}, semantically applying to a
|
||||
* fragment implementation class rather. In other words, this marker applies to a particular repository composition that
|
||||
* enables metadata access for the repository proxy when the composition contain fragments implementing this interface.
|
||||
* <p>
|
||||
* Ideally, in a repository composition only the fragment implementation uses this interface while the fragment
|
||||
* interface does not.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.4
|
||||
* @see RepositoryMethodContext
|
||||
*/
|
||||
public interface RepositoryMetadataAccess {
|
||||
|
||||
}
|
||||
@@ -271,6 +271,27 @@ class RepositoryFactorySupportUnitTests {
|
||||
assertThat(metadata.methodInvocation().getMethod().getName()).isEqualTo("findMetadataByLastname");
|
||||
}
|
||||
|
||||
@Test // GH-3090
|
||||
void capturesRepositoryMetadataWithMetadataAccess() {
|
||||
|
||||
record Metadata(RepositoryMethodContext context, MethodInvocation methodInvocation) {
|
||||
}
|
||||
|
||||
when(factory.queryOne.execute(any(Object[].class)))
|
||||
.then(invocation -> new Metadata(RepositoryMethodContext.currentMethod(),
|
||||
ExposeInvocationInterceptor.currentInvocation()));
|
||||
|
||||
var repository = factory.getRepository(ObjectRepository.class, new RepositoryMetadataAccess() {});
|
||||
var metadataByLastname = repository.findMetadataByLastname();
|
||||
|
||||
assertThat(metadataByLastname).isInstanceOf(Metadata.class);
|
||||
|
||||
Metadata metadata = (Metadata) metadataByLastname;
|
||||
assertThat(metadata.context().getMethod().getName()).isEqualTo("findMetadataByLastname");
|
||||
assertThat(metadata.context().getRepository().getDomainType()).isEqualTo(Object.class);
|
||||
assertThat(metadata.methodInvocation().getMethod().getName()).isEqualTo("findMetadataByLastname");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-509, DATACMNS-1764
|
||||
void convertsWithSameElementType() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user