在WildFly中配置ActiveMQ Artemis自定义负载均衡类遇类找不到异常
自定义ActiveMQ Artemis负载均衡策略在WildFly中触发ClassNotFoundException的解决
问题背景
在WildFly(JBoss)中集成ActiveMQ Artemis时,配置了客户端侧自定义连接负载均衡策略,但运行时触发ClassNotFoundException。
核心配置(CLI)
## Artemis Broker Config /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-artemis1:add(host=my-broker, port=61616) /subsystem=messaging-activemq/server=default/remote-connector=remote-artemis1:add(socket-binding=remote-artemis1) ## Global Artemis Conf /subsystem=messaging-activemq/server=default/pooled-connection-factory=remote-artemis:add(entries=["java:/RemoteJmsXA", "java:jboss/RemoteJmsXA"],connectors=["remote-artemis1"], user="###ARTEMIS_USER###", password="###ARTEMIS_USER_PASSWORD###", ha="true", min-pool-size="3", max-pool-size="30", statistics-enabled="true", connection-load-balancing-policy-class-name="online.myproject.utils.amqartemis.RoundRobinFromFirstConnectionLoadBalancingPolicy") <--- 问题所在 /subsystem=naming/binding=java\:global\/remoteContext:add(binding-type=external-context, module="org.apache.activemq.artemis", class="javax.naming.InitialContext", environment=[java.naming.factory.initial="org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory", java.naming.provider.url="tcp://my-broker:61616", queue.Server_Emit_MyQueue="Server_Emit_MyQueue"])
自定义负载均衡类
package online.myproject.utils.amqartemis; import org.apache.activemq.artemis.api.core.client.loadbalance.ConnectionLoadBalancingPolicy; import java.io.Serializable; public class RoundRobinFromFirstConnectionLoadBalancingPolicy implements ConnectionLoadBalancingPolicy, Serializable { private int pos = -1; @Override public int select(final int max) { pos++; if (pos >= max) { pos = 0; } return pos; } }
报错日志
[0m[33m12:18:16,024 WARN [org.apache.activemq.artemis.ra] (default-threads - 1) AMQ152005: Failure in broker activation org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec(ra=org.wildfly.extension.messaging.activemq.ActiveMQResourceAdapter@69686637 destination=java:global/remoteContext/RestServer_Receive_MediaCreation destinationType=javax.jms.Queue selector=messageType='MEDIA_REFERENCE_CREATED_1.0.0' ack=Auto-acknowledge durable=false clientID=null user=null maxSession=15): ActiveMQInternalErrorException[errorType=INTERNAL_ERROR message=AMQ219004: Failed to initialise session factory] at org.apache.activemq.artemis@2.10.1//org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.initialize(ServerLocatorImpl.java:313) at org.apache.activemq.artemis@2.10.1//org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:768) at org.apache.activemq.artemis.ra@2.10.1//org.apache.activemq.artemis.ra.inflow.ActiveMQActivation.setup(ActiveMQActivation.java:314) at org.apache.activemq.artemis.ra@2.10.1//org.apache.activemq.artemis.ra.inflow.ActiveMQActivation$SetupActivation.run(ActiveMQActivation.java:731) at org.wildfly.extension.messaging-activemq//org.wildfly.extension.messaging.activemq.ActiveMQResourceAdapter$WorkWrapper.run(ActiveMQResourceAdapter.java:171) at org.jboss.ironjacamar.impl@1.4.17.Final//org.jboss.jca.core.workmanager.WorkWrapper.runWork(WorkWrapper.java:445) at org.jboss.as.connector@18.0.1.Final//org.jboss.as.connector.services.workmanager.WildflyWorkWrapper.runWork(WildflyWorkWrapper.java:69) at org.jboss.ironjacamar.impl@1.4.17.Final//org.jboss.jca.core.workmanager.WorkWrapper.run(WorkWrapper.java:223) at org.jboss.threads@2.3.3.Final//org.jboss.threads.SimpleDirectExecutor.execute(SimpleDirectExecutor.java:29) at org.jboss.threads@2.3.3.Final//org.jboss.threads.QueueExecutor.runTask(QueueExecutor.java:789) at org.jboss.threads@2.3.3.Final//org.jboss.threads.QueueExecutor.access$100(QueueExecutor.java:44) at org.jboss.threads@2.3.3.Final//org.jboss.threads.QueueExecutor$Worker.run(QueueExecutor.java:809) at java.base/java.lang.Thread.run(Thread.java:829) at org.jboss.threads@2.3.3.Final//org.jboss.threads.JBossThread.run(JBossThread.java:485) Caused by: java.lang.IllegalStateException: java.lang.ClassNotFoundException: online.myproject.utils.amqartemis.RoundRobinFromFirstConnectionLoadBalancingPolicy from [Module "org.wildfly.extension.messaging-activemq" from local module loader @22f31dec (finder: local module finder @34c01041 (roots: /opt/jboss/wildfly/modules,/opt/jboss/wildfly/modules/system/layers/base))] at org.apache.activemq.artemis.journal//org.apache.activemq.artemis.utils.ClassloadingUtil.newInstanceFromClassLoader(ClassloadingUtil.java:59) at org.apache.activemq.artemis@2.10.1//org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl$3.run(ServerLocatorImpl.java:281) at java.base/java.security.AccessController.doPrivileged(Native Method) at org.apache.activemq.artemis@2.10.1//org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.instantiateLoadBalancingPolicy(ServerLocatorImpl.java:278) at org.apache.activemq.artemis@2.10.1//org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.initialize(ServerLocatorImpl.java:302) ... 13 more Caused by: java.lang.ClassNotFoundException: online.myproject.utils.amqartemis.RoundRobinFromFirstConnectionLoadBalancingPolicy from [Module "org.wildfly.extension.messaging-activemq" from local module loader @22f31dec (finder: local module finder @34c01041 (roots: /opt/jboss/wildfly/modules,/opt/jboss/wildfly/modules/system/layers/base))] at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255) at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410) at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398) at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116) at org.apache.activemq.artemis.journal//org.apache.activemq.artemis.utils.ClassloadingUtil.newInstanceFromClassLoader(ClassloadingUtil.java:55) ... 17 more
问题根源
WildFly采用模块化类加载机制,org.wildfly.extension.messaging-activemq模块默认无法访问你的自定义类,因为该类不在其依赖的模块路径中,因此触发类加载异常。
解决方案
方案一:通过连接工厂配置指定模块(推荐)
无需修改系统模块,直接在CLI配置中为连接工厂添加module属性,指定自定义类所在的模块:
/subsystem=messaging-activemq/server=default/pooled-connection-factory=remote-artemis:add( entries=["java:/RemoteJmsXA", "java:jboss/RemoteJmsXA"], connectors=["remote-artemis1"], user="###ARTEMIS_USER###", password="###ARTEMIS_USER_PASSWORD###", ha="true", min-pool-size="3", max-pool-size="30", statistics-enabled="true", connection-load-balancing-policy-class-name="online.myproject.utils.amqartemis.RoundRobinFromFirstConnectionLoadBalancingPolicy", module="online.myproject.utils.amqartemis" )
然后按以下步骤创建自定义模块:
- 在WildFly的
modules目录下创建路径:modules/online/myproject/utils/amqartemis/main/ - 将编译好的自定义类打包成jar,放入上述目录
- 在该目录创建
module.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.3" name="online.myproject.utils.amqartemis"> <resources> <!-- 替换为你的自定义类jar包名称 --> <resource-root path="custom-amq-loadbalance-policy.jar"/> </resources> <dependencies> <!-- 依赖ActiveMQ Artemis核心API模块 --> <module name="org.apache.activemq.artemis"/> <!-- 依赖Java基础API模块 --> <module name="javax.api"/> </dependencies> </module>
方案二:修改系统模块依赖
如果需要让org.wildfly.extension.messaging-activemq模块直接访问自定义类,可以修改其模块依赖:
- 按方案一的步骤创建自定义模块
- 编辑
modules/system/layers/base/org/wildfly/extension/messaging-activemq/main/module.xml,添加依赖:
<dependencies> <!-- 保留原有所有依赖 --> <module name="online.myproject.utils.amqartemis"/> </dependencies>
最后步骤
完成配置后,重启WildFly服务器,让模块加载生效。
内容的提问来源于stack exchange,提问作者Theo Cerutti
相关产品推荐
相关产品推荐

