我正在尝试使用 quarkus 创建一个扩展,以便将 ibm mq 用作 native 可执行文件。 到目前为止,我已经(在运行时模块中)创建了 ConnectionFactory 生产者:
@ApplicationScoped
public class ConnectionFactoryProducer {
@Produces
@ApplicationScoped
@DefaultBean
public JmsConnectionFactory connectionFactory() throws JMSException {
JmsFactoryFactory ff;
JmsConnectionFactory factory;
ff = JmsFactoryFactory.getInstance(JmsConstants.WMQ_PROVIDER);
factory = ff.createConnectionFactory();
// Always work in TCP/IP client mode
factory.setIntProperty(CommonConstants.WMQ_CONNECTION_MODE, CommonConstants.WMQ_CM_CLIENT);
factory.setStringProperty(CommonConstants.WMQ_HOST_NAME, "localhost");
factory.setIntProperty(CommonConstants.WMQ_PORT, 1414);
factory.setStringProperty(CommonConstants.WMQ_CHANNEL, "DEV.ADMIN.SVRCONN");
factory.setStringProperty(CommonConstants.WMQ_QUEUE_MANAGER, "QM1");
factory.setStringProperty(WMQConstants.USERID, "admin");
factory.setStringProperty(WMQConstants.PASSWORD, "passw0rd");
return factory;
}
}
部署模块包含处理器:
public final class IbmExtProcessor {
private static final String FEATURE = "ibm-ext";
@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}
}
其中 FEATURE 是扩展的名称。
但是当我尝试通过将其作为依赖项导入到我的项目中来使用扩展来执行代码时,没有任何反应。 看起来使用依赖关系的类不再存在于应用程序上下文中。 消息生产者示例:
public class NumberProducer implements Runnable {
private final Random random = new Random();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
@Inject
private ConnectionFactoryProducer cf;
private ConnectionFactory c;
void onStart(@Observes StartupEvent ev) throws JMSException {
c=cf.connectionFactory();
scheduler.scheduleWithFixedDelay(this, 0L, 1L, TimeUnit.SECONDS);
}
void onStop(@Observes ShutdownEvent ev) {
scheduler.shutdown();
}
@Override
public void run() {
JMSContext context = c.createContext();
Queue destination=context.createQueue("queue:///DEV.QUEUE.1");
try {
TextMessage message = context.createTextMessage(String.format("Value : %d", random.nextInt(100)));
JMSProducer producer = context.createProducer();
producer.send(destination, message);
System.out.println(message);
} catch (Exception e) {
throw e;
}
}
}
在这种情况下,我将永远不会打印消息变量。任何人都可以帮忙吗?我想我在扩展中遗漏了一些东西,但我不知道是什么。
最佳答案
当您必须连接到经典 IBM MQ channel 时,AMQP 将不起作用。在这种情况下,您必须使用 com.ibm.mq.allclient jar。尽管有内省(introspection)和线程生成,但可以在 Quarkus native 镜像中使用 com.ibm.mq.allclient。您将需要以下 quarkus.native.additional-build-args:
-J-Dcom.ibm.mq.cfg.useIBMCipherMappings=false,\
-J-Dcom.ibm.msg.client.commonservices.ffst.suppress=-1,\
--initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl\,com.ibm.mq.jmqi.remote.impl.RemoteReconnectThread\,com.ibm.mq.jmqi.JmqiDefaultThreadPool\,com.ibm.msg.client.wmq.compat.jms.internal.MQJMSMessage\,com.ibm.msg.client.commonservices.workqueue.WorkQueueManager,\
-H:ResourceConfigurationFiles=resources-config.json,\
-H:ReflectionConfigurationFiles=reflection-config.json,\
-H:+ReportUnsupportedElementsAtRuntime,\
--report-unsupported-elements-at-runtime
使用非 IBM JDK 时需要第一个系统属性。
我添加了第二个系统属性以避免 FFDC 日志记录; (这将尝试写入本地文件系统)。
第一类提到的initialize-at-run-time 东西是因为使用了 SecureRandom。
其余部分用于 WorkQueueManager 的两个类加载路径。需要 WorkQueueManager 本身,因为它会在运行时生成线程。
关于反射,你必须为类定义一个 reflection-config.json
- com.ibm.msg.client.jms.internal.JmsFactoryFactoryImpl
- com.ibm.mq.jmqi.remote.api.RemoteFAP
- com.sun.security.cert.internal.x509.X509V1CertImpl
当您在与 MQ channel 的连接中使用 SSL/TLS 时,需要最后一个类。
{"pattern": ".+properties$"} 还需要一个 resources-config.json,因为 IBM MQ 代码使用 ResourceBundle 和许多用于错误消息的属性文件。
使用 SSL/TLS 时,您必须在 JmsConnectionFactory 上显式设置 SSLSocketfactory:
connectionFactory.setObjectProperty("XMSC_WMQ_SSL_SOCKET_FACTORY", sslSocketFactory);
根据您配置 JmsConnectionFactory 的方式和 com.ibm.mq.allclient jar 的版本,您可能会在“XMSC_WMQ_HOST_NAME”配置上遇到错误。这些错误是 IBM 代码中的错误,与 native 镜像无关。
关于jms - Quarkus IBM MQ 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60885669/