Skip to content

Commit d2a7d9f

Browse files
committed
Introduce RSocketClientFactoryConfigurer
The new interface supersedes ClientResponderFactory and is more general, for any RSocketFactory customization. DefaultClientResponderFactory implements the new interface and is renamed to AnnotationClientResponderConfigurer. See gh-23170
1 parent 1e9ccdd commit d2a7d9f

File tree

8 files changed

+219
-254
lines changed

8 files changed

+219
-254
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.messaging.rsocket;
17+
18+
import io.rsocket.RSocketFactory;
19+
20+
/**
21+
* Strategy to apply some configuration to a
22+
* {@link io.rsocket.RSocketFactory.ClientRSocketFactory ClientRSocketFactory}.
23+
* It is given to {@link RSocketRequester.Builder} to initialize the
24+
* {@code RSocketFactory} that's used to connect.
25+
*
26+
* @author Rossen Stoyanchev
27+
* @since 5.2
28+
*/
29+
@FunctionalInterface
30+
public interface ClientRSocketFactoryConfigurer {
31+
32+
/**
33+
* This method is invoked by {@link RSocketRequester.Builder} immediately
34+
* before the call to {@link #configure}, and can be used by implementations
35+
* of this interface that need access to the configured
36+
* {@code RSocketStrategies}.
37+
*/
38+
default void configureWithStrategies(RSocketStrategies strategies) {
39+
}
40+
41+
/**
42+
* Configure the given {@code ClientRSocketFactory}.
43+
* @param rsocketFactory the factory to configure
44+
*/
45+
void configure(RSocketFactory.ClientRSocketFactory rsocketFactory);
46+
47+
}

spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilder.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
4747

4848
private MimeType metadataMimeType = DefaultRSocketRequester.COMPOSITE_METADATA;
4949

50-
private List<Consumer<RSocketFactory.ClientRSocketFactory>> factoryConfigurers = new ArrayList<>();
51-
5250
@Nullable
5351
private RSocketStrategies strategies;
5452

5553
private List<Consumer<RSocketStrategies.Builder>> strategiesConfigurers = new ArrayList<>();
5654

55+
private List<ClientRSocketFactoryConfigurer> rsocketFactoryConfigurers = new ArrayList<>();
56+
5757

5858
@Override
5959
public RSocketRequester.Builder dataMimeType(@Nullable MimeType mimeType) {
@@ -68,12 +68,6 @@ public RSocketRequester.Builder metadataMimeType(MimeType mimeType) {
6868
return this;
6969
}
7070

71-
@Override
72-
public RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer) {
73-
this.factoryConfigurers.add(configurer);
74-
return this;
75-
}
76-
7771
@Override
7872
public RSocketRequester.Builder rsocketStrategies(@Nullable RSocketStrategies strategies) {
7973
this.strategies = strategies;
@@ -86,6 +80,12 @@ public RSocketRequester.Builder rsocketStrategies(Consumer<RSocketStrategies.Bui
8680
return this;
8781
}
8882

83+
@Override
84+
public RSocketRequester.Builder rsocketFactory(ClientRSocketFactoryConfigurer configurer) {
85+
this.rsocketFactoryConfigurers.add(configurer);
86+
return this;
87+
}
88+
8989
@Override
9090
public Mono<RSocketRequester> connectTcp(String host, int port) {
9191
return connect(TcpClientTransport.create(host, port));
@@ -110,9 +110,12 @@ private Mono<RSocketRequester> doConnect(ClientTransport transport) {
110110
MimeType dataMimeType = getDataMimeType(rsocketStrategies);
111111
rsocketFactory.dataMimeType(dataMimeType.toString());
112112
rsocketFactory.metadataMimeType(this.metadataMimeType.toString());
113-
114113
rsocketFactory.frameDecoder(PayloadDecoder.ZERO_COPY);
115-
this.factoryConfigurers.forEach(consumer -> consumer.accept(rsocketFactory));
114+
115+
this.rsocketFactoryConfigurers.forEach(configurer -> {
116+
configurer.configureWithStrategies(rsocketStrategies);
117+
configurer.configure(rsocketFactory);
118+
});
116119

117120
return rsocketFactory.transport(transport)
118121
.start()

spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import io.rsocket.ConnectionSetupPayload;
2323
import io.rsocket.RSocket;
24-
import io.rsocket.RSocketFactory;
2524
import io.rsocket.transport.ClientTransport;
2625
import org.reactivestreams.Publisher;
2726
import reactor.core.publisher.Flux;
@@ -30,6 +29,7 @@
3029
import org.springframework.core.ParameterizedTypeReference;
3130
import org.springframework.core.ReactiveAdapterRegistry;
3231
import org.springframework.lang.Nullable;
32+
import org.springframework.messaging.rsocket.annotation.support.AnnotationClientResponderConfigurer;
3333
import org.springframework.util.MimeType;
3434

3535
/**
@@ -141,18 +141,6 @@ interface Builder {
141141
*/
142142
RSocketRequester.Builder metadataMimeType(MimeType mimeType);
143143

144-
/**
145-
* Configure the {@code ClientRSocketFactory}.
146-
* <p><strong>Note:</strong> This builder provides shortcuts for certain
147-
* {@code ClientRSocketFactory} options it needs to know about such as
148-
* {@link #dataMimeType(MimeType)} and {@link #metadataMimeType(MimeType)}.
149-
* Please, use these shortcuts vs configuring them directly on the
150-
* {@code ClientRSocketFactory} so that the resulting
151-
* {@code RSocketRequester} is aware of those changes.
152-
* @param configurer consumer to customize the factory
153-
*/
154-
RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer);
155-
156144
/**
157145
* Set the {@link RSocketStrategies} to use for access to encoders,
158146
* decoders, and a factory for {@code DataBuffer's}.
@@ -169,6 +157,20 @@ interface Builder {
169157
*/
170158
RSocketRequester.Builder rsocketStrategies(Consumer<RSocketStrategies.Builder> configurer);
171159

160+
/**
161+
* Callback to configure the {@code ClientRSocketFactory} directly.
162+
* <p>See {@link AnnotationClientResponderConfigurer} for configuring a
163+
* client side responder.
164+
* <p><strong>Note:</strong> Do not set {@link #dataMimeType(MimeType)}
165+
* and {@link #metadataMimeType(MimeType)} directly on the
166+
* {@code ClientRSocketFactory}. Use the shortcuts on this builder
167+
* instead since the created {@code RSocketRequester} needs to be aware
168+
* of those settings.
169+
* @param configurer consumer to customize the factory
170+
* @see AnnotationClientResponderConfigurer
171+
*/
172+
RSocketRequester.Builder rsocketFactory(ClientRSocketFactoryConfigurer configurer);
173+
172174
/**
173175
* Connect to the RSocket server over TCP.
174176
* @param host the server host
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.messaging.rsocket.annotation.support;
17+
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.Collections;
21+
import java.util.List;
22+
23+
import io.rsocket.RSocketFactory;
24+
25+
import org.springframework.beans.BeanUtils;
26+
import org.springframework.lang.Nullable;
27+
import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer;
28+
import org.springframework.messaging.rsocket.MetadataExtractor;
29+
import org.springframework.messaging.rsocket.RSocketStrategies;
30+
import org.springframework.util.Assert;
31+
import org.springframework.util.RouteMatcher;
32+
33+
/**
34+
* {@link ClientRSocketFactoryConfigurer} to configure and plug in a responder
35+
* that handles requests via annotated handler methods. Effectively a thin layer over
36+
* {@link RSocketMessageHandler} that provides a programmatic way to configure
37+
* it and obtain a responder via {@link RSocketMessageHandler#clientResponder()
38+
* clientResponder()}.
39+
*
40+
* @author Rossen Stoyanchev
41+
* @since 5.2
42+
*/
43+
public final class AnnotationClientResponderConfigurer implements ClientRSocketFactoryConfigurer {
44+
45+
private final List<Object> handlers = new ArrayList<>();
46+
47+
@Nullable
48+
private RouteMatcher routeMatcher;
49+
50+
@Nullable
51+
private MetadataExtractor extractor;
52+
53+
@Nullable
54+
private RSocketStrategies strategies;
55+
56+
57+
private AnnotationClientResponderConfigurer(List<Object> handlers) {
58+
for (Object obj : handlers) {
59+
this.handlers.add(obj instanceof Class ? BeanUtils.instantiateClass((Class<?>) obj) : obj);
60+
}
61+
}
62+
63+
64+
/**
65+
* Configure the {@link RouteMatcher} to use. This is used to set
66+
* {@link RSocketMessageHandler#setRouteMatcher(RouteMatcher)}.
67+
*/
68+
public AnnotationClientResponderConfigurer routeMatcher(RouteMatcher routeMatcher) {
69+
this.routeMatcher = routeMatcher;
70+
return this;
71+
}
72+
73+
/**
74+
* Configure the {@link MetadataExtractor} to use. This is used to set
75+
* {@link RSocketMessageHandler#setMetadataExtractor(MetadataExtractor)}.
76+
*/
77+
public AnnotationClientResponderConfigurer metadataExtractor(MetadataExtractor extractor) {
78+
this.extractor = extractor;
79+
return this;
80+
}
81+
82+
/**
83+
* Configure handlers to detect {@code @MessasgeMapping} handler methods on.
84+
* This is used to set {@link RSocketMessageHandler#setHandlers(List)}.
85+
*/
86+
public AnnotationClientResponderConfigurer handlers(Object... handlers) {
87+
this.handlers.addAll(Arrays.asList(handlers));
88+
return this;
89+
}
90+
91+
92+
// Implementation of ClientRSocketFactoryConfigurer
93+
94+
@Override
95+
public void configureWithStrategies(RSocketStrategies strategies) {
96+
this.strategies = strategies;
97+
}
98+
99+
@Override
100+
public void configure(RSocketFactory.ClientRSocketFactory factory) {
101+
Assert.notEmpty(this.handlers, "No handlers");
102+
RSocketMessageHandler messageHandler = new RSocketMessageHandler();
103+
messageHandler.setHandlers(this.handlers);
104+
if (this.routeMatcher != null) {
105+
messageHandler.setRouteMatcher(this.routeMatcher);
106+
}
107+
if (this.extractor != null) {
108+
messageHandler.setMetadataExtractor(this.extractor);
109+
}
110+
messageHandler.setRSocketStrategies(this.strategies);
111+
messageHandler.afterPropertiesSet();
112+
factory.acceptor(messageHandler.clientResponder());
113+
}
114+
115+
116+
// Static factory methods
117+
118+
/**
119+
* Create an {@code AnnotationClientResponderConfigurer} with the given handlers
120+
* to check for {@code @MessasgeMapping} handler methods.
121+
*/
122+
public static AnnotationClientResponderConfigurer withHandlers(Object... handlers) {
123+
return new AnnotationClientResponderConfigurer(Arrays.asList(handlers));
124+
}
125+
126+
/**
127+
* Create an {@code AnnotationClientResponderConfigurer} to set up further.
128+
*/
129+
public static AnnotationClientResponderConfigurer create() {
130+
return new AnnotationClientResponderConfigurer(Collections.emptyList());
131+
}
132+
133+
}

spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/ClientResponderFactory.java

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)