5
5
6
6
import java .net .URI ;
7
7
import java .util .Arrays ;
8
+ import java .util .Base64 ;
8
9
import java .util .List ;
9
10
import java .util .Objects ;
10
11
import java .util .Random ;
11
12
import java .util .concurrent .CopyOnWriteArrayList ;
12
13
import java .util .concurrent .CountDownLatch ;
13
14
import java .util .concurrent .TimeUnit ;
15
+ import java .util .stream .Collectors ;
16
+ import java .util .stream .IntStream ;
14
17
15
- import jakarta .inject .Inject ;
16
18
import jakarta .ws .rs .GET ;
17
19
import jakarta .ws .rs .Path ;
18
20
import jakarta .ws .rs .Produces ;
34
36
import io .smallrye .mutiny .Multi ;
35
37
import io .vertx .core .Vertx ;
36
38
import io .vertx .ext .web .RoutingContext ;
37
- import wiremock .org .apache .hc .client5 .http .utils .Base64 ;
38
39
39
40
public class MultiNdjsonTest {
40
41
@ RegisterExtension
@@ -110,6 +111,34 @@ void shouldReadNdjsonFromSingleMessage() throws InterruptedException {
110
111
assertThat (collected ).hasSize (4 ).containsAll (expected );
111
112
}
112
113
114
+ @ Test
115
+ void shouldReadNdjsonFromSingleMessageWithNoDelimiter () throws InterruptedException {
116
+ var client = createClient (uri );
117
+ var collected = new CopyOnWriteArrayList <Message >();
118
+ var completionLatch = new CountDownLatch (1 );
119
+ client .readSingleMessageNoDelimiter ().onCompletion ().invoke (completionLatch ::countDown )
120
+ .subscribe ().with (collected ::add );
121
+
122
+ if (!completionLatch .await (5 , TimeUnit .SECONDS )) {
123
+ fail ("Streaming did not complete in time" );
124
+ }
125
+ assertThat (collected ).singleElement ().satisfies (m -> assertThat (m ).isEqualTo (Message .of ("foo" , "bar" )));
126
+ }
127
+
128
+ @ Test
129
+ void shouldReadNdjsonFromMultipleMessagesWithNoEndingDelimiter () throws InterruptedException {
130
+ var client = createClient (uri );
131
+ var collected = new CopyOnWriteArrayList <Message >();
132
+ var completionLatch = new CountDownLatch (1 );
133
+ client .readMultipleMessagesNoEndingDelimiter ().onCompletion ().invoke (completionLatch ::countDown )
134
+ .subscribe ().with (collected ::add );
135
+
136
+ if (!completionLatch .await (5 , TimeUnit .SECONDS )) {
137
+ fail ("Streaming did not complete in time" );
138
+ }
139
+ assertThat (collected ).hasSize (100 );
140
+ }
141
+
113
142
@ Test
114
143
void shouldReadLargeNdjsonPojoAsMulti () throws InterruptedException {
115
144
var client = createClient (uri );
@@ -151,6 +180,18 @@ public interface Client {
151
180
@ RestStreamElementType (MediaType .APPLICATION_JSON )
152
181
Multi <Message > readPojoSingle ();
153
182
183
+ @ GET
184
+ @ Path ("/single-message-no-delimiter" )
185
+ @ Produces (RestMediaType .APPLICATION_NDJSON )
186
+ @ RestStreamElementType (MediaType .APPLICATION_JSON )
187
+ Multi <Message > readSingleMessageNoDelimiter ();
188
+
189
+ @ GET
190
+ @ Path ("multiple-messages-no-ending-delimiter" )
191
+ @ Produces (RestMediaType .APPLICATION_NDJSON )
192
+ @ RestStreamElementType (MediaType .APPLICATION_JSON )
193
+ Multi <Message > readMultipleMessagesNoEndingDelimiter ();
194
+
154
195
@ GET
155
196
@ Path ("/large-pojo" )
156
197
@ Produces (RestMediaType .APPLICATION_NDJSON )
@@ -172,8 +213,14 @@ Multi<Message> people(RoutingContext context) {
172
213
173
214
@ Path ("/stream" )
174
215
public static class StreamingResource {
175
- @ Inject
176
- Vertx vertx ;
216
+ private final ObjectMapper mapper = new ObjectMapper ();
217
+ private final ObjectWriter messageWriter = mapper .writerFor (Message .class );
218
+
219
+ private final Vertx vertx ;
220
+
221
+ public StreamingResource (Vertx vertx ) {
222
+ this .vertx = vertx ;
223
+ }
177
224
178
225
@ GET
179
226
@ Path ("/string" )
@@ -212,19 +259,41 @@ public Multi<Message> readPojo() {
212
259
@ Produces (RestMediaType .APPLICATION_NDJSON )
213
260
@ RestStreamElementType (MediaType .APPLICATION_JSON )
214
261
public String getPojosAsString () throws JsonProcessingException {
215
- ObjectMapper mapper = new ObjectMapper ();
216
262
StringBuilder result = new StringBuilder ();
217
- ObjectWriter objectWriter = mapper .writerFor (Message .class );
218
263
for (var msg : List .of (Message .of ("zero" , "0" ),
219
264
Message .of ("one" , "1" ),
220
265
Message .of ("two" , "2" ),
221
266
Message .of ("three" , "3" ))) {
222
- result .append (objectWriter .writeValueAsString (msg ));
267
+ result .append (messageWriter .writeValueAsString (msg ));
223
268
result .append ("\n " );
224
269
}
225
270
return result .toString ();
226
271
}
227
272
273
+ @ GET
274
+ @ Path ("/single-message-no-delimiter" )
275
+ @ Produces (RestMediaType .APPLICATION_NDJSON )
276
+ @ RestStreamElementType (MediaType .APPLICATION_JSON )
277
+ public String singleMessageNoDelimiter () throws JsonProcessingException {
278
+ return messageWriter .writeValueAsString (Message .of ("foo" , "bar" ));
279
+ }
280
+
281
+ @ GET
282
+ @ Path ("/multiple-messages-no-ending-delimiter" )
283
+ @ Produces (RestMediaType .APPLICATION_NDJSON )
284
+ @ RestStreamElementType (MediaType .APPLICATION_JSON )
285
+ public String multipleMessagesNoEndingDelimiter () throws JsonProcessingException {
286
+ return IntStream .range (0 , 100 )
287
+ .mapToObj (i -> Message .of ("foo" , "bar" ))
288
+ .map (m -> {
289
+ try {
290
+ return messageWriter .writeValueAsString (m );
291
+ } catch (JsonProcessingException e ) {
292
+ throw new RuntimeException (e );
293
+ }
294
+ }).collect (Collectors .joining ("\n " ));
295
+ }
296
+
228
297
@ GET
229
298
@ Path ("/large-pojo" )
230
299
@ Produces (RestMediaType .APPLICATION_NDJSON )
@@ -235,7 +304,7 @@ public Multi<Message> readLargePojo() {
235
304
byte [] bytes = new byte [4 * 1024 ];
236
305
Random random = new Random ();
237
306
random .nextBytes (bytes );
238
- String value = Base64 .encodeBase64String (bytes );
307
+ String value = Base64 .getEncoder (). encodeToString (bytes );
239
308
em .emit (Message .of ("one" , value ));
240
309
em .emit (Message .of ("two" , value ));
241
310
em .emit (Message .of ("three" , value ));
0 commit comments