Skip to content

@Meta annotation not working properly with MongoRepository and custom repositories #4852

Open
@malaquf

Description

@malaquf

Environment:
Kotlin with coroutines 2.1.0
Spring Boot 3.3.1

Problem
When adding a @meta annotation to my queries in a given repository, I get empty lists as result.

Unfortunately, I could not find the root cause yet, but I hope the following description helps to reproduce it.

CrudMethodMetadataPopulatingMethodInterceptor checks if a method is a query using isQueryMethod(). Because @meta adds @QueryAnnotation, the method is not added to Set<Method> implementations.

Surprisingly, query methods defined in repositories by default are added to Set<Method> implementations from CrudMethodMetadataPopulatingMethodInterceptor, and everything works fine when not adding the @meta annotation.

The difference I see so far is in the execution path for the query in the following method:

@Override
		public Object invoke(MethodInvocation invocation) throws Throwable {

			Method method = invocation.getMethod();

			if (!implementations.contains(method)) {
				return invocation.proceed();
			}

			MethodInvocation oldInvocation = currentInvocation.get();
			currentInvocation.set(invocation);

			try {

				CrudMethodMetadata metadata = (CrudMethodMetadata) TransactionSynchronizationManager.getResource(method);

				if (metadata != null) {
					return invocation.proceed();
				}

				CrudMethodMetadata methodMetadata = metadataCache.get(method);

				if (methodMetadata == null) {

					methodMetadata = new DefaultCrudMethodMetadata(repositoryInformation.getRepositoryInterface(), method);
					CrudMethodMetadata tmp = metadataCache.putIfAbsent(method, methodMetadata);

					if (tmp != null) {
						methodMetadata = tmp;
					}
				}

				TransactionSynchronizationManager.bindResource(method, methodMetadata);

				try {
					return invocation.proceed();
				} finally {
					TransactionSynchronizationManager.unbindResource(method);
				}
			} finally {
				currentInvocation.set(oldInvocation);
			}
		}
	}

When adding @meta annotation, my query is executed through invocation.proceed() within if (!implementations.contains(method)) block. If @meta is not present, the execution is done by the rest of the code.

Repository example:

interface MyRepository : ReactiveMongoRepository<MyDocument, MyKey> {

	@Meta(maxExecutionTimeMs = 30000)
	override fun findAllById(ids: Iterable<MyKey>): Flux<MyDocument>

	@Meta(maxExecutionTimeMs = 30000)
	override fun findById(id: MyKey): Mono<MyDocument>
}

I'll update the issue if I have more information.

By the way, all I want in this case is to define maxExecutionTimeMs for my queries and I believe there should be a better way to customise it (and specially set a default) without having to define it for each method in the repository. Like having an interceptor for easily extending the Query options, for example.

Thank you for looking into it.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions