Quarkus 无法加载 cassandra 自定义重试策略 class
Quarkus unable to load the cassandra custom retry policy class
我正在执行将 Quarkus 从 1.x 迁移到 2.x 的任务,而 Quarkus 与嵌入式 Cassandra 的集成在单元测试中失败并出现错误 -
原因:java.lang.IllegalArgumentException:找不到 class com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
(由 advanced.retry-policy.class 指定)
**Custom retry policy**
public class CassandraCustomRetryPolicy implements RetryPolicy {
public CassandraCustomRetryPolicy(DriverContext context, String profileName) {
}
//override methods
}
****quarkus test be like** -**
@QuarkusTest
@QuarkusTestResource(CassandraTestResource.class)
class Test {}
**CassandraTestResource class start the embedded cassandra**
public class CassandraTestResource implements QuarkusTestResourceLifecycleManager {
private Cassandra cassandra;
@Override
public Map<String, String> start() {
cassandra = new CassandraBuilder().version("3.11.9")
.addEnvironmentVariable("JAVA_HOME", getJavaHome())
.addJvmOptions("-Xms512M -Xmx512m").build();
cassandra.start();
}
我已经覆盖了资源文件夹内 application.conf 中的默认 Cassandra 驱动程序策略。
datastax-java-driver {
basic.request {
timeout = ****
consistency = ***
serial-consistency = ***
}
advanced.retry-policy {
class = com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
}
我发现我的自定义重试策略 class 在 QuarkusClassLoader.java-
中属于禁止资源
String resourceName = sanitizeName(name).replace('.', '/') + ".class";
boolean parentFirst = parentFirst(resourceName, state);
if (state.bannedResources.contains(resourceName)) {
throw new ClassNotFoundException(name);
}
我捕获了以下日志 -
java.lang.ClassNotFoundException: com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
在 io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:438)
在 io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:414)
在 java.base/java.lang.Class.forName0(本机方法)
在 java.base/java.lang.Class.forName(Class.java:315)
在 com.datastax.oss.driver.internal.core.util.Reflection.loadClass(Reflection.java:57)
在 com.datastax.oss.driver.internal.core.util.Reflection.resolveClass(Reflection.java:288)
在 com.datastax.oss.driver.internal.core.util.Reflection.buildFromConfig(Reflection.java:235)
在 com.datastax.oss.driver.internal.core.util.Reflection.buildFromConfig 配置文件(Reflection.java:194)
在 com.datastax.oss.driver.internal.core.context.DefaultDriverContext.buildRetryPolicies(DefaultDriverContext.java:359)
在 com.datastax.oss.driver.internal.core.util.concurrent.LazyReference.get(LazyReference.java:55)
在 com.datastax.oss.driver.internal.core.context.DefaultDriverContext.getRetryPolicies(DefaultDriverContext.java:761)
在 com.datastax.oss.driver.internal.core.session.DefaultSession$SingleThreaded.init(DefaultSession.java:339)
在 com.datastax.oss.driver.internal.core.session.DefaultSession$SingleThreaded.access$1100(DefaultSession.java:300)
在 com.datastax.oss.driver.internal.core.session.DefaultSession.lambda$init$0(DefaultSession.java:146)
在 io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98)
在 io.netty.util.concurrent.PromiseTask.run(PromiseTask.java:106)
在 io.netty.channel.DefaultEventLoop.run(DefaultEventLoop.java:54)
在 io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
在 io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
在 io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
在 java.base/java.lang.Thread.run(Thread.java:834)
我正在使用 quarkus 版本 2.7。2.Final 和 cassandra 驱动程序版本 4.14.0
这不是一个完整的答案,但我想在这里留下一些注释,以防其他人在我回到它之前完成它。
这里的根本问题是,在上述 Quarkus 测试用例中,Java 驱动程序代码由 QuarkusClassLoader 加载,其中 (a) 对从何处加载代码有更多限制,(b) 没有'如有必要,似乎不会立即支持调用它的父级。因此在这种情况下,在测试中执行以下操作将失败并出现 ClassNotFoundException:
CqlSession.class.getClassLoader().forName(customretrypolicyclassname)
而以下操作没有问题:
CqlSession.class.getClassLoader().getParent().forName(customretrypolicyclassname)
用于加载 CqlSession 的 class 加载器是 QuarkusClassLoader 实例,而它的父级是普通 JVM class 加载器。
Java 驱动程序 uses Class.forName() 加载为此策略指定的 classes。但是由于 Quarkus class 加载器用于加载驱动程序代码本身,它是用于这些反射操作的加载器......并且如上所述,该驱动程序具有一些使加载外部代码更难的特定特征。
在我像 -
一样初始化 CQL 会话后它起作用了
CqlSession.builder()
.addContactPoint(new InetSocketAddress(settings.getAddress(), settings.getPort()))
.withLocalDatacenter("***")
. withClassLoader(Thread.currentThread().getContextClassLoader()).build())
我正在执行将 Quarkus 从 1.x 迁移到 2.x 的任务,而 Quarkus 与嵌入式 Cassandra 的集成在单元测试中失败并出现错误 -
原因:java.lang.IllegalArgumentException:找不到 class com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy (由 advanced.retry-policy.class 指定)
**Custom retry policy**
public class CassandraCustomRetryPolicy implements RetryPolicy {
public CassandraCustomRetryPolicy(DriverContext context, String profileName) {
}
//override methods
}
****quarkus test be like** -**
@QuarkusTest
@QuarkusTestResource(CassandraTestResource.class)
class Test {}
**CassandraTestResource class start the embedded cassandra**
public class CassandraTestResource implements QuarkusTestResourceLifecycleManager {
private Cassandra cassandra;
@Override
public Map<String, String> start() {
cassandra = new CassandraBuilder().version("3.11.9")
.addEnvironmentVariable("JAVA_HOME", getJavaHome())
.addJvmOptions("-Xms512M -Xmx512m").build();
cassandra.start();
}
我已经覆盖了资源文件夹内 application.conf 中的默认 Cassandra 驱动程序策略。
datastax-java-driver {
basic.request {
timeout = ****
consistency = ***
serial-consistency = ***
}
advanced.retry-policy {
class = com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
}
我发现我的自定义重试策略 class 在 QuarkusClassLoader.java-
中属于禁止资源String resourceName = sanitizeName(name).replace('.', '/') + ".class";
boolean parentFirst = parentFirst(resourceName, state);
if (state.bannedResources.contains(resourceName)) {
throw new ClassNotFoundException(name);
}
我捕获了以下日志 -
java.lang.ClassNotFoundException: com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy 在 io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:438) 在 io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:414) 在 java.base/java.lang.Class.forName0(本机方法) 在 java.base/java.lang.Class.forName(Class.java:315) 在 com.datastax.oss.driver.internal.core.util.Reflection.loadClass(Reflection.java:57) 在 com.datastax.oss.driver.internal.core.util.Reflection.resolveClass(Reflection.java:288) 在 com.datastax.oss.driver.internal.core.util.Reflection.buildFromConfig(Reflection.java:235) 在 com.datastax.oss.driver.internal.core.util.Reflection.buildFromConfig 配置文件(Reflection.java:194) 在 com.datastax.oss.driver.internal.core.context.DefaultDriverContext.buildRetryPolicies(DefaultDriverContext.java:359) 在 com.datastax.oss.driver.internal.core.util.concurrent.LazyReference.get(LazyReference.java:55) 在 com.datastax.oss.driver.internal.core.context.DefaultDriverContext.getRetryPolicies(DefaultDriverContext.java:761) 在 com.datastax.oss.driver.internal.core.session.DefaultSession$SingleThreaded.init(DefaultSession.java:339) 在 com.datastax.oss.driver.internal.core.session.DefaultSession$SingleThreaded.access$1100(DefaultSession.java:300) 在 com.datastax.oss.driver.internal.core.session.DefaultSession.lambda$init$0(DefaultSession.java:146) 在 io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) 在 io.netty.util.concurrent.PromiseTask.run(PromiseTask.java:106) 在 io.netty.channel.DefaultEventLoop.run(DefaultEventLoop.java:54) 在 io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) 在 io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) 在 io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) 在 java.base/java.lang.Thread.run(Thread.java:834)
我正在使用 quarkus 版本 2.7。2.Final 和 cassandra 驱动程序版本 4.14.0
这不是一个完整的答案,但我想在这里留下一些注释,以防其他人在我回到它之前完成它。
这里的根本问题是,在上述 Quarkus 测试用例中,Java 驱动程序代码由 QuarkusClassLoader 加载,其中 (a) 对从何处加载代码有更多限制,(b) 没有'如有必要,似乎不会立即支持调用它的父级。因此在这种情况下,在测试中执行以下操作将失败并出现 ClassNotFoundException:
CqlSession.class.getClassLoader().forName(customretrypolicyclassname)
而以下操作没有问题:
CqlSession.class.getClassLoader().getParent().forName(customretrypolicyclassname)
用于加载 CqlSession 的 class 加载器是 QuarkusClassLoader 实例,而它的父级是普通 JVM class 加载器。
Java 驱动程序 uses Class.forName() 加载为此策略指定的 classes。但是由于 Quarkus class 加载器用于加载驱动程序代码本身,它是用于这些反射操作的加载器......并且如上所述,该驱动程序具有一些使加载外部代码更难的特定特征。
在我像 -
一样初始化 CQL 会话后它起作用了CqlSession.builder() .addContactPoint(new InetSocketAddress(settings.getAddress(), settings.getPort())) .withLocalDatacenter("***") . withClassLoader(Thread.currentThread().getContextClassLoader()).build())