2016-12-07 7 views
2

So ist die Einrichtung folgt:Frühling Integration und JDBC in einzelnen Transaktion

<tx:advice id="txAdvice2" transaction-manager="dataSourceTransactionManager"> 
    <tx:attributes> 
     <tx:method name="*" rollback-for="Throwable" no-rollback-for="ListenerExecutionFailedException"/> 
    </tx:attributes> 
</tx:advice> 

<int-amqp:inbound-channel-adapter channel="input-channel" queue-names="probni" message-converter="jsonMessageConverter" 
            channel-transacted="true" 
            advice-chain="txAdvice2" /> 

<int:chain input-channel="input-channel" output-channel="output-channel"> 
    <int:service-activator ref="h1Handler" method="handle" /> 
    <int:service-activator ref="h2Handler" method="handle" /> 
    <int:service-activator ref="h3Handler" method="handle" /> 
    <int:splitter /> 
</int:chain> 

<int-amqp:outbound-channel-adapter channel="output-channel" exchange-name="outputit" amqp-template="rabbitTemplate" /> 

Wenn bei der Ausführung dieses Threads (da alle diese Kette amqpIN-Prozess-amqpOUT in einzelnen Thread ausführen shold) Ich werfe ListenerExecutionFailedException, dataSourceTransactionManager wird Commit ausführen, aber amqp wird die Nachricht auch erneut in die Warteschlange stellen, da die Ausnahme propagiert wird.

Wie kann ich Kaninchen sagen, die Nachricht in diesem Fall als erfolgreich zu ACK?

Auch sah ich, dass ich No-Rollback-für Attribut tatsächlichen Ausnahmeklasse setzen musste, da meine innere Ausnahme nur in "Ursache" -Attribut gespeichert ist, die nicht von RuleBasedTransactionAttribute überprüft wird.

Eine weitere Sache, wenn ich make config wie folgt aus:

<int-amqp:inbound-channel-adapter channel="input-channel" queue-names="probni" message-converter="jsonMessageConverter" 
            channel-transacted="true" 
            transaction-manager="dataSourceTransactionManager" 
            transaction-attribute="transactionAttribute" /> 

Transaction die RuleBasedTransactionAttribute ist haupt nicht berücksichtigt wird und dataSourceTransactionManager immer noch ist rollbacked wenn ich kein Rollback-für richtig eingestellt haben.

Danke!

Antwort

2

Sie können einen benutzerdefinierte hinzufügen ErrorHandler den Hörer Behälter ( Sie den Behälter von außen konfigurieren und eine Referenz in dem container Attribute zur Verfügung stellen).

Der Standardfehlerhandler ist ein ConditionalRejectingErrorHandler mit einem DefaultExceptionStrategy, den bestimmten Lefe Ursache Ausnahmen als fatal hält:

private boolean isCauseFatal(Throwable cause) { 
     return cause instanceof MessageConversionException 
       || cause instanceof org.springframework.messaging.converter.MessageConversionException 
       || cause instanceof MethodArgumentNotValidException 
       || cause instanceof MethodArgumentTypeMismatchException 
       || cause instanceof NoSuchMethodException 
       || cause instanceof ClassCastException 
       || isUserCauseFatal(cause); 
    } 

Beginnend mit 1.6.4-Version können Sie den Standard DefaultExceptionStrategy Unterklassen und fügen Sie Ihre Ursache (n) isUserCauseFatal().

Vor 1.6.4 mussten Sie Ihre eigene FatalExceptionStrategy (oder Error-Handler-Implementierung) bereitstellen.

Bei schwerwiegenden Ursachen löst der Handler eine AmqpRejectAndDontRequeueException aus, die den Container anweist, die Nachricht zu ignorieren (und nicht erneut anzurufen).

EDIT

By the way, gibt es keine Notwendigkeit für Sie, um die Ausnahme zu wickeln, der Behälter wird das für Sie tun ...

protected Exception wrapToListenerExecutionFailedExceptionIfNeeded(Exception e, Message message) { 
    if (!(e instanceof ListenerExecutionFailedException)) { 
     // Wrap exception to ListenerExecutionFailedException. 
     return new ListenerExecutionFailedException("Listener threw exception", e, message); 
    } 
    return e; 
} 

EDIT2

Mein Fehler, der ErrorHandler kann mit dem error-handler Attribut angegeben werden.

EDIT3

Alternativ werfen nur ein AmqpRejectAndDontRequeueException (die in der LEFE gewickelt wird).

+0

Sie müssen die Ausnahme nicht umbrechen; Siehe meine Bearbeitung. Sie können auch das 'error-handler' Attribut verwenden. –

+0

Danke für die schnelle Antwort. Werde das morgen versuchen.Wenn ichAndDontRequeue ablehne - kommt das in DeadLetterQueue? Ich möchte, dass dies als gewöhnliches ACK behandelt wird, da ich dies tun möchte, falls die Nachricht erneut gesendet wird (mindestens einmal + möglicherweise mehr geliefert). Wissen Sie übrigens auch, warum transaction-attribute bei der Auslieferung innerhalb von inbound-channel-adater nicht mit der Transaktion arbeitet, aber funktioniert, wenn sie als Hinweis angewendet wird? (Der zweite Teil der Frage). –

+0

Das ist, wenn Nachricht erneut geliefert wird, aber jdbc ist bereits commited, will ich eine Ausnahme werfen, die JDBC rollback aber ack Kaninchen Nachricht (da ich commit und ack am Ende der Verarbeitung Pipeline). –

Verwandte Themen