Skip to content

Commit 3b667b9

Browse files
Update documentation and fix nullable annotations.
Original Pull Request: #3093
1 parent 658c04d commit 3b667b9

File tree

5 files changed

+49
-15
lines changed

5 files changed

+49
-15
lines changed

Diff for: src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc

+36-8
Original file line numberDiff line numberDiff line change
@@ -296,24 +296,52 @@ class DefaultSearchExtension<T> implements SearchExtension<T> {
296296
----
297297
====
298298

299-
In the snipped above we use `RepositoryMethodMetadata.get()` to get hold of metadata for the actual method invocation. In doing so we can access additional information attached to the repository. In this case we use the repositories domain type to identify the name of the index to be searched.
299+
In the snipped above we use `RepositoryMethodContext.currentMethod()` to get hold of metadata for the actual method invocation. In doing so we can access additional information attached to the repository. In this case we use the repositories domain type to identify the name of the index to be searched.
300+
301+
Now that we've got both, the fragments declaration and implementation we can register it in the `META-INF/spring.factories` file, package things up if needed and we're almost good to go.
300302

301-
[TIP]
302303
====
303-
For testing you can use `TransactionSynchronizationManager.bindResource(RepositoryMethodMetadata.class, metadata)` to provide repository method metadata.
304+
[source,properties]
305+
----
306+
com.acme.search.SearchExtension=com.acme.search.DefaultSearchExtension
307+
----
304308
====
305309

306-
Now that we've got both, the fragments declaration and implementation we can register it in the `META-INF/spring.factories` file, package things up if needed and we're good to go.
310+
Since we're using additional metadata, that comes with additional cost, via `RepositoryMethodContext.currentMethod()` we need to advise the repository factory responsible for creating the actual repository to expose method metadata by setting the `exposeMetadata` flag.
307311

308312
====
309-
[source,properties]
313+
[source,java]
310314
----
311-
com.acme.search.SearchExtension=com.acme.search.DefaultSearchExtension
315+
import org.springframework.beans.factory.config.BeanPostProcessor;
316+
import org.springframework.context.annotation.Configuration;
317+
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
318+
import org.springframework.lang.Nullable;
319+
320+
@Configuration
321+
class Cfg implements BeanPostProcessor {
322+
323+
@Bean
324+
public BeanPostProcessor exposeMethodMetadata() {
325+
326+
return new BeanPostProcessor() {
327+
328+
@Override
329+
public Object postProcessBeforeInitialization(Object bean, String beanName) {
330+
331+
if(bean instanceof RepositoryFactoryBeanSupport<?,?,?> factoryBean) {
332+
factoryBean.setExposeMetadata(true);
333+
}
334+
}
335+
};
336+
}
337+
}
312338
----
339+
The above snippet outlines how to set the `exposeMetadata` flag using a `BeanPostProcessor`.
340+
Please do not just copy/paste the above but think about your actual use case which may require a more fine grained approach as the above will simply enable the flag on each and every repository. You may want to have a look at our https://github.com/spring-projects/spring-data-examples/tree/main/bom[spring-data-examples] project to draw inspiration.
313341
====
314342

315-
To make use of the extension simply add the interface to the repository as shown below.
316-
The infrastructure will take care placing the required `RepositoryMethodContext` so all that
343+
Now we are ready to make use of the extension.
344+
Simply add the interface to the repository.
317345

318346
====
319347
[source,java]

Diff for: src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryMethodContext.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*
2727
* @author Christoph Strobl
2828
* @author Mark Paluch
29+
* @since 3.4.0
2930
*/
3031
class DefaultRepositoryMethodContext implements RepositoryMethodContext {
3132

@@ -39,18 +40,19 @@ class DefaultRepositoryMethodContext implements RepositoryMethodContext {
3940
private final RepositoryMetadata repositoryMetadata;
4041
private final Method method;
4142

42-
public DefaultRepositoryMethodContext(RepositoryMetadata repositoryMetadata, Method method) {
43+
DefaultRepositoryMethodContext(RepositoryMetadata repositoryMetadata, Method method) {
44+
4345
this.repositoryMetadata = repositoryMetadata;
4446
this.method = method;
4547
}
4648

4749
@Nullable
48-
public static RepositoryMethodContext getMetadata() {
50+
static RepositoryMethodContext getMetadata() {
4951
return currentMethod.get();
5052
}
5153

5254
@Nullable
53-
public static RepositoryMethodContext setMetadata(@Nullable RepositoryMethodContext metadata) {
55+
static RepositoryMethodContext setMetadata(@Nullable RepositoryMethodContext metadata) {
5456

5557
RepositoryMethodContext old = currentMethod.get();
5658
if (metadata != null) {

Diff for: src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ public void setRepositoryBaseClass(Class<?> repositoryBaseClass) {
115115
* <p>
116116
* Default is "false", in order to avoid unnecessary extra interception. This means that no guarantees are provided
117117
* that {@code RepositoryMethodContext} access will work consistently within any method of the advised object.
118+
*
119+
* @since 3.4.0
118120
*/
119121
public void setExposeMetadata(boolean exposeMetadata) {
120122
this.exposeMetadata = exposeMetadata;

Diff for: src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import org.aopalliance.intercept.MethodInvocation;
3131
import org.apache.commons.logging.Log;
3232
import org.apache.commons.logging.LogFactory;
33-
import org.jetbrains.annotations.NotNull;
34-
3533
import org.springframework.aop.framework.ProxyFactory;
3634
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
3735
import org.springframework.beans.BeanUtils;
@@ -129,8 +127,10 @@ public RepositoryFactorySupport() {
129127
* retrieval via the {@code RepositoryMethodContext} class. This is useful if an advised object needs to obtain
130128
* repository information.
131129
* <p>
132-
* Default is "false", in order to avoid unnecessary extra interception. This means that no guarantees are provided
130+
* Default is {@literal "false"}, in order to avoid unnecessary extra interception. This means that no guarantees are provided
133131
* that {@code RepositoryMethodContext} access will work consistently within any method of the advised object.
132+
*
133+
* @since 3.4.0
134134
*/
135135
public void setExposeMetadata(boolean exposeMetadata) {
136136
this.exposeMetadata = exposeMetadata;
@@ -665,7 +665,8 @@ public ExposeMetadataInterceptor(RepositoryMetadata repositoryMetadata) {
665665

666666
@Nullable
667667
@Override
668-
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
668+
public Object invoke(MethodInvocation invocation) throws Throwable {
669+
669670
RepositoryMethodContext oldMetadata = null;
670671
try {
671672
oldMetadata = RepositoryMethodContext

Diff for: src/main/java/org/springframework/data/repository/core/support/RepositoryMethodContext.java

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
*
3636
* @author Christoph Strobl
3737
* @author Mark Paluch
38+
* @since 3.4.0
3839
*/
3940
public interface RepositoryMethodContext {
4041

0 commit comments

Comments
 (0)