Properly analyze Java 9 class cast messages for lambda event listeners
Issue: SPR-16435
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -173,8 +173,9 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
|||||||
}
|
}
|
||||||
catch (ClassCastException ex) {
|
catch (ClassCastException ex) {
|
||||||
String msg = ex.getMessage();
|
String msg = ex.getMessage();
|
||||||
if (msg == null || msg.startsWith(event.getClass().getName())) {
|
if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) {
|
||||||
// Possibly a lambda-defined listener which we could not resolve the generic event type for
|
// Possibly a lambda-defined listener which we could not resolve the generic event type for
|
||||||
|
// -> let's suppress the exception and just log a debug message.
|
||||||
Log logger = LogFactory.getLog(getClass());
|
Log logger = LogFactory.getLog(getClass());
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Non-matching event type for listener: " + listener, ex);
|
logger.debug("Non-matching event type for listener: " + listener, ex);
|
||||||
@@ -186,4 +187,18 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean matchesClassCastMessage(String classCastMessage, String eventClassName) {
|
||||||
|
// On Java 8, the message simply starts with the class name: "java.lang.String cannot be cast..."
|
||||||
|
if (classCastMessage.startsWith(eventClassName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// On Java 9, the message contains the module name: "java.base/java.lang.String cannot be cast..."
|
||||||
|
int moduleSeparatorIndex = classCastMessage.indexOf('/');
|
||||||
|
if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClassName, moduleSeparatorIndex + 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Assuming an unrelated class cast failure...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -472,6 +472,30 @@ public class ApplicationContextEventTests extends AbstractApplicationEventListen
|
|||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void lambdaAsListenerWithJava8StyleClassCastMessage() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
|
ApplicationListener<ApplicationEvent> listener =
|
||||||
|
event -> { throw new ClassCastException(event.getClass().getName()); };
|
||||||
|
context.addApplicationListener(listener);
|
||||||
|
context.refresh();
|
||||||
|
|
||||||
|
context.publishEvent(new MyEvent(context));
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void lambdaAsListenerWithJava9StyleClassCastMessage() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
|
ApplicationListener<ApplicationEvent> listener =
|
||||||
|
event -> { throw new ClassCastException("spring.context/" + event.getClass().getName()); };
|
||||||
|
context.addApplicationListener(listener);
|
||||||
|
context.refresh();
|
||||||
|
|
||||||
|
context.publishEvent(new MyEvent(context));
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void beanPostProcessorPublishesEvents() {
|
public void beanPostProcessorPublishesEvents() {
|
||||||
GenericApplicationContext context = new GenericApplicationContext();
|
GenericApplicationContext context = new GenericApplicationContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user