2017-02-09 55 views
0

使用jms队列。jms消息停止启动后非持久性重新传送appServer

EJB发件人:

@Resource(lookup = "jms/csPdvQueue") 
private Queue csPdvQueue; 
@Inject 
private JMSContext jmsContext; 

方法发送消息:

public void asynchWatched(Pdv pdv, boolean pending) { 
    jmsContext.createProducer().setDeliveryMode(DeliveryMode.NON_PERSISTENT); 
    jmsContext.createProducer().send(csPdvQueue, pdv); 
} 

EJB消费者:

@MessageDriven(mappedName = "jms/csPdvQueue") 
public class PdvProcessorMdb implements MessageListener { 

    @Override 
    public void onMessage(Message message) { 
    ... execute some businesslogic... 
    } 

} 

如果应用服务器(似鲭水狼牙鱼)消息中退出消耗(的onMessage),则事务正确回滚。

当应用程序服务器再次启动时,即使设置了DeliveryMode.NON_PERSISTENT,也会重新传递消息。

我想避免消息重新传送。

是否有可能(以及如何)?

+0

“当启动appServer同样的消息从消费者接收,但发件人不发送任何东西。” - 你能解释得更好吗?你如何从消费者那里收到 - 消费者不会发送消息而是收到消息。重启后是否收到相同的消息? – OndrejM

回答

1

当发送消息时,你做的是setDeliveryMode(DeliveryMode.NON_PERSISTENT);,这意味着在重新启动消息代理之间消息不会被保存。如果您在嵌入模式下使用OpenMQ代理(默认),则它将与服务器一起重新启动。因此,重新启动后,该消息不存在并且不能再次发送。

更新:

然而,您的代码设置在不同的生产比一个发送消息的传送模式(在创建一个制片人,设置传递模式,然后扔掉;下一行创建一个新的生产者,它发送消息)。 您需要将创建的生成存储在一个变量,设置的投放模式,然后使用相同的生产商发送消息:

public void asynchWatched(Pdv pdv, boolean pending) { 
    JMSProducer producer = jmsContext.createProducer(); 
    producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); 
    producer.send(csPdvQueue, pdv); 
} 

你可以把它缩短,以流畅的API的优势:

public void asynchWatched(Pdv pdv, boolean pending) { 
    jmsContext.createProducer() 
    .setDeliveryMode(DeliveryMode.NON_PERSISTENT); 
    .send(csPdvQueue, pdv); 
} 
+0

使用嵌入式消息代理。使用发布的代码,asynchWatched发送消息 - > onMessage接收消息 - >在进程消息期间,停止服务器 - >重新启动服务器 - > onMessage接收消息。 – omarbr

+0

感谢您的解释。我现在意识到你*确实希望邮件不会再发送。因此,您正确地要设置传送模式NON_PERSISTENT。但是代码将它设置在不同的生产者上。您必须存储创建的制作人,设置传送模式,然后使用同一制作人发送邮件。看到我更新的答案。 – OndrejM

+0

显然它的工作原理。我为我的愚蠢错误道歉! – omarbr