diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java index 59e9606e2d..ef9643632f 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java @@ -30,7 +30,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.codec.Decoder; import org.springframework.lang.Nullable; -import org.springframework.messaging.rsocket.annotation.support.AnnotationClientResponderConfigurer; +import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; import org.springframework.util.MimeType; /** @@ -165,14 +165,15 @@ public interface RSocketRequester { /** * Callback to configure the {@code ClientRSocketFactory} directly. - *

See {@link AnnotationClientResponderConfigurer} for configuring a - * client side responder. + *

See static factory method + * {@link RSocketMessageHandler#clientResponder(Object...)} for + * configuring a client side responder with annotated methods. *

Note: Do not set {@link #dataMimeType(MimeType)} * and {@link #metadataMimeType(MimeType)} directly on the * {@code ClientRSocketFactory}. Use the shortcuts on this builder * instead since the created {@code RSocketRequester} needs to be aware * of those settings. - * @see AnnotationClientResponderConfigurer + * @see RSocketMessageHandler#clientResponder(Object...) */ RSocketRequester.Builder rsocketFactory(ClientRSocketFactoryConfigurer configurer); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java deleted file mode 100644 index aadc3405ab..0000000000 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.messaging.rsocket.annotation.support; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.rsocket.RSocketFactory; - -import org.springframework.beans.BeanUtils; -import org.springframework.lang.Nullable; -import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.util.Assert; - -/** - * {@link ClientRSocketFactoryConfigurer} to configure and plug in a responder - * that handles requests via annotated handler methods. Effectively a thin layer over - * {@link RSocketMessageHandler} that provides a programmatic way to configure - * it and obtain a responder via {@link RSocketMessageHandler#clientResponder() - * clientResponder()}. - * - * @author Rossen Stoyanchev - * @since 5.2 - */ -public final class AnnotationClientResponderConfigurer implements ClientRSocketFactoryConfigurer { - - private final List handlers = new ArrayList<>(); - - @Nullable - private RSocketStrategies strategies; - - - private AnnotationClientResponderConfigurer(List handlers) { - for (Object obj : handlers) { - this.handlers.add(obj instanceof Class ? BeanUtils.instantiateClass((Class) obj) : obj); - } - } - - - /** - * Configure handlers to detect {@code @MessasgeMapping} handler methods on. - * This is used to set {@link RSocketMessageHandler#setHandlers(List)}. - */ - public AnnotationClientResponderConfigurer handlers(Object... handlers) { - this.handlers.addAll(Arrays.asList(handlers)); - return this; - } - - - // Implementation of ClientRSocketFactoryConfigurer - - @Override - public void configureWithStrategies(RSocketStrategies strategies) { - this.strategies = strategies; - } - - @Override - public void configure(RSocketFactory.ClientRSocketFactory factory) { - Assert.notEmpty(this.handlers, "No handlers"); - RSocketMessageHandler messageHandler = new RSocketMessageHandler(); - messageHandler.setHandlers(this.handlers); - messageHandler.setRSocketStrategies(this.strategies); - messageHandler.afterPropertiesSet(); - factory.acceptor(messageHandler.clientResponder()); - } - - - // Static factory methods - - /** - * Create an {@code AnnotationClientResponderConfigurer} with the given handlers - * to check for {@code @MessasgeMapping} handler methods. - */ - public static AnnotationClientResponderConfigurer withHandlers(Object... handlers) { - return new AnnotationClientResponderConfigurer(Arrays.asList(handlers)); - } - - /** - * Create an {@code AnnotationClientResponderConfigurer} to set up further. - */ - public static AnnotationClientResponderConfigurer create() { - return new AnnotationClientResponderConfigurer(Collections.emptyList()); - } - -} diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java index a595e73566..e817ea9885 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java @@ -24,10 +24,12 @@ import java.util.function.Function; import io.rsocket.ConnectionSetupPayload; import io.rsocket.RSocket; +import io.rsocket.RSocketFactory; import io.rsocket.SocketAcceptor; import io.rsocket.frame.FrameType; import reactor.core.publisher.Mono; +import org.springframework.beans.BeanUtils; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.codec.Decoder; @@ -40,6 +42,7 @@ import org.springframework.messaging.handler.DestinationPatternsMessageCondition import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.reactive.MessageMappingMessageHandler; import org.springframework.messaging.handler.invocation.reactive.HandlerMethodReturnValueHandler; +import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer; import org.springframework.messaging.rsocket.DefaultMetadataExtractor; import org.springframework.messaging.rsocket.MetadataExtractor; import org.springframework.messaging.rsocket.RSocketRequester; @@ -324,10 +327,50 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler { Assert.notNull(strategies, "No RSocketStrategies. Was afterPropertiesSet not called?"); RSocketRequester requester = RSocketRequester.wrap(rsocket, dataMimeType, metadataMimeType, strategies); - Assert.notNull(this.metadataExtractor, () -> "No MetadataExtractor. Was afterPropertiesSet not called?"); + Assert.state(this.metadataExtractor != null, + () -> "No MetadataExtractor. Was afterPropertiesSet not called?"); + + Assert.state(getRouteMatcher() != null, + () -> "No RouteMatcher. Was afterPropertiesSet not called?"); return new MessagingRSocket(dataMimeType, metadataMimeType, this.metadataExtractor, requester, this, getRouteMatcher(), strategies); } + + public static ClientRSocketFactoryConfigurer clientResponder(Object... handlers) { + return new ResponderConfigurer(handlers); + } + + + private static final class ResponderConfigurer implements ClientRSocketFactoryConfigurer { + + private final List handlers = new ArrayList<>(); + + @Nullable + private RSocketStrategies strategies; + + + private ResponderConfigurer(Object... handlers) { + Assert.notEmpty(handlers, "No handlers"); + for (Object obj : handlers) { + this.handlers.add(obj instanceof Class ? BeanUtils.instantiateClass((Class) obj) : obj); + } + } + + @Override + public void configureWithStrategies(RSocketStrategies strategies) { + this.strategies = strategies; + } + + @Override + public void configure(RSocketFactory.ClientRSocketFactory factory) { + RSocketMessageHandler handler = new RSocketMessageHandler(); + handler.setHandlers(this.handlers); + handler.setRSocketStrategies(this.strategies); + handler.afterPropertiesSet(); + factory.acceptor(handler.clientResponder()); + } + } + } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/RSocketServerToClientIntegrationTests.java b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/RSocketServerToClientIntegrationTests.java index c153112436..818ccdd0f5 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/RSocketServerToClientIntegrationTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/RSocketServerToClientIntegrationTests.java @@ -39,7 +39,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.rsocket.annotation.ConnectMapping; -import org.springframework.messaging.rsocket.annotation.support.AnnotationClientResponderConfigurer; import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; import org.springframework.stereotype.Controller; @@ -111,7 +110,7 @@ public class RSocketServerToClientIntegrationTests { factory.metadataMimeType("text/plain"); factory.setupPayload(ByteBufPayload.create("", connectionRoute)); }) - .rsocketFactory(AnnotationClientResponderConfigurer.withHandlers(new ClientHandler())) + .rsocketFactory(RSocketMessageHandler.clientResponder(new ClientHandler())) .rsocketStrategies(context.getBean(RSocketStrategies.class)) .connectTcp("localhost", server.address().getPort()) .block();