Skip to content

Commit e39be7e

Browse files
garyrussellartembilan
authored andcommitted
GH-948: Decorate LEFE for batch listeners
See #948 Also add the groupId for batch listeners, for consistency.
1 parent 2907f9c commit e39be7e

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

spring-kafka/src/main/java/org/springframework/kafka/listener/KafkaMessageListenerContainer.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,10 +1077,11 @@ private void invokeBatchErrorHandler(final ConsumerRecords<K, V> records,
10771077
@SuppressWarnings(RAW_TYPES) @Nullable Producer producer, RuntimeException e) {
10781078

10791079
if (this.batchErrorHandler instanceof ContainerAwareBatchErrorHandler) {
1080-
this.batchErrorHandler.handle(e, records, this.consumer, KafkaMessageListenerContainer.this.container);
1080+
this.batchErrorHandler.handle(decorateException(e), records, this.consumer,
1081+
KafkaMessageListenerContainer.this.container);
10811082
}
10821083
else {
1083-
this.batchErrorHandler.handle(e, records, this.consumer);
1084+
this.batchErrorHandler.handle(decorateException(e), records, this.consumer);
10841085
}
10851086
// if the handler handled the error (no exception), go ahead and commit
10861087
if (producer != null) {
@@ -1243,18 +1244,6 @@ private void invokeErrorHandler(final ConsumerRecord<K, V> record,
12431244
@SuppressWarnings(RAWTYPES) @Nullable Producer producer,
12441245
Iterator<ConsumerRecord<K, V>> iterator, RuntimeException e) {
12451246

1246-
Exception toHandle = e;
1247-
if (toHandle instanceof ListenerExecutionFailedException) {
1248-
toHandle = new ListenerExecutionFailedException(toHandle.getMessage(), this.consumerGroupId,
1249-
toHandle.getCause());
1250-
}
1251-
else {
1252-
/*
1253-
* TODO: in 2.3, wrap all exceptions (e.g. thrown by user implementations
1254-
* of MessageListener) in LEFE with groupId. @KafkaListeners always throw
1255-
* LEFE.
1256-
*/
1257-
}
12581247
if (this.errorHandler instanceof RemainingRecordsErrorHandler) {
12591248
if (producer == null) {
12601249
processCommits();
@@ -1264,17 +1253,33 @@ private void invokeErrorHandler(final ConsumerRecord<K, V> record,
12641253
while (iterator.hasNext()) {
12651254
records.add(iterator.next());
12661255
}
1267-
((RemainingRecordsErrorHandler) this.errorHandler).handle(toHandle, records, this.consumer,
1256+
((RemainingRecordsErrorHandler) this.errorHandler).handle(decorateException(e), records, this.consumer,
12681257
KafkaMessageListenerContainer.this.container);
12691258
}
12701259
else {
1271-
this.errorHandler.handle(toHandle, record, this.consumer);
1260+
this.errorHandler.handle(decorateException(e), record, this.consumer);
12721261
}
12731262
if (producer != null) {
12741263
ackCurrent(record, producer);
12751264
}
12761265
}
12771266

1267+
private Exception decorateException(RuntimeException e) {
1268+
Exception toHandle = e;
1269+
if (toHandle instanceof ListenerExecutionFailedException) {
1270+
toHandle = new ListenerExecutionFailedException(toHandle.getMessage(), this.consumerGroupId,
1271+
toHandle.getCause());
1272+
}
1273+
else {
1274+
/*
1275+
* TODO: in 2.3, wrap all exceptions (e.g. thrown by user implementations
1276+
* of MessageListener) in LEFE with groupId. @KafkaListeners always throw
1277+
* LEFE.
1278+
*/
1279+
}
1280+
return toHandle;
1281+
}
1282+
12781283
public void checkDeser(final ConsumerRecord<K, V> record, String headerName) {
12791284
Header header = record.headers().lastHeader(headerName);
12801285
if (header != null) {

spring-kafka/src/test/java/org/springframework/kafka/listener/SeekToCurrentBatchErrorHandlerTests.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2018 the original author or authors.
2+
* Copyright 2017-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -112,6 +112,8 @@ public void discardRemainingRecordsFromPollAndSeek() throws Exception {
112112
offsets.put(new TopicPartition("foo", 2), new OffsetAndMetadata(2L));
113113
inOrder.verify(this.producer).sendOffsetsToTransaction(offsets, CONTAINER_ID);
114114
inOrder.verify(this.producer).commitTransaction();
115+
assertThat(this.config.ehException).isInstanceOf(ListenerExecutionFailedException.class);
116+
assertThat(((ListenerExecutionFailedException) this.config.ehException).getGroupId()).isEqualTo(CONTAINER_ID);
115117
}
116118

117119
@Configuration
@@ -126,6 +128,8 @@ public static class Config {
126128

127129
private final AtomicBoolean fail = new AtomicBoolean(true);
128130

131+
private volatile Exception ehException;
132+
129133
@KafkaListener(id = CONTAINER_ID, topics = "foo")
130134
public void foo(List<String> in) {
131135
this.deliveryLatch.countDown();
@@ -195,7 +199,17 @@ public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() {
195199
ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
196200
factory.setConsumerFactory(consumerFactory());
197201
factory.getContainerProperties().setAckOnError(false);
198-
factory.setBatchErrorHandler(new SeekToCurrentBatchErrorHandler());
202+
factory.setBatchErrorHandler(new SeekToCurrentBatchErrorHandler() {
203+
204+
@Override
205+
public void handle(Exception thrownException, ConsumerRecords<?, ?> data, Consumer<?, ?> consumer,
206+
MessageListenerContainer container) {
207+
208+
Config.this.ehException = thrownException;
209+
super.handle(thrownException, data, consumer, container);
210+
}
211+
212+
});
199213
factory.setBatchListener(true);
200214
factory.getContainerProperties().setTransactionManager(tm());
201215
return factory;

0 commit comments

Comments
 (0)