Skip to content

Commit b79994f

Browse files
garyrussellartembilan
authored andcommitted
Improve Decorated ListenerExecutionFailedException
When decorating a `ListenerExecutionFailedException` with the consumer's group id, add the lost stack trace of the original LEFE in a suppressed exception. This retains the top stack frames which were otherwise lost; suppressed exceptions are printed nested within the stacktrace of the new exception so we can now see the complete stack trace with no loss. ``` Caused by: org.springframework.kafka.listener.ListenerExecutionFailedException: Listener method 'public void com.example.demo.Gitter97Application.listen(java.lang.String)' threw exception; nested exception is java.lang.RuntimeException: x; nested exception is java.lang.RuntimeException: x at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.decorateException(KafkaMessageListenerContainer.java:2487) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:2457) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeOnMessage(KafkaMessageListenerContainer.java:2418) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:2332) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] ... 9 common frames omitted Suppressed: org.springframework.kafka.listener.ListenerExecutionFailedException: Restored Stack Trace at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:363) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:92) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:53) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:2437) ~[spring-kafka-2.8.0-SNAPSHOT.jar:2.8.0-SNAPSHOT] Caused by: java.lang.RuntimeException: x ``` **cherry-pick to 2.7.x**
1 parent 3ae1aea commit b79994f

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2484,14 +2484,51 @@ private RuntimeException decorateException(Exception ex) {
24842484
Exception toHandle = ex;
24852485
if (toHandle instanceof ListenerExecutionFailedException) {
24862486
toHandle = new ListenerExecutionFailedException(toHandle.getMessage(), this.consumerGroupId,
2487-
toHandle.getCause()); // NOSONAR
2487+
toHandle.getCause()); // NOSONAR restored below
2488+
fixStackTrace(ex, toHandle);
24882489
}
24892490
else {
24902491
toHandle = new ListenerExecutionFailedException("Listener failed", this.consumerGroupId, toHandle);
24912492
}
24922493
return (RuntimeException) toHandle;
24932494
}
24942495

2496+
private void fixStackTrace(Exception ex, Exception toHandle) {
2497+
try {
2498+
StackTraceElement[] stackTrace = ex.getStackTrace();
2499+
if (stackTrace != null && stackTrace.length > 0) {
2500+
StackTraceElement[] stackTrace2 = toHandle.getStackTrace();
2501+
if (stackTrace2 != null) {
2502+
int matching = -1;
2503+
for (int i = 0; i < stackTrace2.length; i++) {
2504+
StackTraceElement se2 = stackTrace[i];
2505+
for (StackTraceElement se : stackTrace2) {
2506+
if (se2.equals(se)) {
2507+
matching = i;
2508+
break;
2509+
}
2510+
}
2511+
if (matching >= 0) {
2512+
break;
2513+
}
2514+
}
2515+
if (matching >= 0) {
2516+
StackTraceElement[] merged = new StackTraceElement[matching];
2517+
System.arraycopy(stackTrace, 0, merged, 0, matching);
2518+
ListenerExecutionFailedException suppressed =
2519+
new ListenerExecutionFailedException("Restored Stack Trace");
2520+
suppressed.setStackTrace(merged);
2521+
toHandle.addSuppressed(suppressed);
2522+
}
2523+
}
2524+
}
2525+
}
2526+
catch (Exception ex2) {
2527+
this.logger.debug(ex2,
2528+
"Could not restore the stack trace when decorating the LEFE with the group id");
2529+
}
2530+
}
2531+
24952532
public void checkDeser(final ConsumerRecord<K, V> record, String headerName) {
24962533
DeserializationException exception = ListenerUtils.getExceptionFromHeader(record, headerName, this.logger);
24972534
if (exception != null) {

0 commit comments

Comments
 (0)