Add native support for @SubscribeMapping and @MessageExceptionHandler

Closes gh-30002
This commit is contained in:
Sébastien Deleuze
2023-02-21 18:47:30 +01:00
parent 3d8455b257
commit 626a7fc52a
4 changed files with 66 additions and 17 deletions

View File

@@ -22,6 +22,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.aot.hint.annotation.Reflective;
/**
* Annotation for handling exceptions thrown from message-handling methods within a
* specific handler class.
@@ -32,6 +34,7 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective(MessageMappingReflectiveProcessor.class)
public @interface MessageExceptionHandler {
/**

View File

@@ -30,23 +30,28 @@ import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.messaging.support.MessageHeaderAccessor;
/**
* {@link ReflectiveProcessor} implementation for {@link MessageMapping}
* annotated types. In addition to registering reflection hints for invoking
* {@link ReflectiveProcessor} implementation for types annotated
* with {@link MessageMapping @MessageMapping},
* {@link SubscribeMapping @SubscribeMapping}
* and {@link MessageExceptionHandler @MessageExceptionHandler}.
* In addition to registering reflection hints for invoking
* the annotated method, this implementation handles:
*
* <ul>
* <li>Return types</li>
* <li>Parameters identified as potential payloads</li>
* <li>{@link Message} parameters</li>
* <li>Exception classes specified via {@link MessageExceptionHandler @MessageExceptionHandler}</li>
* </ul>
*
* @author Sebastien Deleuze
* @since 6.0
*/
class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
public class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
@@ -58,6 +63,9 @@ class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
}
else if (element instanceof Method method) {
registerMethodHints(hints, method);
if (element.isAnnotationPresent(MessageExceptionHandler.class)) {
registerMessageExceptionHandlerHints(hints, element.getAnnotation(MessageExceptionHandler.class));
}
}
}
@@ -84,6 +92,12 @@ class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
}
}
protected void registerMessageExceptionHandlerHints(ReflectionHints hints, MessageExceptionHandler annotation) {
for (Class<?> exceptionClass : annotation.value()) {
hints.registerType(exceptionClass);
}
}
protected boolean couldBePayload(MethodParameter methodParameter) {
return !methodParameter.hasParameterAnnotation(DestinationVariable.class) &&
!methodParameter.hasParameterAnnotation(Header.class) &&

View File

@@ -22,6 +22,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.messaging.handler.annotation.MessageMappingReflectiveProcessor;
/**
* Annotation for mapping subscription messages onto specific handler methods based
* on the destination of a subscription. Supported with STOMP over WebSocket only
@@ -54,6 +57,7 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective(MessageMappingReflectiveProcessor.class)
public @interface SubscribeMapping {
/**