|
23 | 23 | import java.util.Map;
|
24 | 24 | import java.util.Set;
|
25 | 25 | import java.util.TreeSet;
|
| 26 | +import java.util.concurrent.CompletableFuture; |
26 | 27 | import java.util.concurrent.ExecutionException;
|
27 | 28 | import java.util.concurrent.Future;
|
28 | 29 | import java.util.concurrent.TimeUnit;
|
29 | 30 | import java.util.concurrent.TimeoutException;
|
30 | 31 | import java.util.concurrent.atomic.AtomicBoolean;
|
31 | 32 |
|
32 |
| -import org.apache.kafka.clients.consumer.ConsumerRecord; |
33 | 33 | import org.apache.kafka.clients.producer.ProducerConfig;
|
34 | 34 | import org.apache.kafka.clients.producer.ProducerRecord;
|
35 | 35 | import org.apache.kafka.common.TopicPartition;
|
|
69 | 69 | import org.springframework.messaging.MessageHeaders;
|
70 | 70 | import org.springframework.util.Assert;
|
71 | 71 | import org.springframework.util.StringUtils;
|
72 |
| -import org.springframework.util.concurrent.ListenableFuture; |
73 |
| -import org.springframework.util.concurrent.ListenableFutureCallback; |
74 |
| -import org.springframework.util.concurrent.SettableListenableFuture; |
75 | 72 |
|
76 | 73 | /**
|
77 | 74 | * A Message Handler for Apache Kafka; when supplied with a {@link ReplyingKafkaTemplate} it is used as
|
@@ -174,7 +171,7 @@ public KafkaProducerMessageHandler(final KafkaTemplate<K, V> kafkaTemplate) {
|
174 | 171 | if (this.isGateway) {
|
175 | 172 | setAsync(true);
|
176 | 173 | updateNotPropagatedHeaders(
|
177 |
| - new String[]{KafkaHeaders.TOPIC, KafkaHeaders.PARTITION, KafkaHeaders.KEY}, false); |
| 174 | + new String[]{ KafkaHeaders.TOPIC, KafkaHeaders.PARTITION, KafkaHeaders.KEY }, false); |
178 | 175 | }
|
179 | 176 | if (JacksonPresent.isJackson2Present()) {
|
180 | 177 | this.headerMapper = new DefaultKafkaHeaderMapper();
|
@@ -498,7 +495,7 @@ protected Object handleRequestMessage(final Message<?> message) {
|
498 | 495 | if (futureToken != null) {
|
499 | 496 | producerRecord.headers().remove(KafkaIntegrationHeaders.FUTURE_TOKEN);
|
500 | 497 | }
|
501 |
| - ListenableFuture<SendResult<K, V>> sendFuture; |
| 498 | + CompletableFuture<SendResult<K, V>> sendFuture; |
502 | 499 | RequestReplyFuture<K, V, Object> gatewayFuture = null;
|
503 | 500 | if (this.isGateway && (!preBuilt || producerRecord.headers().lastHeader(KafkaHeaders.REPLY_TOPIC) == null)) {
|
504 | 501 | producerRecord.headers().add(new RecordHeader(KafkaHeaders.REPLY_TOPIC, getReplyTopic(message)));
|
@@ -530,7 +527,7 @@ protected Object handleRequestMessage(final Message<?> message) {
|
530 | 527 | return processReplyFuture(gatewayFuture);
|
531 | 528 | }
|
532 | 529 |
|
533 |
| - private void sendFutureIfRequested(ListenableFuture<SendResult<K, V>> sendFuture, Object futureToken) { |
| 530 | + private void sendFutureIfRequested(CompletableFuture<SendResult<K, V>> sendFuture, Object futureToken) { |
534 | 531 |
|
535 | 532 | if (futureToken != null) {
|
536 | 533 | MessageChannel futures = getFuturesChannel();
|
@@ -662,31 +659,26 @@ private void determineValidReplyTopicsAndPartitions() {
|
662 | 659 | }
|
663 | 660 |
|
664 | 661 | public void processSendResult(final Message<?> message, final ProducerRecord<K, V> producerRecord,
|
665 |
| - ListenableFuture<SendResult<K, V>> future, MessageChannel metadataChannel) |
| 662 | + CompletableFuture<SendResult<K, V>> future, MessageChannel metadataChannel) |
666 | 663 | throws InterruptedException, ExecutionException {
|
667 | 664 |
|
668 | 665 | final MessageChannel failureChannel = getSendFailureChannel();
|
669 | 666 | if (failureChannel != null || metadataChannel != null) {
|
670 |
| - future.addCallback(new ListenableFutureCallback<SendResult<K, V>>() { // NOSONAR |
671 |
| - |
672 |
| - @Override |
673 |
| - public void onSuccess(SendResult<K, V> result) { |
| 667 | + future.whenComplete((sendResult, exception) -> { |
| 668 | + if (exception == null) { |
674 | 669 | if (metadataChannel != null) {
|
675 | 670 | KafkaProducerMessageHandler.this.messagingTemplate.send(metadataChannel,
|
676 |
| - getMessageBuilderFactory().fromMessage(message) |
677 |
| - .setHeader(KafkaHeaders.RECORD_METADATA, result.getRecordMetadata()).build()); |
| 671 | + getMessageBuilderFactory() |
| 672 | + .fromMessage(message) |
| 673 | + .setHeader(KafkaHeaders.RECORD_METADATA, sendResult.getRecordMetadata()) |
| 674 | + .build()); |
678 | 675 | }
|
679 | 676 | }
|
680 |
| - |
681 |
| - @Override |
682 |
| - public void onFailure(Throwable ex) { |
683 |
| - if (failureChannel != null) { |
684 |
| - KafkaProducerMessageHandler.this.messagingTemplate.send(failureChannel, |
685 |
| - KafkaProducerMessageHandler.this.errorMessageStrategy.buildErrorMessage( |
686 |
| - new KafkaSendFailureException(message, producerRecord, ex), null)); |
687 |
| - } |
| 677 | + else if (failureChannel != null) { |
| 678 | + KafkaProducerMessageHandler.this.messagingTemplate.send(failureChannel, |
| 679 | + KafkaProducerMessageHandler.this.errorMessageStrategy.buildErrorMessage( |
| 680 | + new KafkaSendFailureException(message, producerRecord, exception), null)); |
688 | 681 | }
|
689 |
| - |
690 | 682 | });
|
691 | 683 | }
|
692 | 684 |
|
@@ -720,51 +712,47 @@ private Future<?> processReplyFuture(@Nullable RequestReplyFuture<?, ?, Object>
|
720 | 712 | return new ConvertingReplyFuture(future);
|
721 | 713 | }
|
722 | 714 |
|
723 |
| - private final class ConvertingReplyFuture extends SettableListenableFuture<Object> { |
| 715 | + private final class ConvertingReplyFuture extends CompletableFuture<Object> { |
724 | 716 |
|
725 | 717 | ConvertingReplyFuture(RequestReplyFuture<?, ?, Object> future) {
|
726 | 718 | addCallback(future);
|
727 | 719 | }
|
728 | 720 |
|
729 | 721 | private void addCallback(final RequestReplyFuture<?, ?, Object> future) {
|
730 |
| - future.addCallback(new ListenableFutureCallback<ConsumerRecord<?, Object>>() { // NOSONAR |
731 |
| - |
732 |
| - @Override |
733 |
| - public void onSuccess(ConsumerRecord<?, Object> result) { |
| 722 | + future.whenComplete((result, exception) -> { |
| 723 | + if (exception == null) { |
734 | 724 | try {
|
735 |
| - set(dontLeakHeaders(KafkaProducerMessageHandler.this.replyMessageConverter.toMessage(result, |
736 |
| - null, null, KafkaProducerMessageHandler.this.replyPayloadType))); |
737 |
| - } |
738 |
| - catch (Exception e) { |
739 |
| - setException(e); |
740 |
| - } |
741 |
| - } |
742 |
| - |
743 |
| - private Message<?> dontLeakHeaders(Message<?> message) { |
744 |
| - if (message.getHeaders() instanceof KafkaMessageHeaders) { |
745 |
| - Map<String, Object> headers = ((KafkaMessageHeaders) message.getHeaders()).getRawHeaders(); |
746 |
| - headers.remove(KafkaHeaders.CORRELATION_ID); |
747 |
| - headers.remove(KafkaHeaders.REPLY_TOPIC); |
748 |
| - headers.remove(KafkaHeaders.REPLY_PARTITION); |
749 |
| - return message; |
| 725 | + complete(dontLeakHeaders( |
| 726 | + KafkaProducerMessageHandler.this.replyMessageConverter.toMessage(result, null, null, |
| 727 | + KafkaProducerMessageHandler.this.replyPayloadType))); |
750 | 728 | }
|
751 |
| - else { |
752 |
| - return getMessageBuilderFactory().fromMessage(message) |
753 |
| - .removeHeader(KafkaHeaders.CORRELATION_ID) |
754 |
| - .removeHeader(KafkaHeaders.REPLY_TOPIC) |
755 |
| - .removeHeader(KafkaHeaders.REPLY_PARTITION) |
756 |
| - .build(); |
| 729 | + catch (Exception ex) { |
| 730 | + completeExceptionally(ex); |
757 | 731 | }
|
758 | 732 | }
|
759 |
| - |
760 |
| - @Override |
761 |
| - public void onFailure(Throwable ex) { |
762 |
| - setException(ex); |
| 733 | + else { |
| 734 | + completeExceptionally(exception); |
763 | 735 | }
|
764 |
| - |
765 | 736 | });
|
766 | 737 | }
|
767 | 738 |
|
| 739 | + private Message<?> dontLeakHeaders(Message<?> message) { |
| 740 | + if (message.getHeaders() instanceof KafkaMessageHeaders) { |
| 741 | + Map<String, Object> headers = ((KafkaMessageHeaders) message.getHeaders()).getRawHeaders(); |
| 742 | + headers.remove(KafkaHeaders.CORRELATION_ID); |
| 743 | + headers.remove(KafkaHeaders.REPLY_TOPIC); |
| 744 | + headers.remove(KafkaHeaders.REPLY_PARTITION); |
| 745 | + return message; |
| 746 | + } |
| 747 | + else { |
| 748 | + return getMessageBuilderFactory().fromMessage(message) |
| 749 | + .removeHeader(KafkaHeaders.CORRELATION_ID) |
| 750 | + .removeHeader(KafkaHeaders.REPLY_TOPIC) |
| 751 | + .removeHeader(KafkaHeaders.REPLY_PARTITION) |
| 752 | + .build(); |
| 753 | + } |
| 754 | + } |
| 755 | + |
768 | 756 | }
|
769 | 757 |
|
770 | 758 | /**
|
|
0 commit comments