Skip to content

Commit 91b040d

Browse files
committed
Add responder strategies to RSocketStrategies
RouteMatcher and MetadataExtractor can now be configured on and accessed through RSocketStrategies. This simplifies configuration for client and server responders. See gh-23314
1 parent a780cad commit 91b040d

File tree

5 files changed

+134
-63
lines changed

5 files changed

+134
-63
lines changed

spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
8888
@Nullable
8989
private Validator validator;
9090

91+
@Nullable
9192
private RouteMatcher routeMatcher;
9293

9394
private ConversionService conversionService = new DefaultFormattingConversionService();
@@ -97,9 +98,6 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
9798

9899

99100
public MessageMappingMessageHandler() {
100-
AntPathMatcher pathMatcher = new AntPathMatcher();
101-
pathMatcher.setPathSeparator(".");
102-
this.routeMatcher = new SimpleRouteMatcher(pathMatcher);
103101
setHandlerPredicate(type -> AnnotatedElementUtils.hasAnnotation(type, Controller.class));
104102
}
105103

@@ -150,7 +148,9 @@ public void setRouteMatcher(RouteMatcher routeMatcher) {
150148

151149
/**
152150
* Return the {@code RouteMatcher} used to map messages to handlers.
151+
* May be {@code null} before component is initialized.
153152
*/
153+
@Nullable
154154
public RouteMatcher getRouteMatcher() {
155155
return this.routeMatcher;
156156
}
@@ -203,6 +203,12 @@ protected List<? extends HandlerMethodArgumentResolver> initArgumentResolvers()
203203
resolvers.add(new PayloadMethodArgumentResolver(
204204
getDecoders(), this.validator, getReactiveAdapterRegistry(), true));
205205

206+
if (this.routeMatcher == null) {
207+
AntPathMatcher pathMatcher = new AntPathMatcher();
208+
pathMatcher.setPathSeparator(".");
209+
this.routeMatcher = new SimpleRouteMatcher(pathMatcher);
210+
}
211+
206212
return resolvers;
207213
}
208214

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

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@
3838
import org.springframework.core.io.buffer.DataBufferFactory;
3939
import org.springframework.core.io.buffer.NettyDataBufferFactory;
4040
import org.springframework.lang.Nullable;
41+
import org.springframework.util.AntPathMatcher;
4142
import org.springframework.util.Assert;
43+
import org.springframework.util.MimeTypeUtils;
44+
import org.springframework.util.RouteMatcher;
45+
import org.springframework.util.SimpleRouteMatcher;
4246

4347
/**
4448
* Default, package-private {@link RSocketStrategies} implementation.
@@ -52,18 +56,25 @@ final class DefaultRSocketStrategies implements RSocketStrategies {
5256

5357
private final List<Decoder<?>> decoders;
5458

55-
private final ReactiveAdapterRegistry adapterRegistry;
59+
private final RouteMatcher routeMatcher;
60+
61+
private final MetadataExtractor metadataExtractor;
5662

5763
private final DataBufferFactory bufferFactory;
5864

65+
private final ReactiveAdapterRegistry adapterRegistry;
66+
5967

6068
private DefaultRSocketStrategies(List<Encoder<?>> encoders, List<Decoder<?>> decoders,
61-
ReactiveAdapterRegistry adapterRegistry, DataBufferFactory bufferFactory) {
69+
RouteMatcher routeMatcher, MetadataExtractor metadataExtractor,
70+
DataBufferFactory bufferFactory, ReactiveAdapterRegistry adapterRegistry) {
6271

6372
this.encoders = Collections.unmodifiableList(encoders);
6473
this.decoders = Collections.unmodifiableList(decoders);
65-
this.adapterRegistry = adapterRegistry;
74+
this.routeMatcher = routeMatcher;
75+
this.metadataExtractor = metadataExtractor;
6676
this.bufferFactory = bufferFactory;
77+
this.adapterRegistry = adapterRegistry;
6778
}
6879

6980

@@ -78,15 +89,25 @@ public List<Decoder<?>> decoders() {
7889
}
7990

8091
@Override
81-
public ReactiveAdapterRegistry reactiveAdapterRegistry() {
82-
return this.adapterRegistry;
92+
public RouteMatcher routeMatcher() {
93+
return this.routeMatcher;
94+
}
95+
96+
@Override
97+
public MetadataExtractor metadataExtractor() {
98+
return this.metadataExtractor;
8399
}
84100

85101
@Override
86102
public DataBufferFactory dataBufferFactory() {
87103
return this.bufferFactory;
88104
}
89105

106+
@Override
107+
public ReactiveAdapterRegistry reactiveAdapterRegistry() {
108+
return this.adapterRegistry;
109+
}
110+
90111

91112
/**
92113
* Default RSocketStrategies.Builder implementation.
@@ -97,6 +118,12 @@ static class DefaultRSocketStrategiesBuilder implements RSocketStrategies.Builde
97118

98119
private final List<Decoder<?>> decoders = new ArrayList<>();
99120

121+
@Nullable
122+
private RouteMatcher routeMatcher;
123+
124+
@Nullable
125+
private MetadataExtractor metadataExtractor;
126+
100127
private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
101128

102129
@Nullable
@@ -151,6 +178,18 @@ public Builder decoders(Consumer<List<Decoder<?>>> consumer) {
151178
return this;
152179
}
153180

181+
@Override
182+
public Builder routeMatcher(RouteMatcher routeMatcher) {
183+
this.routeMatcher = routeMatcher;
184+
return this;
185+
}
186+
187+
@Override
188+
public Builder metadataExtractor(MetadataExtractor metadataExtractor) {
189+
this.metadataExtractor = metadataExtractor;
190+
return this;
191+
}
192+
154193
@Override
155194
public Builder reactiveAdapterStrategy(ReactiveAdapterRegistry registry) {
156195
Assert.notNull(registry, "ReactiveAdapterRegistry is required");
@@ -167,12 +206,27 @@ public Builder dataBufferFactory(DataBufferFactory bufferFactory) {
167206
@Override
168207
public RSocketStrategies build() {
169208
return new DefaultRSocketStrategies(
170-
this.encoders, this.decoders, this.adapterRegistry, initBufferFactory());
209+
this.encoders, this.decoders,
210+
this.routeMatcher != null ? this.routeMatcher : initRouteMatcher(),
211+
this.metadataExtractor != null ? this.metadataExtractor : initMetadataExtractor(),
212+
this.bufferFactory != null ? this.bufferFactory : initBufferFactory(),
213+
this.adapterRegistry);
214+
}
215+
216+
private RouteMatcher initRouteMatcher() {
217+
AntPathMatcher pathMatcher = new AntPathMatcher();
218+
pathMatcher.setPathSeparator(".");
219+
return new SimpleRouteMatcher(pathMatcher);
220+
}
221+
222+
private MetadataExtractor initMetadataExtractor() {
223+
DefaultMetadataExtractor extractor = new DefaultMetadataExtractor();
224+
extractor.metadataToExtract(MimeTypeUtils.TEXT_PLAIN, String.class, MetadataExtractor.ROUTE_KEY);
225+
return extractor;
171226
}
172227

173228
private DataBufferFactory initBufferFactory() {
174-
return this.bufferFactory != null ? this.bufferFactory :
175-
new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT);
229+
return new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT);
176230
}
177231
}
178232

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

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
3232
import org.springframework.core.io.buffer.NettyDataBufferFactory;
3333
import org.springframework.lang.Nullable;
34+
import org.springframework.util.AntPathMatcher;
3435
import org.springframework.util.MimeType;
36+
import org.springframework.util.RouteMatcher;
37+
import org.springframework.util.SimpleRouteMatcher;
3538

3639
/**
3740
* Access to strategies for use by RSocket requester and responder components.
@@ -90,17 +93,27 @@ default <T> Decoder<T> decoder(ResolvableType elementType, @Nullable MimeType mi
9093
}
9194

9295
/**
93-
* Return the configured
94-
* {@link Builder#reactiveAdapterStrategy(ReactiveAdapterRegistry) reactiveAdapterRegistry}.
96+
* Return the configured {@link Builder#routeMatcher(RouteMatcher)}.
9597
*/
96-
ReactiveAdapterRegistry reactiveAdapterRegistry();
98+
RouteMatcher routeMatcher();
99+
100+
/**
101+
* Return the configured {@link Builder#metadataExtractor(MetadataExtractor)}.
102+
*/
103+
MetadataExtractor metadataExtractor();
97104

98105
/**
99106
* Return the configured
100107
* {@link Builder#dataBufferFactory(DataBufferFactory) dataBufferFactory}.
101108
*/
102109
DataBufferFactory dataBufferFactory();
103110

111+
/**
112+
* Return the configured
113+
* {@link Builder#reactiveAdapterStrategy(ReactiveAdapterRegistry) reactiveAdapterRegistry}.
114+
*/
115+
ReactiveAdapterRegistry reactiveAdapterRegistry();
116+
104117

105118
/**
106119
* Return a builder to build a new {@code RSocketStrategies} instance.
@@ -149,6 +162,27 @@ interface Builder {
149162
*/
150163
Builder decoders(Consumer<List<Decoder<?>>> consumer);
151164

165+
/**
166+
* Configure a {@code RouteMatcher} for matching routes to message
167+
* handlers based on route patterns. This option is applicable to
168+
* client or server responders.
169+
* <p>By default, {@link SimpleRouteMatcher} is used, backed by
170+
* {@link AntPathMatcher} with "." as separator. For better
171+
* efficiency consider using the {@code PathPatternRouteMatcher} from
172+
* {@code spring-web} instead.
173+
*/
174+
Builder routeMatcher(RouteMatcher routeMatcher);
175+
176+
/**
177+
* Configure a {@link MetadataExtractor} to extract the route along with
178+
* other metadata. This option is applicable to client or server
179+
* responders.
180+
* <p>By default this is {@link DefaultMetadataExtractor} extracting a
181+
* route from {@code "message/x.rsocket.routing.v0"} or
182+
* {@code "text/plain"} metadata entries.
183+
*/
184+
Builder metadataExtractor(MetadataExtractor metadataExtractor);
185+
152186
/**
153187
* Configure the registry for reactive type support. This can be used to
154188
* to adapt to, and/or determine the semantics of a given

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

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@
2525
import org.springframework.beans.BeanUtils;
2626
import org.springframework.lang.Nullable;
2727
import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer;
28-
import org.springframework.messaging.rsocket.MetadataExtractor;
2928
import org.springframework.messaging.rsocket.RSocketStrategies;
3029
import org.springframework.util.Assert;
31-
import org.springframework.util.RouteMatcher;
3230

3331
/**
3432
* {@link ClientRSocketFactoryConfigurer} to configure and plug in a responder
@@ -44,12 +42,6 @@ public final class AnnotationClientResponderConfigurer implements ClientRSocketF
4442

4543
private final List<Object> handlers = new ArrayList<>();
4644

47-
@Nullable
48-
private RouteMatcher routeMatcher;
49-
50-
@Nullable
51-
private MetadataExtractor extractor;
52-
5345
@Nullable
5446
private RSocketStrategies strategies;
5547

@@ -61,24 +53,6 @@ private AnnotationClientResponderConfigurer(List<Object> handlers) {
6153
}
6254

6355

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-
8256
/**
8357
* Configure handlers to detect {@code @MessasgeMapping} handler methods on.
8458
* This is used to set {@link RSocketMessageHandler#setHandlers(List)}.
@@ -101,12 +75,6 @@ public void configure(RSocketFactory.ClientRSocketFactory factory) {
10175
Assert.notEmpty(this.handlers, "No handlers");
10276
RSocketMessageHandler messageHandler = new RSocketMessageHandler();
10377
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-
}
11078
messageHandler.setRSocketStrategies(this.strategies);
11179
messageHandler.afterPropertiesSet();
11280
factory.acceptor(messageHandler.clientResponder());

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

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,16 @@ public List<? extends Encoder<?>> getEncoders() {
114114
/**
115115
* Provide configuration in the form of {@link RSocketStrategies} instance
116116
* which can also be re-used to initialize a client-side
117-
* {@link RSocketRequester}. When this property is set, it also sets
118-
* {@link #setDecoders(List) decoders}, {@link #setEncoders(List) encoders},
119-
* and {@link #setReactiveAdapterRegistry(ReactiveAdapterRegistry)
120-
* reactiveAdapterRegistry}.
117+
* {@link RSocketRequester}.
118+
* <p>When this is set, in turn it sets the following:
119+
* <ul>
120+
* <li>{@link #setDecoders(List)}
121+
* <li>{@link #setEncoders(List)}
122+
* <li>{@link #setRouteMatcher(RouteMatcher)}
123+
* <li>{@link #setMetadataExtractor(MetadataExtractor)}
124+
* <li>{@link #setReactiveAdapterRegistry(ReactiveAdapterRegistry)}
125+
* </ul>
126+
* <p>By default if this is not set, it is initialized from the above.
121127
*/
122128
public void setRSocketStrategies(@Nullable RSocketStrategies rsocketStrategies) {
123129
this.rsocketStrategies = rsocketStrategies;
@@ -138,12 +144,10 @@ public RSocketStrategies getRSocketStrategies() {
138144
}
139145

140146
/**
141-
* Configure a {@link MetadataExtractor} to extract the route and possibly
142-
* other metadata from the first payload of incoming requests.
143-
* <p>By default this is a {@link DefaultMetadataExtractor} with the
144-
* configured {@link RSocketStrategies} (and decoders), extracting a route
145-
* from {@code "message/x.rsocket.routing.v0"} or {@code "text/plain"}
146-
* metadata entries.
147+
* Configure a {@link MetadataExtractor} to extract the route along with
148+
* other metadata.
149+
* <p>By default this is {@link DefaultMetadataExtractor} extracting a
150+
* route from {@code "message/x.rsocket.routing.v0"} or {@code "text/plain"}.
147151
* @param extractor the extractor to use
148152
*/
149153
public void setMetadataExtractor(MetadataExtractor extractor) {
@@ -200,20 +204,25 @@ public MimeType getDefaultMetadataMimeType() {
200204

201205
@Override
202206
public void afterPropertiesSet() {
207+
208+
getArgumentResolverConfigurer().addCustomResolver(new RSocketRequesterMethodArgumentResolver());
209+
super.afterPropertiesSet();
210+
211+
if (getMetadataExtractor() == null) {
212+
DefaultMetadataExtractor extractor = new DefaultMetadataExtractor();
213+
extractor.metadataToExtract(MimeTypeUtils.TEXT_PLAIN, String.class, MetadataExtractor.ROUTE_KEY);
214+
setMetadataExtractor(extractor);
215+
}
216+
203217
if (this.rsocketStrategies == null) {
204218
this.rsocketStrategies = RSocketStrategies.builder()
205219
.decoder(getDecoders().toArray(new Decoder<?>[0]))
206220
.encoder(getEncoders().toArray(new Encoder<?>[0]))
221+
.routeMatcher(getRouteMatcher())
222+
.metadataExtractor(getMetadataExtractor())
207223
.reactiveAdapterStrategy(getReactiveAdapterRegistry())
208224
.build();
209225
}
210-
if (this.metadataExtractor == null) {
211-
DefaultMetadataExtractor extractor = new DefaultMetadataExtractor();
212-
extractor.metadataToExtract(MimeTypeUtils.TEXT_PLAIN, String.class, MetadataExtractor.ROUTE_KEY);
213-
this.metadataExtractor = extractor;
214-
}
215-
getArgumentResolverConfigurer().addCustomResolver(new RSocketRequesterMethodArgumentResolver());
216-
super.afterPropertiesSet();
217226
}
218227

219228
@Override

0 commit comments

Comments
 (0)