2012-09-14 6 views
9

Ich verwende ActiveMQ, um die Nachricht zu senden.Warum kommt die Nachricht wieder zur onMessage() Funktion?

Also, wenn ich eine Nachricht gesendet habe, kommt Nachricht, um Nachricht zu erhalten. Bei erfolgreichem Einfügen wird es bestätigt.

Aber ich habe einen Code nach der Bestätigung, die NullPointerException werfen kann.

Um diese Ausnahme absichtlich zu erzeugen, habe ich NullPointerException werfen. So wenn ich das tue

Nachricht ist nicht dequeued und die gleiche Meldung kommt wieder auf die onMessage Funktion.

mein Code:

public void onMessage(Message message) { 
    String msg = null; 
    try 
    { 
     msg = receiveMessage(message); 

     // other code to insert message in db 

     message.acknowledge(); 

     if(true) 
     { 
     throw new NullPointerException("npe")); 
     } 
     ** // other code which might produces null pointer exception ** 
     } 
     catch(Exception ex){} 
    } 

Nun meine Frage ist, warum die Nachricht wieder zu onMessage() Funktion kommen, wie ich acknowledge() es auch haben.

Da habe ich bereits die Nachricht in db eingefügt.

Wird die Nachricht innerhalb der Warteschlange nicht unter acknowledge() entfernt?

Wie kann ich das erreichen? Vielen Dank im Voraus.

+0

Was ist der Bestätigungsmodus Ihrer Sitzung? –

+0

@Tim Bestätigungsmodus ist als Client_Acknowledge festgelegt. vikiiii

+0

Welche Version von activemq verwenden Sie? –

Antwort

2

Sie können eine separate Methode für die Verarbeitung der Nachricht erstellen, mit der ich meine, dass in onMessage() Funktion schreiben Sie einen Code für nur Einfügen dieser Nachricht in DB.

Und erstellen Sie eine separate Funktion für die Verarbeitung dieser Nachricht. Wenn Sie während der Verarbeitung einen Fehler erhalten, wird die Nachricht nicht erneut an onMessage().

gesendet.
+0

Danke für die Idee. Ich werde versuchen, es zu implementieren. – vikiiii

0

Wenn Sie einen Transaktions-JMS-Bestätigungsmodus verwenden, wird Ihre Nachricht mehrmals vom JMS-Listener empfangen (in AMQ ist standardmäßig ~ 8) bis sie ohne Ausnahme verarbeitet wird oder vom JMS-Container in die DQL-Warteschlange verschoben wird. Einzelheiten finden Sie unter Message Redelivery and DLQ Handling.

Die Verwaltung von Transaktionen hängt von dem von Ihnen verwendeten Framework ab. Ich ziehe es Frühling zu verwenden, so dass mein Spring-XML-config sieht aus wie

<jms:listener-container container-type="default" connection-factory="calendarConnectionFactory" 
         acknowledge="transacted" destination-type="queue" cache="consumer" concurrency="1-5"> 
    <jms:listener destination="${jms.calendar.destination}" ref="calendarListener"/> 
</jms:listener-container> 

und der Java-Code meiner Nachricht Hörer ist

@Override 
@Transactional(propagation = Propagation.REQUIRED, 
     noRollbackFor = {ClassCastException.class, IllegalArgumentException.class}) 
public void onMessage(Message message) { 
.... 
} 

So kann ich festlegen, welche Ausnahmen die Transaktion Rollback oder nicht

+0

Ich habe versucht mit den obigen Anmerkungen aber wieder dasselbe Problem. – vikiiii

4

Sie verwenden den AUTO-Bestätigungsmodus mit Nachrichtenlistenern. Anschließend wird eine Nachricht erneut gesendet, wenn die Nachrichten-Listener nicht erfolgreich zurückgegeben werden können (z. B. wenn eine Ausnahme ausgelöst wird).

In Ihrem Fall versuchen Sie manuell die Nachricht zu bestätigen, aber das ist nicht möglich, mit createSession(false, Session.AUTO_ACKNOWLEDGE) einer Sitzung erstellt.

Ihr Code hätte mit Session.CLIENT_ACKNOWLEDGE funktioniert.

Andernfalls möchten Sie die Ausnahmen in der onMessage-Methode abfangen, während Sie AUTO_ACKNOWLEDGE verwenden.

Um eine detailliertere Kontrolle über Ihre Nachrichten zu erhalten, sollten Sie transaktierte Sitzungen verwenden und session.commit(); verwenden, um zu bestätigen, dass eine Nachricht gelesen wurde.

+0

In meiner jms-config.xml Datei. Ich habe es auf CLIENT_ACKNOWLEDGE festgelegt, aber immer noch das gleiche Problem. – vikiiii

3

Haben Sie überprüft, dass Sie nicht transacted sessions verwenden?.Wenn getätigten Sitzungen verwendet wird, wird der Bestätigungsmodus ignoriert, so:

  • Ihre message.acknowledge() effektiv ein

    no-op wäre würde
  • Ihre abgefangene Ausnahme ein „Session-Rollback“ auslösen werden, wenn Ihre Nachricht Hörer Flucht , Erzwingen der Neuzustellung der Nachricht.

ANMERKUNG: Sie veröffentlichte Code hat ein catch (Exception ex) { }, so dass ich weiß nicht genau, wie Sie Ihre Ausnahme außerhalb entweicht.

+0

Nach Bestätigung, es wirft Nullpointerexception und dann geht es zum catch-Block. Nach dieser Nachricht kommt wieder die onMessage() -Funktion. – vikiiii

+0

"Ihre message.acknowledge() wäre effektiv ein No-Op" Was bedeutet No-Op? – vikiiii

+0

@vikiiii No-Op bedeutet "Keine Operation". Es ist ein häufiger Begriff für eine Anweisung, die nichts tut. – gpeche

Verwandte Themen