java.lang.IllegalStateException is thrown by invoking findBy method
java.lang.IllegalStateException: No MethodInvocation found: Check that an AOP invocation is in progress, and that the CrudMethodMetadataPopulatingMethodInterceptor is upfront in the interceptor chain.
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.currentInvocation(CrudMethodMetadataPostProcessor.java:123)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$ThreadBoundTargetSource.getTarget(CrudMethodMetadataPostProcessor.java:294)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:229)
at jdk.proxy2/jdk.proxy2.$Proxy100.getLockModeType(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.applyRepositoryMethodMetadata(SimpleJpaRepository.java:845)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:756)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.lambda$doFindBy$2(SimpleJpaRepository.java:521)
at org.springframework.data.jpa.repository.support.FetchableFluentQueryBySpecification.createSortedAndProjectedQuery(FetchableFluentQueryBySpecification.java:183)
at org.springframework.data.jpa.repository.support.FetchableFluentQueryBySpecification.stream(FetchableFluentQueryBySpecification.java:166)
at findby.FindByTests.findBy(FindByTests.java:30)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Here is test case:
package findby;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.jpa.domain.AbstractPersistable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.test.context.ContextConfiguration;
import jakarta.persistence.Entity;
@DataJpaTest
@EnableJpaRepositories(basePackageClasses = FindByTests.TestEntityRepository.class, considerNestedRepositories = true)
@EntityScan(basePackageClasses = FindByTests.TestEntity.class)
@ContextConfiguration(classes = FindByTests.class)
class FindByTests {
@Autowired
TestEntityRepository repository;
@Test
void findBy() {
// will throw java.lang.IllegalStateException: No MethodInvocation found
repository.findBy((root, query, cb) -> null, Function.identity()).stream();
}
@Test
void findByInDefaultMethod() {
// works fine
repository.findByInDefaultMethod();
}
interface TestEntityRepository extends JpaRepository<TestEntity, Long>, JpaSpecificationExecutor<TestEntity> {
default Stream<TestEntity> findByInDefaultMethod() {
return findBy((root, query, cb) -> null, Function.identity()).stream();
}
}
@Entity
static class TestEntity extends AbstractPersistable<Long> {
}
}
with
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.1'
id 'io.spring.dependency-management' version 'latest.release'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'com.h2database:h2'
}
tasks.named('test') {
useJUnitPlatform()
}
I also ecountered this using "org.springframework.boot:spring-boot-starter-data-mongodb"
Thank you @quaff for reporting and adding the test snippet. The current behaviour, though unintuitive, is the expected one. The findBy method in this case exposes the FetchableFluentQuery outside the repository. So when the stream invocation happens the context is already gone.
We're considering to enhance the current flow so that we capture method metadata early and can provide it later on in this scenario.
Meanwhile you can try it this way repository.findBy((root, query, cb) -> null, FetchableFluentQuery::stream).
Meanwhile you can try it this way
repository.findBy((root, query, cb) -> null, FetchableFluentQuery::stream).
Thanks, it works, does the document mention such limitation?
Unfortunately not, all samples are using one of the terminating (one, first, all,...) methods.