2017-02-09 45 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

相關問題