17
17
package org .springframework .integration .amqp .inbound ;
18
18
19
19
import java .util .Map ;
20
+ import java .util .concurrent .atomic .AtomicInteger ;
20
21
21
22
import org .springframework .amqp .core .AcknowledgeMode ;
22
23
import org .springframework .amqp .core .Address ;
32
33
import org .springframework .amqp .support .converter .MessageConverter ;
33
34
import org .springframework .amqp .support .converter .SimpleMessageConverter ;
34
35
import org .springframework .core .AttributeAccessor ;
36
+ import org .springframework .integration .IntegrationMessageHeaderAccessor ;
35
37
import org .springframework .integration .amqp .support .AmqpHeaderMapper ;
36
38
import org .springframework .integration .amqp .support .AmqpMessageHeaderErrorMessageStrategy ;
37
39
import org .springframework .integration .amqp .support .DefaultAmqpHeaderMapper ;
38
40
import org .springframework .integration .gateway .MessagingGatewaySupport ;
39
41
import org .springframework .integration .support .ErrorMessageStrategy ;
40
42
import org .springframework .integration .support .ErrorMessageUtils ;
43
+ import org .springframework .integration .support .StaticMessageHeaderAccessor ;
41
44
import org .springframework .retry .RecoveryCallback ;
42
45
import org .springframework .retry .RetryCallback ;
43
46
import org .springframework .retry .RetryContext ;
@@ -255,23 +258,29 @@ protected class Listener implements ChannelAwareMessageListener, RetryListener {
255
258
public void onMessage (final Message message , final Channel channel ) throws Exception {
256
259
if (AmqpInboundGateway .this .retryTemplate == null ) {
257
260
try {
258
- doOnMessage (message , channel );
261
+ org .springframework .messaging .Message <Object > converted = convert (message , channel );
262
+ if (converted != null ) {
263
+ process (message , converted );
264
+ }
259
265
}
260
266
finally {
261
267
attributesHolder .remove ();
262
268
}
263
269
}
264
270
else {
265
- AmqpInboundGateway .this .retryTemplate .execute (context -> {
266
- doOnMessage (message , channel );
271
+ org .springframework .messaging .Message <Object > converted = convert (message , channel );
272
+ if (converted != null ) {
273
+ AmqpInboundGateway .this .retryTemplate .execute (context -> {
274
+ StaticMessageHeaderAccessor .getDeliveryAttempt (converted ).incrementAndGet ();
275
+ process (message , converted );
267
276
return null ;
268
277
},
269
278
(RecoveryCallback <Object >) AmqpInboundGateway .this .recoveryCallback );
279
+ }
270
280
}
271
281
}
272
282
273
- private void doOnMessage (Message message , Channel channel ) {
274
- boolean error = false ;
283
+ private org .springframework .messaging .Message <Object > convert (Message message , Channel channel ) {
275
284
Map <String , Object > headers = null ;
276
285
Object payload = null ;
277
286
try {
@@ -281,6 +290,9 @@ private void doOnMessage(Message message, Channel channel) {
281
290
headers .put (AmqpHeaders .DELIVERY_TAG , message .getMessageProperties ().getDeliveryTag ());
282
291
headers .put (AmqpHeaders .CHANNEL , channel );
283
292
}
293
+ if (AmqpInboundGateway .this .retryTemplate != null ) {
294
+ headers .put (IntegrationMessageHeaderAccessor .DELIVERY_ATTEMPT , new AtomicInteger ());
295
+ }
284
296
}
285
297
catch (RuntimeException e ) {
286
298
if (getErrorChannel () != null ) {
@@ -290,60 +302,60 @@ private void doOnMessage(Message message, Channel channel) {
290
302
else {
291
303
throw e ;
292
304
}
293
- error = true ;
305
+ return null ;
294
306
}
295
-
296
- if (!error ) {
297
- org .springframework .messaging .Message <Object > messagingMessage = getMessageBuilderFactory ()
307
+ return getMessageBuilderFactory ()
298
308
.withPayload (payload )
299
309
.copyHeaders (headers )
300
310
.build ();
301
- setAttributesIfNecessary (message , messagingMessage );
302
- final org .springframework .messaging .Message <?> reply = sendAndReceiveMessage (messagingMessage );
303
- if (reply != null ) {
304
- Address replyTo ;
305
- String replyToProperty = message .getMessageProperties ().getReplyTo ();
306
- if (replyToProperty != null ) {
307
- replyTo = new Address (replyToProperty );
308
- }
309
- else {
310
- replyTo = AmqpInboundGateway .this .defaultReplyTo ;
311
- }
311
+ }
312
312
313
- MessagePostProcessor messagePostProcessor =
314
- message1 -> {
315
- MessageProperties messageProperties = message1 .getMessageProperties ();
316
- String contentEncoding = messageProperties .getContentEncoding ();
317
- long contentLength = messageProperties .getContentLength ();
318
- String contentType = messageProperties .getContentType ();
319
- AmqpInboundGateway .this .headerMapper .fromHeadersToReply (reply .getHeaders (),
320
- messageProperties );
321
- // clear the replyTo from the original message since we are using it now
322
- messageProperties .setReplyTo (null );
323
- // reset the content-* properties as determined by the MessageConverter
324
- if (StringUtils .hasText (contentEncoding )) {
325
- messageProperties .setContentEncoding (contentEncoding );
326
- }
327
- messageProperties .setContentLength (contentLength );
328
- if (contentType != null ) {
329
- messageProperties .setContentType (contentType );
330
- }
331
- return message1 ;
332
- };
333
-
334
- if (replyTo != null ) {
335
- AmqpInboundGateway .this .amqpTemplate .convertAndSend (replyTo .getExchangeName (),
336
- replyTo .getRoutingKey (), reply .getPayload (), messagePostProcessor );
313
+ private void process (Message message , org .springframework .messaging .Message <Object > messagingMessage ) {
314
+ setAttributesIfNecessary (message , messagingMessage );
315
+ final org .springframework .messaging .Message <?> reply = sendAndReceiveMessage (messagingMessage );
316
+ if (reply != null ) {
317
+ Address replyTo ;
318
+ String replyToProperty = message .getMessageProperties ().getReplyTo ();
319
+ if (replyToProperty != null ) {
320
+ replyTo = new Address (replyToProperty );
321
+ }
322
+ else {
323
+ replyTo = AmqpInboundGateway .this .defaultReplyTo ;
324
+ }
325
+
326
+ MessagePostProcessor messagePostProcessor =
327
+ message1 -> {
328
+ MessageProperties messageProperties = message1 .getMessageProperties ();
329
+ String contentEncoding = messageProperties .getContentEncoding ();
330
+ long contentLength = messageProperties .getContentLength ();
331
+ String contentType = messageProperties .getContentType ();
332
+ AmqpInboundGateway .this .headerMapper .fromHeadersToReply (reply .getHeaders (),
333
+ messageProperties );
334
+ // clear the replyTo from the original message since we are using it now
335
+ messageProperties .setReplyTo (null );
336
+ // reset the content-* properties as determined by the MessageConverter
337
+ if (StringUtils .hasText (contentEncoding )) {
338
+ messageProperties .setContentEncoding (contentEncoding );
339
+ }
340
+ messageProperties .setContentLength (contentLength );
341
+ if (contentType != null ) {
342
+ messageProperties .setContentType (contentType );
343
+ }
344
+ return message1 ;
345
+ };
346
+
347
+ if (replyTo != null ) {
348
+ AmqpInboundGateway .this .amqpTemplate .convertAndSend (replyTo .getExchangeName (),
349
+ replyTo .getRoutingKey (), reply .getPayload (), messagePostProcessor );
350
+ }
351
+ else {
352
+ if (!AmqpInboundGateway .this .amqpTemplateExplicitlySet ) {
353
+ throw new IllegalStateException ("There is no 'replyTo' message property " +
354
+ "and the `defaultReplyTo` hasn't been configured." );
337
355
}
338
356
else {
339
- if (!AmqpInboundGateway .this .amqpTemplateExplicitlySet ) {
340
- throw new IllegalStateException ("There is no 'replyTo' message property " +
341
- "and the `defaultReplyTo` hasn't been configured." );
342
- }
343
- else {
344
- AmqpInboundGateway .this .amqpTemplate .convertAndSend (reply .getPayload (),
345
- messagePostProcessor );
346
- }
357
+ AmqpInboundGateway .this .amqpTemplate .convertAndSend (reply .getPayload (),
358
+ messagePostProcessor );
347
359
}
348
360
}
349
361
}
0 commit comments