Camel 为什么会出现“必须指定connectionFactory”异常?

rekjcdws  于 2022-11-07  发布在  Apache
关注(0)|答案(2)|浏览(153)

追踪:

org.apache.camel.FailedToStartRouteException: Failed to start route FromSAA because of null
    at org.apache.camel.impl.engine.RouteService.setUp(RouteService.java:132)
    at org.apache.camel.impl.engine.InternalRouteStartupManager.doInitRoutes(InternalRouteStartupManager.java:92)
    at org.apache.camel.impl.engine.AbstractCamelContext.doInit(AbstractCamelContext.java:2949)
    at org.apache.camel.support.service.BaseService.init(BaseService.java:83)
    at org.apache.camel.impl.engine.AbstractCamelContext.init(AbstractCamelContext.java:2630)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:111)
    at org.apache.camel.impl.engine.AbstractCamelContext.start(AbstractCamelContext.java:2649)
    at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:262)
    at org.apache.camel.spring.SpringCamelContext.start(SpringCamelContext.java:119)
    at org.apache.camel.spring.SpringCamelContext.onApplicationEvent(SpringCamelContext.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:938)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
    at ru.rbru.fms.router.Bootstrap.main(Bootstrap.java:13)
Caused by: java.lang.IllegalArgumentException: connectionFactory must be specified
    at org.apache.camel.util.ObjectHelper.notNull(ObjectHelper.java:156)
    at org.apache.camel.component.jms.JmsConfiguration.createConnectionFactory(JmsConfiguration.java:1746)
    at org.apache.camel.component.jms.JmsConfiguration.getOrCreateConnectionFactory(JmsConfiguration.java:856)
    at org.apache.camel.component.jms.JmsConfiguration.createListenerConnectionFactory(JmsConfiguration.java:1754)
    at org.apache.camel.component.jms.JmsConfiguration.getOrCreateListenerConnectionFactory(JmsConfiguration.java:900)
    at org.apache.camel.component.jms.JmsConfiguration.configureMessageListenerContainer(JmsConfiguration.java:1582)
    at org.apache.camel.component.jms.JmsConfiguration.createMessageListenerContainer(JmsConfiguration.java:786)
    at org.apache.camel.component.jms.JmsEndpoint.createMessageListenerContainer(JmsEndpoint.java:157)
    at org.apache.camel.component.jms.JmsEndpoint.createConsumer(JmsEndpoint.java:152)
    at org.apache.camel.component.jms.JmsEndpoint.createConsumer(JmsEndpoint.java:69)
    at org.apache.camel.impl.engine.DefaultRoute.gatherRootServices(DefaultRoute.java:636)
    at org.apache.camel.impl.engine.DefaultRoute.gatherServices(DefaultRoute.java:620)
    at org.apache.camel.impl.engine.DefaultRoute.initializeServices(DefaultRoute.java:205)
    at org.apache.camel.impl.engine.RouteService.doSetup(RouteService.java:151)
    at org.apache.camel.impl.engine.RouteService.setUp(RouteService.java:130)
    ... 23 common frames omitted

我的配置:
第一个
如果我只使用一个ConnectionFactory,则不会出现问题,但只要我再添加一个ConnectionFactory,例如:
第一个
我得到了前面提到的例外。
什么原因会导致此异常?

qvsjd97n

qvsjd97n1#

如果您使用camel-jms-starter组件,它会尝试自动发现ConnectionFactory。如果注册表中只有一个ConnectionFactory对象,则默认使用该对象。但如果存在多个工厂,则必须使用connectionFactory端点属性在路由上指定该对象。

from(jms:destinationType:destinationName? 
      connectionFactory=#saaIbmMqFactory)
      .log(LoggingLevel.DEBUG, log, "New message received")
      .process(processor)
      .choice()
      .when(exchange -> 
            exchange.getProperty(STATUS)
           .equals(MessageStatus.SUCCESSFULLY_PARSED))
               .to(esbIbmMqProperties.getQueue())
       .otherwise()
               .log("Message was not converted")
       .endChoice();
shstlldc

shstlldc2#

如果我现在必须猜测而不试图重现代码,我认为这是因为您在此代码中传递给register方法调用的参数

private void registerComponent(CamelContext context,
                               ConnectionFactory connectionFactory,
                               IbmMqProperties ibmMqProperties) {
    ComponentsBuilderFactory.jms()
            .connectionFactory(connectionFactory)
            .acknowledgementModeName(ACKNOWLEDGEMENT_MODE)
            .concurrentConsumers(ibmMqProperties.getConcurrentConsumersCount())
            .register(context, ibmMqProperties.getQueue());
}

register方法的doc将第二个参数指定为组件名称,并传递整个队列名称。Camel使用组件“names”来解析哪个组件将处理某个路由。因此,如果您编写:

.to("jms:queueName....")

Camel将查找使用名称“jms”注册的组件-默认情况下是JmsComponent,但没有什么可以阻止您使用名称“myJmsComponent”注册JmsComponent,因此您可以编写:

.to("myJmsComponent:queueName")

在您的示例中,您正在使用队列的名称注册组件,而不是您所认为的那样--为不同的队列注册不同的连接工厂。
如果你想继续使用这个ComponentBuilderFactory模式,我建议你重写你的初始化器类,如下所示:

@Component
    @RequiredArgsConstructor
    public class IbmMqInitializer {
    private static final String ACKNOWLEDGEMENT_MODE = "CLIENT_ACKNOWLEDGE";

    public void configure(CamelContext context, IbmMqProperties ibmMqProperties, ConnectionFactory connectionFactory, String componentName) throws JMSException {
        registerIbmMq(context, ibmMqProperties, connectionFactory, componentName);
    }

    private void registerIbmMq(CamelContext context, IbmMqProperties ibmMqProperties, ConnectionFactory connectionFactory, String componentName) {
        registerComponent(context, connectionFactory, ibmMqProperties, componentName);
    }

    private void registerComponent(CamelContext context,
                                   ConnectionFactory connectionFactory,
IbmMqProperties ibmMqProperties
                                   String componentName) {
        ComponentsBuilderFactory.jms()
                .connectionFactory(connectionFactory)
                .acknowledgementModeName(ACKNOWLEDGEMENT_MODE)
                .concurrentConsumers(ibmMqProperties.getConcurrentConsumersCount())
                .register(context, componentName);
    }
}

然后这样称呼它:

try {
  ibmMqInitializer.configure(context, saaIbmMqProps, saaIbmMqFactory, "saa");
  ibmMqInitializer.configure(context, esbIbmMqProps, esbIbmMqFactory, "esb");
} catch (JMSException e) {
    log.error("Failed to connect to MQ", e);
}

然后更改属性,使方法IbmMqProperties::getQueue()返回以saa:esb:开头的路由,而不是现在的路由,这两个路由可能都是jms:...
所以saa:sourceQueueNameesb:destQueueName

相关问题