我使用的是Spring Boot和ActiveMQ。我想发送和接收来自主题的消息。这很好用。我的代码如下所示:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
JmsSpike.TestListener1.class,
JmsSpike.TestListener2.class,
JmsSpike.Config.class
})
@TestPropertySource(properties = {
"spring.activemq.broker-url: tcp://localhost:61616",
"spring.activemq.password: admin",
"spring.activemq.user: admin",
"spring.jms.pub-sub-domain: true", // queue vs. topic
})
@EnableJms
@EnableAutoConfiguration
public class JmsSpike {
@Autowired
private JmsTemplate jmsTemplate;
@Test
public void sendMessage() throws Exception {
sendMessageInThread();
Thread.sleep(10000);
}
private void sendMessageInThread() {
new Thread() {
public void run() {
jmsTemplate.convertAndSend("asx2ras", "I'm a test");
}
}.start();
}
@TestComponent
protected static class TestListener1 {
@JmsListener(destination = "asx2ras")
public void receiveMessage(String message) {
System.out.println("****************** 1 *******************");
System.out.println("Hey 1! I got a message: " + message);
System.out.println("****************** 1 *******************");
}
}
@TestComponent
protected static class TestListener2 {
@JmsListener(destination = "asx2ras")
public void receiveMessage(String message) {
throw new RuntimeException("Nope");
}
}
@Configuration
protected static class Config {
@Bean
public RedeliveryPolicy redeliveryPolicy() {
RedeliveryPolicy topicPolicy = new RedeliveryPolicy();
topicPolicy.setMaximumRedeliveries(1);
return topicPolicy;
}
@Bean
public ConnectionFactory connectionFactory(@Value("${spring.activemq.user}") final String username,
@Value("${spring.activemq.password}") final String password,
@Value("${spring.activemq.broker-url}") final String brokerUrl) {
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(username, password, brokerUrl);
cf.setRedeliveryPolicy(redeliveryPolicy());
return cf;
}
}
}
我将重试设置为" 1",因此在抛出异常后将再次调用失败的侦听器。但是,重试后,消息不会传递到错误队列(或错误主题)。如何将消息发送到错误队列,以便以后再次调用失败的侦听器?
请注意,我只想再次调用失败的侦听器,而不是所有关于该主题的侦听器。这可能吗?
修改
这是我的activemq.xml
(仅broker
标记):
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<managementContext>
<managementContext createConnector="false"/>
</managementContext>
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
<shutdownHooks>
<bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
</shutdownHooks>
</broker>
答案 0 :(得分:1)
根据official documentation,您可以覆盖客户端的代理配置:
代理传输他喜欢的默认传递策略 客户端连接在他的BrokerInfo命令包中。但客户可以 使用。覆盖策略设置 ActiveMQConnection.getRedeliveryPolicy()方法:
RedeliveryPolicy policy = connection.getRedeliveryPolicy();
policy.setInitialRedeliveryDelay(500); policy.setBackOffMultiplier(2);
policy.setUseExponentialBackOff(true);
policy.setMaximumRedeliveries(2);
因此,您配置重新传递策略的方式似乎没问题。
我看到的唯一问题是,当您创建RedeliveryPolicy
的新实例并且仅设置单个字段topicPolicy.setMaximumRedeliveries(1);
时,所有其他基元字段都将被分配默认值。您应该在现有的重新传递策略实例上设置最大重新传输:
RedeliveryPolicy policy = cf.getRedeliveryPolicy();
policy.setMaximumRedeliveries(1);
修改强>
另外,请确保使用@JmsListener
未使用CLIENT_ACKNOWLEDGE
。根据此thread,在使用CLIENT_ACKNOWLEDGE
时,不会重新传递邮件。