在使用Spring Boot消费JMS主题消息时出现异常。

huangapple go评论79阅读模式
英文:

Exception while trying to consume a JMS Topic message using Spring Boot

问题

以下是翻译好的部分:

我正在尝试从ActiveMQ主题中消费消息。以下是代码:

@Configuration
@EnableJms
public class Config {

    @Value("${activemq.broker-url}")
    private String brokerURL;

    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory() {
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
        activeMQConnectionFactory.setBrokerURL(brokerURL);
        activeMQConnectionFactory.setTrustAllPackages(true);
        return activeMQConnectionFactory;
    }

    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(){
        DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
        defaultJmsListenerContainerFactory.setConnectionFactory(activeMQConnectionFactory());
        defaultJmsListenerContainerFactory.setPubSubDomain(true);
        return defaultJmsListenerContainerFactory;
    }
}

我的消费者代码:

@Component
@EnableJms
public class Consumer {

   @JmsListener(destination = "xml.inbound.topic", containerFactory = "jmsListenerContainerFactory")
   public void Processor(final Message xmlMessage) {

   }
}

我得到的异常是:

Unsatisfied dependency expressed through field 'jmsTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsTemplate' defined in class path resource [com/investmentbank/equityfeedsprocessingrevised/config/Config.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.core.JmsTemplate]: Factory method 'jmsTemplate' threw exception; nested exception is java.lang.ClassCastException: class org.springframework.jms.config.DefaultJmsListenerContainerFactory cannot be cast to class javax.jms.ConnectionFactory (org.springframework.jms.config.DefaultJmsListenerContainerFactory and javax.jms.ConnectionFactory are in unnamed module of loader 'app')

我在这里做错了什么?为什么会出现异常?

我还尝试过:

@Bean
public DefaultMessageListenerContainer jmsListenerContainerFactory() {
        DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
        dmlc.setConnectionFactory(activeMQConnectionFactory());
        dmlc.setPubSubDomain(true);
        return dmlc;
}

我在这里得到的异常是:

Unsatisfied dependency expressed through field 'jmsTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsTemplate' defined in class path resource [com/investmentbank/equityfeedsprocessingrevised/config/Config.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.core.JmsTemplate]: Factory method 'jmsTemplate' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsListenerContainerFactory' defined in class path resource [com/investmentbank/equityfeedsprocessingrevised/config/Config.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'destination' or 'destinationName' is required

只是补充一下,我的JmsTemplate代码看起来像这样:

@Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate();
         jmsTemplate.setConnectionFactory(activeMQConnectionFactory());
         jmsTemplate.setPubSubDomain(true);
         return jmsTemplate;
}

我使用Apache Camel实现了JMS主题发布者(代码):

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
CamelContext _ctx = new DefaultCamelContext(); 
_ctx.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
_ctx.addRoutes(new RouteBuilder() {
    
    public void configure() throws Exception {
        from("file:src/main/resources?fileName=data-sample_2.csv")
        .process(new MyTransformRevised1())
        .to("file:src/main/resources/?fileName=emp.xml")				
        .split(body().tokenizeXML("equityFeeds", null)).streaming().to("jms:topic:xml.inbound.topic");
    }
    
});

我能够在主题名称的“消息入队”列中看到消息数。

发生了什么错误?我已经阅读了网络上的各种帖子,但无法解决这个问题。请帮助解决这个问题。我无法在ActiveMQ主题上读取消息。如果我漏掉了一些信息,请告诉我。

英文:

I am trying to consume message from ActiveMQ Topic. Below is the Code:

@Configuration
@EnableJms
public class Config {

@Value("${activemq.broker-url}")
private String brokerURL;

@Bean
public ActiveMQConnectionFactory activeMQConnectionFactory() {
    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
    activeMQConnectionFactory.setBrokerURL(brokerURL);
    activeMQConnectionFactory.setTrustAllPackages(true);
    return activeMQConnectionFactory;
}

public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(){
    DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
    defaultJmsListenerContainerFactory.setConnectionFactory(activeMQConnectionFactory());
    defaultJmsListenerContainerFactory.setPubSubDomain(true);
    return defaultJmsListenerContainerFactory;
}

My Consumer Code:

@Component
@EnableJms
public class Consumer {

   @JmsListener(destination = "xml.inbound.topic", containerFactory = "jmsListenerContainerFactory")
   public void Processor(final Message xmlMessage) {

   }
}

The Exception which I am getting is:

Unsatisfied dependency expressed through field 'jmsTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsTemplate' defined in class path resource [com/investmentbank/equityfeedsprocessingrevised/config/Config.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.core.JmsTemplate]: Factory method 'jmsTemplate' threw exception; nested exception is java.lang.ClassCastException: class org.springframework.jms.config.DefaultJmsListenerContainerFactory cannot be cast to class javax.jms.ConnectionFactory (org.springframework.jms.config.DefaultJmsListenerContainerFactory and javax.jms.ConnectionFactory are in unnamed module of loader 'app')

What am I doing wrong here ? Why the exception?

I have also tried :

@Bean
public DefaultMessageListenerContainer jmsListenerContainerFactory() {
        DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
        dmlc.setConnectionFactory(activeMQConnectionFactory());
        dmlc.setPubSubDomain(true);
        return dmlc;
}

The Exception which I get here is:

Unsatisfied dependency expressed through field 'jmsTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsTemplate' defined in class path resource [com/investmentbank/equityfeedsprocessingrevised/config/Config.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.core.JmsTemplate]: Factory method 'jmsTemplate' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsListenerContainerFactory' defined in class path resource [com/investmentbank/equityfeedsprocessingrevised/config/Config.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'destination' or 'destinationName' is required

Just to add my JmsTemplate code looks like this:

@Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate();
         jmsTemplate.setConnectionFactory(activeMQConnectionFactory());
         jmsTemplate.setPubSubDomain(true);
         return jmsTemplate;
}

I have implemented the JMS Topic Publisher using Apache Camel (Code):

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
		CamelContext _ctx = new DefaultCamelContext(); 
		_ctx.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
		_ctx.addRoutes(new RouteBuilder() {
			
			public void configure() throws Exception {
				from("file:src/main/resources?fileName=data-sample_2.csv")
				.process(new MyTransformRevised1())
				.to("file:src/main/resources/?fileName=emp.xml")				
				.split(body().tokenizeXML("equityFeeds", null)).streaming().to("jms:topic:xml.inbound.topic");
			}
			
		});

I am able to see the number of messages in "Message Enqueued" column of my Topic name.

What is going wrong ? I have read various posts on net but not able to solve the issue. Kindly help in resolving the issue. I am not able to read the message on ActiveMQ Topic. Let me know if some information is missing from my end.

答案1

得分: 2

你可以尝试将`activeMQConnectionFactory`包装在`CachingConnectionFactory`并利用`DefaultJmsListenerContainerFactoryConfigurer`来配置`JmsListenerContainerFactory`:

@Bean
ConnectionFactory connectionFactory() {
    return new CachingConnectionFactory(activeMQConnectionFactory());
}

@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory(ConnectionFactory connectionFactory,
                                    DefaultJmsListenerContainerFactoryConfigurer configurer) {

    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    configurer.configure(factory, connectionFactory);
    return factory;
}

EDIT start:

你可以尝试将`JmsTemplate`更改为

@Bean
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
    JmsTemplate jmsTemplate = new JmsTemplate();
    jmsTemplate.setConnectionFactory(connectionFactory);
    jmsTemplate.setPubSubDomain(true);
    return jmsTemplate;
}
英文:

you could try to wrap the activeMQConnectionFactory in a CachingConnectionFactory and utilize the DefaultJmsListenerContainerFactoryConfigurer to configure the JmsListenerContainerFactory:

@Bean
ConnectionFactory connectionFactory() {
	return new CachingConnectionFactory(activeMQConnectionFactory());
}

@Bean
public JmsListenerContainerFactory&lt;?&gt; jmsListenerContainerFactory(ConnectionFactory connectionFactory,
									DefaultJmsListenerContainerFactoryConfigurer configurer) {
	
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
	configurer.configure(factory, connectionFactory);
	return factory;
}

EDIT start:

could you try changing the JmsTemplate to:

@Bean
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
JmsTemplate jmsTemplate = new JmsTemplate();
         jmsTemplate.setConnectionFactory(connectionFactory);
         jmsTemplate.setPubSubDomain(true);
         return jmsTemplate;
}

答案2

得分: 0

我用以下代码解决了这个问题:

public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(){
    DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
    defaultJmsListenerContainerFactory.setConnectionFactory(activeMQConnectionFactory());
    defaultJmsListenerContainerFactory.setPubSubDomain(true);
    return defaultJmsListenerContainerFactory;
}

@Bean
public JmsTemplate jmsTemplate() {
    JmsTemplate jmsTemplate = new JmsTemplate();
    jmsTemplate.setConnectionFactory(activeMQConnectionFactory());
    jmsTemplate.setPubSubDomain(true);
    return jmsTemplate;
}

@JmsListener(destination = "${my.inboundTopicName}", containerFactory = "jmsListenerContainerFactory")
public void myProcessor(final Message xmlMessage) {
    ///
}

我想补充说明,我遇到了一些异常行为。

  1. 在生产者生成消息的同时,如果消费者正在运行,那么消费者只会消费到消息。也就是说,如果消息由生产者生成并由ActiveMQ排队,然后过了一段时间我启动消费者,那么消费者将无法消费到这些消息。

  2. 此外,消费者消费消息之前需要一些时间。

英文:

I solved this with the below Code:

    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(){
    DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
                defaultJmsListenerContainerFactory.setConnectionFactory(activeMQConnectionFactory());
defaultJmsListenerContainerFactory.setPubSubDomain(true);
return defaultJmsListenerContainerFactory;
        }
    
     @Bean
     public JmsTemplate jmsTemplate() {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setConnectionFactory(activeMQConnectionFactory());
        jmsTemplate.setPubSubDomain(true);
        return jmsTemplate;
    }
    
    @JmsListener(destination = &quot;${my.inboundTopicName}&quot;, containerFactory = &quot;jmsListenerContainerFactory&quot;)
    public void myProcessor(final Message xmlMessage) {
    ///
    
    }

I want to add that I am experiencing some unusual behavior.

  1. At the time when the messages are generated from the producer and if
    the consumer is up then only the messages are consumed by the
    consumer. I mean that if the messages are produced by the producer
    and enqueued by ActiveMQ and after some time I turn on the consumer
    then the messages are not consumed by the consumer.

  2. . Also it takes a while before the messages are consumed by the
    consumer.

huangapple
  • 本文由 发表于 2020年4月8日 19:56:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/61100093.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定