如何在Spring中在DefaultMessageListenerContainer中设置持久订阅者?

时间:2018-06-16 17:42:31

标签: jms spring-jms amq

消息的生产者不会将消息作为持久性发送,当我尝试通过MessageListener消费消息时,如果发生任何异常(运行时),它将重试特定次数(默认值为AMQ的6)和消息迷路了。

原因是,由于生产者未将交付模式设置为持久性,因此在经过一定次数的重试尝试后,不会创建DLQ,并且消息不会移至DLQ。因此,我丢失了信息。

我的代码是这样的: -

@Configuration
@PropertySource("classpath:application.properties")
public class ActiveMqJmsConfig {

@Autowired
private AbcMessageListener abcMessageListener;

public DefaultMessageListenerContainer purchaseMsgListenerforAMQ(
    @Qualifier("AMQConnectionFactory") ConnectionFactory amqConFactory) {

    LOG.info("Message listener for purchases from AMQ : Starting");
    DefaultMessageListenerContainer defaultMessageListenerContainer =
        new DefaultMessageListenerContainer();

    defaultMessageListenerContainer.setConnectionFactory(amqConFactory);

    defaultMessageListenerContainer.setMaxConcurrentConsumers(4);

    defaultMessageListenerContainer
        .setDestinationName(purchaseReceivingQueueName);

    defaultMessageListenerContainer
        .setMessageListener(abcMessageListener);

    defaultMessageListenerContainer.setSessionTransacted(true);

    return defaultMessageListenerContainer;
}

 @Bean
@Qualifier(value = "AMQConnectionFactory")
public ConnectionFactory activeMQConnectionFactory() {

    ActiveMQConnectionFactory amqConnectionFactory =
        new ActiveMQConnectionFactory();

    amqConnectionFactory
        .setBrokerURL(System.getProperty(tcp://localhost:61616));
    amqConnectionFactory
        .setUserName(System.getProperty(admin));
    amqConnectionFactory
        .setPassword(System.getProperty(admin));

    return amqConnectionFactory;

}

}

@Component
public class AbcMessageListener implements MessageListener {
 @Override
public void onMessage(Message msg) {
//CODE implementation
}

}

问题: - 通过在连接级别设置client-id(Connection.setclientid(" String")),即使消息不是持久的,我们也可以订阅为持久订阅者。通过执行此操作,如果应用程序抛出运行时异常,则在执行一定次数的重试后,将为队列创建DLQ并将消息移动到DLQ。

但是在DefaultMessageListenerContainer中,连接不会暴露给客户端。我认为它是由Class本身维护的。

如何在DefaultMessageListenerContainer中实现持久订阅?

1 个答案:

答案 0 :(得分:0)

您可以在容器上设置客户端ID:

/**
 * Specify the JMS client ID for a shared Connection created and used
 * by this container.
 * <p>Note that client IDs need to be unique among all active Connections
 * of the underlying JMS provider. Furthermore, a client ID can only be
 * assigned if the original ConnectionFactory hasn't already assigned one.
 * @see javax.jms.Connection#setClientID
 * @see #setConnectionFactory
 */
public void setClientId(@Nullable String clientId) {
    this.clientId = clientId;
}

/**
 * Set the name of a durable subscription to create. This method switches
 * to pub-sub domain mode and activates subscription durability as well.
 * <p>The durable subscription name needs to be unique within this client's
 * JMS client id. Default is the class name of the specified message listener.
 * <p>Note: Only 1 concurrent consumer (which is the default of this
 * message listener container) is allowed for each durable subscription,
 * except for a shared durable subscription (which requires JMS 2.0).
 * @see #setPubSubDomain
 * @see #setSubscriptionDurable
 * @see #setSubscriptionShared
 * @see #setClientId
 * @see #setMessageListener
 */
public void setDurableSubscriptionName(@Nullable String durableSubscriptionName) {
    this.subscriptionName = durableSubscriptionName;
    this.subscriptionDurable = (durableSubscriptionName != null);
}