17
17
18
18
import java .util .function .Function ;
19
19
20
+ import io .rsocket .AbstractRSocket ;
20
21
import io .rsocket .ConnectionSetupPayload ;
21
22
import io .rsocket .Payload ;
22
23
import io .rsocket .RSocket ;
40
41
import org .springframework .messaging .support .MessageHeaderAccessor ;
41
42
import org .springframework .util .Assert ;
42
43
import org .springframework .util .MimeType ;
44
+ import org .springframework .util .MimeTypeUtils ;
45
+ import org .springframework .util .StringUtils ;
43
46
44
47
/**
45
48
* Package private implementation of {@link RSocket} that is is hooked into an
49
52
* @author Rossen Stoyanchev
50
53
* @since 5.2
51
54
*/
52
- class MessagingRSocket implements RSocket {
55
+ class MessagingRSocket extends AbstractRSocket {
53
56
54
57
private final ReactiveMessageChannel messageChannel ;
55
58
56
59
private final RSocketRequester requester ;
57
60
58
61
@ Nullable
59
- private final MimeType dataMimeType ;
62
+ private MimeType dataMimeType ;
60
63
61
64
private final RSocketStrategies strategies ;
62
65
63
66
64
67
MessagingRSocket (ReactiveMessageChannel messageChannel ,
65
- RSocket sendingRSocket , @ Nullable MimeType dataMimeType , RSocketStrategies strategies ) {
68
+ RSocket sendingRSocket , @ Nullable MimeType defaultDataMimeType , RSocketStrategies strategies ) {
66
69
67
70
Assert .notNull (messageChannel , "'messageChannel' is required" );
68
71
Assert .notNull (sendingRSocket , "'sendingRSocket' is required" );
69
72
this .messageChannel = messageChannel ;
70
- this .requester = RSocketRequester .create (sendingRSocket , dataMimeType , strategies );
71
- this .dataMimeType = dataMimeType ;
73
+ this .requester = RSocketRequester .create (sendingRSocket , defaultDataMimeType , strategies );
74
+ this .dataMimeType = defaultDataMimeType ;
72
75
this .strategies = strategies ;
73
76
}
74
77
75
78
76
- public Mono <Void > afterConnectionEstablished (ConnectionSetupPayload payload ) {
77
- return execute (payload ).flatMap (flux -> flux .take (0 ).then ());
79
+
80
+ public Mono <Void > handleConnectionSetupPayload (ConnectionSetupPayload payload ) {
81
+ if (StringUtils .hasText (payload .dataMimeType ())) {
82
+ this .dataMimeType = MimeTypeUtils .parseMimeType (payload .dataMimeType ());
83
+ }
84
+ return handle (payload );
78
85
}
79
86
80
87
81
88
@ Override
82
89
public Mono <Void > fireAndForget (Payload payload ) {
83
- return execute (payload ). flatMap ( flux -> flux . take ( 0 ). then () );
90
+ return handle (payload );
84
91
}
85
92
86
93
@ Override
87
94
public Mono <Payload > requestResponse (Payload payload ) {
88
- return execute (payload ). flatMap ( Flux :: next );
95
+ return handleAndReply (payload , Flux . just ( payload )). next ( );
89
96
}
90
97
91
98
@ Override
92
99
public Flux <Payload > requestStream (Payload payload ) {
93
- return execute (payload ). flatMapMany ( Function . identity ( ));
100
+ return handleAndReply (payload , Flux . just ( payload ));
94
101
}
95
102
96
103
@ Override
97
104
public Flux <Payload > requestChannel (Publisher <Payload > payloads ) {
98
105
return Flux .from (payloads )
99
- .switchOnFirst ((signal , inner ) -> {
100
- Payload first = signal .get ();
101
- return first != null ? execute ( first , inner ). flatMapMany ( Function . identity ()) : inner ;
106
+ .switchOnFirst ((signal , innerFlux ) -> {
107
+ Payload firstPayload = signal .get ();
108
+ return firstPayload == null ? innerFlux : handleAndReply ( firstPayload , innerFlux ) ;
102
109
});
103
110
}
104
111
105
112
@ Override
106
113
public Mono <Void > metadataPush (Payload payload ) {
107
- return null ;
114
+ // This won't be very useful until createHeaders starting doing something more with metadata..
115
+ return handle (payload );
108
116
}
109
117
110
- private Mono <Flux <Payload >> execute (Payload payload ) {
111
- return execute (payload , Flux .just (payload ));
112
- }
113
118
114
- private Mono <Flux < Payload >> execute (Payload firstPayload , Flux < Payload > payloads ) {
119
+ private Mono <Void > handle (Payload payload ) {
115
120
116
- // TODO:
117
- // Since we do retain(), we need to ensure buffers are released if not consumed ,
118
- // e.g. error before Flux subscribed to, no handler found, @MessageMapping ignores payload, etc.
121
+ Message <?> message = MessageBuilder . createMessage (
122
+ Mono . fromCallable (() -> wrapPayloadData ( payload )) ,
123
+ createHeaders ( payload , null ));
119
124
120
- Flux <DataBuffer > payloadDataBuffers = payloads
121
- .map (payload -> PayloadUtils .asDataBuffer (payload , this .strategies .dataBufferFactory ()))
122
- .doOnDiscard (PooledDataBuffer .class , DataBufferUtils ::release );
125
+ return this .messageChannel .send (message ).flatMap (result -> result ?
126
+ Mono .empty () : Mono .error (new MessageDeliveryException ("RSocket request not handled" )));
127
+ }
128
+
129
+ private Flux <Payload > handleAndReply (Payload firstPayload , Flux <Payload > payloads ) {
123
130
124
131
MonoProcessor <Flux <Payload >> replyMono = MonoProcessor .create ();
125
- MessageHeaders headers = createHeaders (firstPayload , replyMono );
126
132
127
- Message <?> message = MessageBuilder .createMessage (payloadDataBuffers , headers );
133
+ Message <?> message = MessageBuilder .createMessage (
134
+ payloads .map (this ::wrapPayloadData ).doOnDiscard (PooledDataBuffer .class , DataBufferUtils ::release ),
135
+ createHeaders (firstPayload , replyMono ));
128
136
129
- return this .messageChannel .send (message ).flatMap (result -> result ?
130
- replyMono .isTerminated () ? replyMono : Mono . empty ( ) :
131
- Mono .error (new MessageDeliveryException ("RSocket interaction not handled" )));
137
+ return this .messageChannel .send (message ).flatMapMany (result ->
138
+ result && replyMono .isTerminated () ? replyMono . flatMapMany ( Function . identity () ) :
139
+ Mono .error (new MessageDeliveryException ("RSocket request not handled" )));
132
140
}
133
141
134
- private MessageHeaders createHeaders (Payload payload , MonoProcessor <?> replyMono ) {
142
+ private MessageHeaders createHeaders (Payload payload , @ Nullable MonoProcessor <?> replyMono ) {
135
143
144
+ // TODO:
136
145
// For now treat the metadata as a simple string with routing information.
137
146
// We'll have to get more sophisticated once the routing extension is completed.
138
147
// https://github.com/rsocket/rsocket-java/issues/568
@@ -147,21 +156,19 @@ private MessageHeaders createHeaders(Payload payload, MonoProcessor<?> replyMono
147
156
}
148
157
149
158
headers .setHeader (RSocketRequesterMethodArgumentResolver .RSOCKET_REQUESTER_HEADER , this .requester );
150
- headers .setHeader (RSocketPayloadReturnValueHandler .RESPONSE_HEADER , replyMono );
159
+
160
+ if (replyMono != null ) {
161
+ headers .setHeader (RSocketPayloadReturnValueHandler .RESPONSE_HEADER , replyMono );
162
+ }
151
163
152
164
DataBufferFactory bufferFactory = this .strategies .dataBufferFactory ();
153
165
headers .setHeader (HandlerMethodReturnValueHandler .DATA_BUFFER_FACTORY_HEADER , bufferFactory );
154
166
155
167
return headers .getMessageHeaders ();
156
168
}
157
169
158
- @ Override
159
- public Mono <Void > onClose () {
160
- return null ;
161
- }
162
-
163
- @ Override
164
- public void dispose () {
170
+ private DataBuffer wrapPayloadData (Payload payload ) {
171
+ return PayloadUtils .wrapPayloadData (payload , this .strategies .dataBufferFactory ());
165
172
}
166
173
167
174
}
0 commit comments