You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm not sure if there is an easy way to reproduce the issue since I don't face it in a local environment but this error always come up in k8s environment. Here are probable steps that cause it:
Steps to reproduce the behaviour:
Try to fetch entities by id with method findAllById (probably with a long list of ids, but not sure if length of the list matters) in repository component with defaultEntityGraph overridden and EntityGraphJpaRepository interface implemented in async manner. To be more precise I use Netflix DGS and it's entity fetchers which use ForkJoinPools under the hood to parallel requests to backend services, as far as I know.
What is the expected output ?
The request to database is executed with no issues.
What happens instead ?
The error is faced:
j.l.IllegalArgumentException: org.hibernate.query.hql.spi.SqmQueryImplementor referenced from a method is not visible from class loader
at j.l.r.Proxy$ProxyBuilder.ensureVisible(Unknown Source)
at j.l.r.Proxy$ProxyBuilder.validateProxyInterfaces(Unknown Source)
at j.l.r.Proxy$ProxyBuilder.<init>(Unknown Source)
at j.lang.reflect.Proxy.lambda$getProxyConstructor$1(Unknown Source)
at j.i.l.AbstractClassLoaderValue$Memoizer.get(Unknown Source)
at j.i.l.AbstractClassLoaderValue.computeIfAbsent(Unknown Source)
at j.lang.reflect.Proxy.getProxyConstructor(Unknown Source)
at j.lang.reflect.Proxy.newProxyInstance(Unknown Source)
at o.s.a.f.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:123)
at o.s.a.f.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:115)
at o.s.a.f.ProxyFactory.getProxy(ProxyFactory.java:97)
at c.c.s.d.j.e.g.r.s.RepositoryQueryEntityGraphInjector.proxy(RepositoryQueryEntityGraphInjector.java:37)
at c.c.s.d.j.e.g.r.s.RepositoryEntityManagerEntityGraphInjector.invoke(RepositoryEntityManagerEntityGraphInjector.java:70)
at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at o.s.a.f.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
at j.proxy2.$Proxy218.createQuery(Unknown Source)
at o.s.d.j.r.s.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:755)
at o.s.d.j.r.s.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:733)
at o.s.d.j.r.s.SimpleJpaRepository.findAllById(SimpleJpaRepository.java:408)
at j.i.r.NativeMethodAccessorImpl.invoke0(Unknown Source)
at j.i.r.NativeMethodAccessorImpl.invoke(Unknown Source)
at j.i.r.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at j.l.reflect.Method.invoke(Unknown Source)
at o.s.d.r.c.s.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288)
at o.s.d.r.c.s.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
at o.s.d.r.c.s.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
at o.s.d.r.c.s.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
at o.s.d.r.c.s.RepositoryComposition.invoke(RepositoryComposition.java:285)
at o.s.d.r.c.s.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
... 10 frames truncated
... 39 common frames omitted\nWrapped by: o.s.d.InvalidDataAccessApiUsageException: org.hibernate.query.hql.spi.SqmQueryImplementor referenced from a method is not visible from class loader
at o.s.o.j.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
at o.s.o.j.v.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:234)
at o.s.o.j.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
at o.s.d.s.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at o.s.d.s.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at o.s.d.s.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at c.c.s.d.j.e.g.r.s.RepositoryMethodInvocation.proceed(RepositoryMethodInvocation.java:23)
at c.c.s.d.j.e.g.r.s.EntityGraphQueryHintCandidates.doInvoke(EntityGraphQueryHintCandidates.java:96)
at c.c.s.d.j.e.g.r.s.EntityGraphQueryHintCandidates.invoke(EntityGraphQueryHintCandidates.java:60)
at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at o.s.d.j.r.s.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164)
at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at o.s.a.i.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
Environment
Spring Data JPA version (not the Spring Boot one): 3.1.2
Hey, just an FYI as this came up for myself. Its not kubernetes, its within a docker container, so I was able to recreate this in an unrelated project locally.
I believe this is fixed by the following answer on stackoverflow:
which in turn depends on the following solution in creating a ForkJoinerWorkerThreadFactory and propagating the correct class loader to the other thread.
public class MyForkJoinWorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory {
@Override
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new MyForkJoinWorkerThread(pool);
}
private static class MyForkJoinWorkerThread extends ForkJoinWorkerThread {
private MyForkJoinWorkerThread(final ForkJoinPool pool) {
super(pool);
// set the correct classloader here
setContextClassLoader(Thread.currentThread().getContextClassLoader());
}
}
}
Delcare custom executor:
@Bean(name = "customExecutor")
public Executor customExecutor() {
MyForkJoinWorkerThreadFactory factory = new MyForkJoinWorkerThreadFactory();
ForkJoinPool myCommonPool = new ForkJoinPool(Math.min(32767, Runtime.getRuntime().availableProcessors()), factory, null, false);
return new DelegatingSecurityContextExecutor(myCommonPool, SecurityContextHolder.getContext());
}
At that point the usage of data loader should use the customExecutor bean
@Bean(name = "myDataLoader")
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public DataLoader<Object, Object> myDataLoader(@Qualifier("customExecutor") Executor customExecutor) {
return DataLoaderFactory.newDataLoader(myValue -> {
CompletableFuture.supplyAsync(() -> {
return 1L; // perform the actual work causing the exception here
}, customExecutor));
}):
What steps will reproduce the problem ?
I'm not sure if there is an easy way to reproduce the issue since I don't face it in a local environment but this error always come up in k8s environment. Here are probable steps that cause it:
Steps to reproduce the behaviour:
findAllById
(probably with a long list of ids, but not sure if length of the list matters) in repository component withdefaultEntityGraph
overridden andEntityGraphJpaRepository
interface implemented in async manner. To be more precise I use Netflix DGS and it's entity fetchers which use ForkJoinPools under the hood to parallel requests to backend services, as far as I know.What is the expected output ?
The request to database is executed with no issues.
What happens instead ?
The error is faced:
Environment
Link to an automated test demonstrating the problem
No luck to create a test or provide environment to reproduce it.
Additional context
I talked with guys from spring boot and they gave me some places worth to look at: spring-projects/spring-boot#37474
The text was updated successfully, but these errors were encountered: