Skip to content

Commit 4ac27e4

Browse files
committed
Suppress ClassCastException for payload type mismatch as well
Closes gh-26349
1 parent b0abdee commit 4ac27e4

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

spring-context/src/main/java/org/springframework/context/PayloadApplicationEvent.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -16,18 +16,21 @@
1616

1717
package org.springframework.context;
1818

19+
import java.util.function.Consumer;
20+
1921
import org.springframework.core.ResolvableType;
2022
import org.springframework.core.ResolvableTypeProvider;
2123
import org.springframework.util.Assert;
2224

2325
/**
2426
* An {@link ApplicationEvent} that carries an arbitrary payload.
2527
*
26-
* <p>Mainly intended for internal use within the framework.
27-
*
2828
* @author Stephane Nicoll
29+
* @author Juergen Hoeller
2930
* @since 4.2
3031
* @param <T> the payload type of the event
32+
* @see ApplicationEventPublisher#publishEvent(Object)
33+
* @see ApplicationListener#forPayload(Consumer)
3134
*/
3235
@SuppressWarnings("serial")
3336
public class PayloadApplicationEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {

spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -24,6 +24,7 @@
2424
import org.springframework.beans.factory.BeanFactory;
2525
import org.springframework.context.ApplicationEvent;
2626
import org.springframework.context.ApplicationListener;
27+
import org.springframework.context.PayloadApplicationEvent;
2728
import org.springframework.core.ResolvableType;
2829
import org.springframework.lang.Nullable;
2930
import org.springframework.util.ErrorHandler;
@@ -55,6 +56,9 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
5556
@Nullable
5657
private ErrorHandler errorHandler;
5758

59+
@Nullable
60+
private volatile Log lazyLogger;
61+
5862

5963
/**
6064
* Create a new SimpleApplicationEventMulticaster.
@@ -173,12 +177,18 @@ private void doInvokeListener(ApplicationListener listener, ApplicationEvent eve
173177
}
174178
catch (ClassCastException ex) {
175179
String msg = ex.getMessage();
176-
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
180+
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
181+
(event instanceof PayloadApplicationEvent &&
182+
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
177183
// Possibly a lambda-defined listener which we could not resolve the generic event type for
178-
// -> let's suppress the exception and just log a debug message.
179-
Log logger = LogFactory.getLog(getClass());
180-
if (logger.isTraceEnabled()) {
181-
logger.trace("Non-matching event type for listener: " + listener, ex);
184+
// -> let's suppress the exception.
185+
Log loggerToUse = this.lazyLogger;
186+
if (loggerToUse == null) {
187+
loggerToUse = LogFactory.getLog(getClass());
188+
this.lazyLogger = loggerToUse;
189+
}
190+
if (loggerToUse.isTraceEnabled()) {
191+
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
182192
}
183193
}
184194
else {

spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -49,9 +49,11 @@ public void testEventClassWithInterface() {
4949
public void testProgrammaticEventListener() {
5050
List<Auditable> events = new ArrayList<>();
5151
ApplicationListener<AuditablePayloadEvent<String>> listener = events::add;
52+
ApplicationListener<AuditablePayloadEvent<Integer>> mismatch = (event -> event.getPayload().intValue());
5253

5354
ConfigurableApplicationContext ac = new GenericApplicationContext();
5455
ac.addApplicationListener(listener);
56+
ac.addApplicationListener(mismatch);
5557
ac.refresh();
5658

5759
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
@@ -63,9 +65,11 @@ public void testProgrammaticEventListener() {
6365
public void testProgrammaticPayloadListener() {
6466
List<String> events = new ArrayList<>();
6567
ApplicationListener<PayloadApplicationEvent<String>> listener = ApplicationListener.forPayload(events::add);
68+
ApplicationListener<PayloadApplicationEvent<Integer>> mismatch = ApplicationListener.forPayload(payload -> payload.intValue());
6669

6770
ConfigurableApplicationContext ac = new GenericApplicationContext();
6871
ac.addApplicationListener(listener);
72+
ac.addApplicationListener(mismatch);
6973
ac.refresh();
7074

7175
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");

0 commit comments

Comments
 (0)