• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats.java / #2086

31 Jul 2025 04:04PM UTC coverage: 95.621% (+0.05%) from 95.573%
#2086

push

github

web-flow
Merge pull request #1377 from nats-io/stream-name-not-null

Stream Name cannot be null

3 of 4 new or added lines in 2 files covered. (75.0%)

11858 of 12401 relevant lines covered (95.62%)

0.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.08
/src/main/java/io/nats/client/api/StreamConfiguration.java
1
// Copyright 2020 The NATS Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at:
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package io.nats.client.api;
15

16
import io.nats.client.support.*;
17
import org.jspecify.annotations.NonNull;
18
import org.jspecify.annotations.Nullable;
19

20
import java.time.Duration;
21
import java.util.*;
22

23
import static io.nats.client.support.ApiConstants.*;
24
import static io.nats.client.support.JsonUtils.*;
25
import static io.nats.client.support.JsonValueUtils.*;
26
import static io.nats.client.support.JsonValueUtils.readBoolean;
27
import static io.nats.client.support.JsonValueUtils.readInteger;
28
import static io.nats.client.support.JsonValueUtils.readLong;
29
import static io.nats.client.support.JsonValueUtils.readNanos;
30
import static io.nats.client.support.JsonValueUtils.readString;
31
import static io.nats.client.support.Validator.*;
32

33
/**
34
 * The StreamConfiguration class specifies the configuration for creating a JetStream stream on the server.
35
 * Options are created using a {@link StreamConfiguration.Builder Builder}.
36
 */
37
public class StreamConfiguration implements JsonSerializable {
38

39
    // see builder for defaults
40
    private final String name;
41
    private final String description;
42
    private final List<String> subjects;
43
    private final RetentionPolicy retentionPolicy;
44
    private final CompressionOption compressionOption;
45
    private final long maxConsumers;
46
    private final long maxMsgs;
47
    private final long maxMsgsPerSubject;
48
    private final long maxBytes;
49
    private final Duration maxAge;
50
    private final int maxMsgSize;
51
    private final StorageType storageType;
52
    private final int replicas;
53
    private final boolean noAck;
54
    private final String templateOwner;
55
    private final DiscardPolicy discardPolicy;
56
    private final Duration duplicateWindow;
57
    private final Placement placement;
58
    private final Republish republish;
59
    private final SubjectTransform subjectTransform;
60
    private final ConsumerLimits consumerLimits;
61
    private final Mirror mirror;
62
    private final List<Source> sources;
63
    private final boolean sealed;
64
    private final boolean allowRollup;
65
    private final boolean allowDirect;
66
    private final boolean mirrorDirect;
67
    private final boolean denyDelete;
68
    private final boolean denyPurge;
69
    private final boolean discardNewPerSubject;
70
    private final Map<String, String> metadata;
71
    private final long firstSequence;
72
    private final boolean allowMessageTtl;
73
    private final Duration subjectDeleteMarkerTtl;
74

75
    static StreamConfiguration instance(JsonValue v) {
76
        return new Builder()
1✔
77
            .retentionPolicy(RetentionPolicy.get(readString(v, RETENTION)))
1✔
78
            .compressionOption(CompressionOption.get(readString(v, COMPRESSION)))
1✔
79
            .storageType(StorageType.get(readString(v, STORAGE)))
1✔
80
            .discardPolicy(DiscardPolicy.get(readString(v, DISCARD)))
1✔
81
            .name(readString(v, NAME))
1✔
82
            .description(readString(v, DESCRIPTION))
1✔
83
            .maxConsumers(readLong(v, MAX_CONSUMERS, -1))
1✔
84
            .maxMessages(readLong(v, MAX_MSGS, -1))
1✔
85
            .maxMessagesPerSubject(readLong(v, MAX_MSGS_PER_SUB, -1))
1✔
86
            .maxBytes(readLong(v, MAX_BYTES, -1))
1✔
87
            .maxAge(readNanos(v, MAX_AGE))
1✔
88
            .maximumMessageSize(readInteger(v, MAX_MSG_SIZE, -1))
1✔
89
            .replicas(readInteger(v, NUM_REPLICAS, 1))
1✔
90
            .noAck(readBoolean(v, NO_ACK))
1✔
91
            .templateOwner(readString(v, TEMPLATE_OWNER))
1✔
92
            .duplicateWindow(readNanos(v, DUPLICATE_WINDOW))
1✔
93
            .subjects(readStringList(v, SUBJECTS))
1✔
94
            .placement(Placement.optionalInstance(readValue(v, PLACEMENT)))
1✔
95
            .republish(Republish.optionalInstance(readValue(v, REPUBLISH)))
1✔
96
            .subjectTransform(SubjectTransform.optionalInstance(readValue(v, SUBJECT_TRANSFORM)))
1✔
97
            .consumerLimits(ConsumerLimits.optionalInstance(readValue(v, CONSUMER_LIMITS)))
1✔
98
            .mirror(Mirror.optionalInstance(readValue(v, MIRROR)))
1✔
99
            .sources(Source.optionalListOf(readValue(v, SOURCES)))
1✔
100
            .sealed(readBoolean(v, SEALED))
1✔
101
            .allowRollup(readBoolean(v, ALLOW_ROLLUP_HDRS))
1✔
102
            .allowDirect(readBoolean(v, ALLOW_DIRECT))
1✔
103
            .mirrorDirect(readBoolean(v, MIRROR_DIRECT))
1✔
104
            .denyDelete(readBoolean(v, DENY_DELETE))
1✔
105
            .denyPurge(readBoolean(v, DENY_PURGE))
1✔
106
            .discardNewPerSubject(readBoolean(v, DISCARD_NEW_PER_SUBJECT))
1✔
107
            .metadata(readStringStringMap(v, METADATA))
1✔
108
            .firstSequence(readLong(v, FIRST_SEQ, 1))
1✔
109
            .allowMessageTtl(readBoolean(v, ALLOW_MSG_TTL))
1✔
110
            .subjectDeleteMarkerTtl(readNanos(v, SUBJECT_DELETE_MARKER_TTL))
1✔
111
            .build();
1✔
112
    }
113

114
    // For the builder, assumes all validations are already done in builder
115
    StreamConfiguration(Builder b) {
1✔
116
        this.name = b.name;
1✔
117
        this.description = b.description;
1✔
118
        this.subjects = b.subjects;
1✔
119
        this.retentionPolicy = b.retentionPolicy;
1✔
120
        this.compressionOption = b.compressionOption;
1✔
121
        this.maxConsumers = b.maxConsumers;
1✔
122
        this.maxMsgs = b.maxMsgs;
1✔
123
        this.maxMsgsPerSubject = b.maxMsgsPerSubject;
1✔
124
        this.maxBytes = b.maxBytes;
1✔
125
        this.maxAge = b.maxAge;
1✔
126
        this.maxMsgSize = b.maxMsgSize;
1✔
127
        this.storageType = b.storageType;
1✔
128
        this.replicas = b.replicas;
1✔
129
        this.noAck = b.noAck;
1✔
130
        this.templateOwner = b.templateOwner;
1✔
131
        this.discardPolicy = b.discardPolicy;
1✔
132
        this.duplicateWindow = b.duplicateWindow;
1✔
133
        this.placement = b.placement;
1✔
134
        this.republish = b.republish;
1✔
135
        this.subjectTransform = b.subjectTransform;
1✔
136
        this.consumerLimits = b.consumerLimits;
1✔
137
        this.mirror = b.mirror;
1✔
138
        this.sources = b.sources;
1✔
139
        this.sealed = b.sealed;
1✔
140
        this.allowRollup = b.allowRollup;
1✔
141
        this.allowDirect = b.allowDirect;
1✔
142
        this.mirrorDirect = b.mirrorDirect;
1✔
143
        this.denyDelete = b.denyDelete;
1✔
144
        this.denyPurge = b.denyPurge;
1✔
145
        this.discardNewPerSubject = b.discardNewPerSubject;
1✔
146
        this.metadata = b.metadata;
1✔
147
        this.firstSequence = b.firstSequence;
1✔
148
        this.allowMessageTtl = b.allowMessageTtl;
1✔
149
        this.subjectDeleteMarkerTtl = b.subjectDeleteMarkerTtl;
1✔
150
    }
1✔
151

152
    /**
153
     * Returns a StreamConfiguration deserialized from its JSON form.
154
     *
155
     * @see #toJson()
156
     * @param json the json representing the Stream Configuration
157
     * @return StreamConfiguration for the given json
158
     * @throws JsonParseException thrown if the parsing fails for invalid json
159
     */
160
    public static StreamConfiguration instance(String json) throws JsonParseException {
161
        return instance(JsonParser.parse(json));
1✔
162
    }
163

164
    /**
165
     * Returns a JSON representation of this consumer configuration.
166
     *
167
     * @return json consumer configuration to send to the server.
168
     */
169
    @Override
170
    @NonNull
171
    public String toJson() {
172

173
        StringBuilder sb = beginJson();
1✔
174

175
        addField(sb, NAME, name);
1✔
176
        JsonUtils.addField(sb, DESCRIPTION, description);
1✔
177
        addStrings(sb, SUBJECTS, subjects);
1✔
178
        addField(sb, RETENTION, retentionPolicy.toString());
1✔
179
        addEnumWhenNot(sb, COMPRESSION, compressionOption, CompressionOption.None);
1✔
180
        addField(sb, MAX_CONSUMERS, maxConsumers);
1✔
181
        addField(sb, MAX_MSGS, maxMsgs);
1✔
182
        addField(sb, MAX_MSGS_PER_SUB, maxMsgsPerSubject);
1✔
183
        addField(sb, MAX_BYTES, maxBytes);
1✔
184
        addFieldAsNanos(sb, MAX_AGE, maxAge);
1✔
185
        addField(sb, MAX_MSG_SIZE, maxMsgSize);
1✔
186
        addField(sb, STORAGE, storageType.toString());
1✔
187
        addField(sb, NUM_REPLICAS, replicas);
1✔
188
        addFldWhenTrue(sb, NO_ACK, noAck);
1✔
189
        addField(sb, TEMPLATE_OWNER, templateOwner);
1✔
190
        addField(sb, DISCARD, discardPolicy.toString());
1✔
191
        addFieldAsNanos(sb, DUPLICATE_WINDOW, duplicateWindow);
1✔
192
        if (placement != null && placement.hasData()) {
1✔
193
            addField(sb, PLACEMENT, placement);
1✔
194
        }
195
        addField(sb, REPUBLISH, republish);
1✔
196
        addField(sb, SUBJECT_TRANSFORM, subjectTransform);
1✔
197
        addField(sb, CONSUMER_LIMITS, consumerLimits);
1✔
198
        addField(sb, MIRROR, mirror);
1✔
199
        addJsons(sb, SOURCES, sources);
1✔
200
        addFldWhenTrue(sb, SEALED, sealed);
1✔
201
        addFldWhenTrue(sb, ALLOW_ROLLUP_HDRS, allowRollup);
1✔
202
        addFldWhenTrue(sb, ALLOW_DIRECT, allowDirect);
1✔
203
        addFldWhenTrue(sb, MIRROR_DIRECT, mirrorDirect);
1✔
204
        addFldWhenTrue(sb, DENY_DELETE, denyDelete);
1✔
205
        addFldWhenTrue(sb, DENY_PURGE, denyPurge);
1✔
206
        addFldWhenTrue(sb, DISCARD_NEW_PER_SUBJECT, discardNewPerSubject);
1✔
207
        addField(sb, METADATA, metadata);
1✔
208
        addFieldWhenGreaterThan(sb, FIRST_SEQ, firstSequence, 1);
1✔
209
        addFldWhenTrue(sb, ALLOW_MSG_TTL, allowMessageTtl);
1✔
210
        addFieldAsNanos(sb, SUBJECT_DELETE_MARKER_TTL, subjectDeleteMarkerTtl);
1✔
211

212
        return endJson(sb).toString();
1✔
213
    }
214

215
    /**
216
     * Gets the name of this stream configuration.
217
     * @return the name of the stream.
218
     */
219
    @NonNull
220
    public String getName() {
221
        return name;
1✔
222
    }
223

224
    /**
225
     * Gets the description of this stream configuration.
226
     * @return the description of the stream.
227
     */
228
    @Nullable
229
    public String getDescription() {
230
        return description;
1✔
231
    }
232

233
    /**
234
     * Gets the subjects for this stream configuration.
235
     * @return the subject of the stream.
236
     */
237
    @NonNull
238
    public List<String> getSubjects() {
239
        return subjects;
1✔
240
    }
241

242
    /**
243
     * Gets the discard policy for this stream configuration.
244
     * @return the discard policy of the stream.
245
     */
246
    @Nullable
247
    public DiscardPolicy getDiscardPolicy() {
248
        return discardPolicy;
1✔
249
    }
250

251
    /**
252
     * Gets the retention policy for this stream configuration.
253
     * @return the retention policy for this stream.
254
     */
255
    @NonNull
256
    public RetentionPolicy getRetentionPolicy() {
257
        return retentionPolicy;
1✔
258
    }
259

260
    /**
261
     * Gets the compression option for this stream configuration.
262
     * @return the compression option for this stream.
263
     */
264
    @Nullable
265
    public CompressionOption getCompressionOption() {
266
        return compressionOption;
1✔
267
    }
268

269
    /**
270
     * Gets the maximum number of consumers for this stream configuration.
271
     * @return the maximum number of consumers for this stream.
272
     */
273
    public long getMaxConsumers() {
274
        return maxConsumers;
1✔
275
    }
276

277
    /**
278
     * Gets the maximum messages for this stream configuration.
279
     * @return the maximum number of messages for this stream.
280
     */
281
    public long getMaxMsgs() {
282
        return maxMsgs;
1✔
283
    }
284

285
    /**
286
     * Gets the maximum messages for this stream configuration.
287
     * @return the maximum number of messages for this stream.
288
     */
289
    public long getMaxMsgsPerSubject() {
290
        return maxMsgsPerSubject;
1✔
291
    }
292

293
    /**
294
     * Gets the maximum number of bytes for this stream configuration.
295
     * @return the maximum number of bytes for this stream.
296
     */
297
    public long getMaxBytes() {
298
        return maxBytes;
1✔
299
    }
300

301
    /**
302
     * Gets the maximum message age for this stream configuration.
303
     * @return the maximum message age for this stream.
304
     */
305
    @NonNull
306
    public Duration getMaxAge() {
307
        return maxAge;
1✔
308
    }
309

310
    /**
311
     * Gets the maximum message size for this stream configuration.
312
     * @deprecated the server value is a 32-bit signed value. Use {@link #getMaximumMessageSize()} instead.
313
     * @return the maximum message size for this stream.
314
     */
315
    @Deprecated
316
    public long getMaxMsgSize() {
317
        return maxMsgSize;
1✔
318
    }
319

320
    /**
321
     * Gets the maximum message size for this stream configuration.
322
     * @return the maximum message size for this stream.
323
     */
324
    public int getMaximumMessageSize() {
325
        return maxMsgSize;
1✔
326
    }
327

328
    /**
329
     * Gets the storage type for this stream configuration.
330
     * @return the storage type for this stream.
331
     */
332
    @NonNull
333
    public StorageType getStorageType() {
334
        return storageType;
1✔
335
    }
336

337
    /**
338
     * Gets the number of replicas for this stream configuration.
339
     * @return the number of replicas
340
     */    
341
    public int getReplicas() {
342
        return replicas;
1✔
343
    }
344

345
    /**
346
     * Gets whether acknowledgements are required in this stream configuration.
347
     * @return true if acknowedgments are not required.
348
     */
349
    public boolean getNoAck() {
350
        return noAck;
1✔
351
    }
352

353
    /**
354
     * Gets the template json for this stream configuration.
355
     * @return the template for this stream.
356
     */
357
    @Nullable
358
    public String getTemplateOwner() {
359
        return templateOwner;
1✔
360
    }
361

362
    /**
363
     * Gets the duplicate checking window stream configuration.  Duration.ZERO
364
     * means duplicate checking is not enabled.
365
     * @return the duration of the window.
366
     */
367
    @Nullable
368
    public Duration getDuplicateWindow() {
369
        return duplicateWindow;
1✔
370
    }
371

372
    /**
373
     * Get the placement directives to consider when placing replicas of this stream,
374
     * random placement when unset. May be null.
375
     * @return the placement object
376
     */
377
    @Nullable
378
    public Placement getPlacement() {
379
        return placement;
1✔
380
    }
381

382
    /**
383
     * Get the republish configuration. May be null.
384
     * @return the republish object
385
     */
386
    @Nullable
387
    public Republish getRepublish() {
388
        return republish;
1✔
389
    }
390

391
    /**
392
     * Get the subjectTransform configuration. May be null.
393
     * @return the subjectTransform object
394
     */
395
    @Nullable
396
    public SubjectTransform getSubjectTransform() {
397
        return subjectTransform;
1✔
398
    }
399

400
    /**
401
     * Get the consumerLimits configuration. May be null.
402
     * @return the consumerLimits object
403
     */
404
    @Nullable
405
    public ConsumerLimits getConsumerLimits() {
406
        return consumerLimits;
1✔
407
    }
408

409
    /**
410
     * The mirror definition for this stream
411
     * @return the mirror
412
     */
413
    @Nullable
414
    public Mirror getMirror() {
415
        return mirror;
1✔
416
    }
417

418
    /**
419
     * The sources for this stream
420
     * @return the sources
421
     */
422
    @Nullable
423
    public List<Source> getSources() {
424
        return sources;
1✔
425
    }
426

427
    /**
428
     * Get the flag indicating if the stream is sealed.
429
     * @return the sealed flag
430
     */
431
    public boolean getSealed() {
432
        return sealed;
1✔
433
    }
434

435
    /**
436
     * Get the flag indicating if the stream allows rollup.
437
     * @return the allows rollup flag
438
     */
439
    public boolean getAllowRollup() {
440
        return allowRollup;
1✔
441
    }
442

443
    /**
444
     * Get the flag indicating if the stream allows direct message access.
445
     * @return the allows direct flag
446
     */
447
    public boolean getAllowDirect() {
448
        return allowDirect;
1✔
449
    }
450

451
    /**
452
     * Get the flag indicating if the stream allows
453
     * higher performance and unified direct access for mirrors as well.
454
     * @return the allows direct flag
455
     */
456
    public boolean getMirrorDirect() {
457
        return mirrorDirect;
1✔
458
    }
459

460
    /**
461
     * Get the flag indicating if deny delete is set for the stream
462
     * @return the deny delete flag
463
     */
464
    public boolean getDenyDelete() {
465
        return denyDelete;
1✔
466
    }
467

468
    /**
469
     * Get the flag indicating if deny purge is set for the stream
470
     * @return the deny purge flag
471
     */
472
    public boolean getDenyPurge() {
473
        return denyPurge;
1✔
474
    }
475

476
    /**
477
     * Whether discard policy with max message per subject is applied per subject.
478
     * @return the discard new per subject flag
479
     */
480
    public boolean isDiscardNewPerSubject() {
481
        return discardNewPerSubject;
1✔
482
    }
483

484
    /**
485
     * Metadata for the stream
486
     * @return the metadata map. Might be null.
487
     */
488
    @Nullable
489
    public Map<String, String> getMetadata() {
490
        return metadata;
1✔
491
    }
492

493
    /**
494
     * The first sequence used in the stream.
495
     * @return the first sequence
496
     */
497
    public long getFirstSequence() {
498
        return firstSequence;
1✔
499
    }
500

501
    /**
502
     * Whether Allow Message TTL is set
503
     * @return the flag
504
     */
505
    public boolean isAllowMessageTtl() {
506
        return allowMessageTtl;
1✔
507
    }
508

509
    /**
510
     * Get the Subject Delete Marker TTL duration. May be null.
511
     * @return The duration
512
     */
513
    @Nullable
514
    public Duration getSubjectDeleteMarkerTtl() {
515
        return subjectDeleteMarkerTtl;
1✔
516
    }
517

518
    @Override
519
    public String toString() {
520
        return toJson();
1✔
521
    }
522

523
    /**
524
     * Creates a builder for the stream configuration.
525
     * @return a stream configuration builder
526
     */
527
    public static Builder builder() {
528
        return new Builder();
1✔
529
    }
530

531
    /**
532
     * Creates a builder to copy the stream configuration.
533
     * @param sc an existing StreamConfiguration
534
     * @return a stream configuration builder
535
     */
536
    public static Builder builder(StreamConfiguration sc) {
537
        return new Builder(sc);
1✔
538
    }
539

540
    /**
541
     * StreamConfiguration is created using a Builder. The builder supports chaining and will
542
     * create a default set of options if no methods are calls.
543
     * 
544
     * <p>{@code new StreamConfiguration.Builder().build()} will create a new StreamConfiguration.
545
     * 
546
     */
547
    public static class Builder {
548

549
        private String name = null;
1✔
550
        private String description = null;
1✔
551
        private final List<String> subjects = new ArrayList<>();
1✔
552
        private RetentionPolicy retentionPolicy = RetentionPolicy.Limits;
1✔
553
        private CompressionOption compressionOption = CompressionOption.None;
1✔
554
        private long maxConsumers = -1;
1✔
555
        private long maxMsgs = -1;
1✔
556
        private long maxMsgsPerSubject = -1;
1✔
557
        private long maxBytes = -1;
1✔
558
        private Duration maxAge = Duration.ZERO;
1✔
559
        private int maxMsgSize = -1;
1✔
560
        private StorageType storageType = StorageType.File;
1✔
561
        private int replicas = 1;
1✔
562
        private boolean noAck = false;
1✔
563
        private String templateOwner = null;
1✔
564
        private DiscardPolicy discardPolicy = DiscardPolicy.Old;
1✔
565
        private Duration duplicateWindow = Duration.ZERO;
1✔
566
        private Placement placement = null;
1✔
567
        private Republish republish = null;
1✔
568
        private SubjectTransform subjectTransform = null;
1✔
569
        private ConsumerLimits consumerLimits = null;
1✔
570
        private Mirror mirror = null;
1✔
571
        private final List<Source> sources = new ArrayList<>();
1✔
572
        private boolean sealed = false;
1✔
573
        private boolean allowRollup = false;
1✔
574
        private boolean allowDirect = false;
1✔
575
        private boolean mirrorDirect = false;
1✔
576
        private boolean denyDelete = false;
1✔
577
        private boolean denyPurge = false;
1✔
578
        private boolean discardNewPerSubject = false;
1✔
579
        private Map<String, String> metadata;
580
        private long firstSequence = 1;
1✔
581
        private boolean allowMessageTtl = false;
1✔
582
        private Duration subjectDeleteMarkerTtl;
583

584
        /**
585
         * Default Builder
586
         */
587
        public Builder() {}
1✔
588

589
        /**
590
         * Update Builder, useful if you need to update a configuration
591
         * @param sc the configuration to copy
592
         */
593
        public Builder(StreamConfiguration sc) {
1✔
594
            if (sc != null) {
1✔
595
                this.name = sc.name;
1✔
596
                this.description = sc.description;
1✔
597
                subjects(sc.subjects);
1✔
598
                this.retentionPolicy = sc.retentionPolicy;
1✔
599
                this.compressionOption = sc.compressionOption;
1✔
600
                this.maxConsumers = sc.maxConsumers;
1✔
601
                this.maxMsgs = sc.maxMsgs;
1✔
602
                this.maxMsgsPerSubject = sc.maxMsgsPerSubject;
1✔
603
                this.maxBytes = sc.maxBytes;
1✔
604
                this.maxAge = sc.maxAge;
1✔
605
                this.maxMsgSize = sc.maxMsgSize;
1✔
606
                this.storageType = sc.storageType;
1✔
607
                this.replicas = sc.replicas;
1✔
608
                this.noAck = sc.noAck;
1✔
609
                this.templateOwner = sc.templateOwner;
1✔
610
                this.discardPolicy = sc.discardPolicy;
1✔
611
                this.duplicateWindow = sc.duplicateWindow;
1✔
612
                this.placement = sc.placement;
1✔
613
                this.republish = sc.republish;
1✔
614
                this.subjectTransform = sc.subjectTransform;
1✔
615
                this.consumerLimits = sc.consumerLimits;
1✔
616
                this.mirror = sc.mirror;
1✔
617
                sources(sc.sources);
1✔
618
                this.sealed = sc.sealed;
1✔
619
                this.allowRollup = sc.allowRollup;
1✔
620
                this.allowDirect = sc.allowDirect;
1✔
621
                this.mirrorDirect = sc.mirrorDirect;
1✔
622
                this.denyDelete = sc.denyDelete;
1✔
623
                this.denyPurge = sc.denyPurge;
1✔
624
                this.discardNewPerSubject = sc.discardNewPerSubject;
1✔
625
                if (sc.metadata != null) {
1✔
626
                    this.metadata = new HashMap<>(sc.metadata);
1✔
627
                }
628
                this.firstSequence = sc.firstSequence;
1✔
629
                this.allowMessageTtl = sc.allowMessageTtl;
1✔
630
                this.subjectDeleteMarkerTtl = sc.subjectDeleteMarkerTtl;
1✔
631
            }
632
        }
1✔
633

634
        /**
635
         * Sets the name of the stream.
636
         * @param name name of the stream.
637
         * @return the builder
638
         */
639
        public Builder name(String name) {
640
            this.name =  validateStreamName(name, false);
1✔
641
            return this;
1✔
642
        }
643

644
        /**
645
         * Sets the description
646
         * @param description the description
647
         * @return the builder
648
         */
649
        public Builder description(String description) {
650
            this.description = description;
1✔
651
            return this;
1✔
652
        }
653

654
        /**
655
         * Sets the subjects in the StreamConfiguration.
656
         * @param subjects the stream's subjects
657
         * @return The Builder
658
         */
659
        public Builder subjects(String... subjects) {
660
            this.subjects.clear();
1✔
661
            return addSubjects(subjects);
1✔
662
        }
663

664
        /**
665
         * Sets the subjects in the StreamConfiguration.
666
         * @param subjects the stream's subjects
667
         * @return The Builder
668
         */
669
        public Builder subjects(Collection<String> subjects) {
670
            this.subjects.clear();
1✔
671
            return addSubjects(subjects);
1✔
672
        }
673

674
        /**
675
         * Adds unique subjects into the StreamConfiguration.
676
         * @param subjects the stream's subjects to add
677
         * @return The Builder
678
         */
679
        public Builder addSubjects(String... subjects) {
680
            if (subjects != null) {
1✔
681
                return addSubjects(Arrays.asList(subjects));
1✔
682
            }
683
            return this;
1✔
684
        }
685

686
        /**
687
         * Adds unique subjects into the StreamConfiguration.
688
         * @param subjects the stream's subjects to add
689
         * @return The Builder
690
         */
691
        public Builder addSubjects(Collection<String> subjects) {
692
            if (subjects != null) {
1✔
693
                for (String sub : subjects) {
1✔
694
                    if (sub != null && !this.subjects.contains(sub)) {
1✔
695
                        this.subjects.add(sub);
1✔
696
                    }
697
                }
1✔
698
            }
699
            return this;
1✔
700
        }
701

702
        /**
703
         * Sets the retention policy in the StreamConfiguration.
704
         * @param policy the retention policy of the StreamConfiguration
705
         * @return The Builder
706
         */
707
        public Builder retentionPolicy(RetentionPolicy policy) {
708
            this.retentionPolicy = policy == null ? RetentionPolicy.Limits : policy;
1✔
709
            return this;
1✔
710
        }
711

712
        /**
713
         * Sets the compression option in the StreamConfiguration.
714
         * @param compressionOption the compression option of the StreamConfiguration
715
         * @return The Builder
716
         */
717
        public Builder compressionOption(CompressionOption compressionOption) {
718
            this.compressionOption = compressionOption == null ? CompressionOption.None : compressionOption;
1✔
719
            return this;
1✔
720
        }
721

722
        /**
723
         * Sets the maximum number of consumers in the StreamConfiguration.
724
         * @param maxConsumers the maximum number of consumers
725
         * @return The Builder
726
         */        
727
        public Builder maxConsumers(long maxConsumers) {
728
            this.maxConsumers = validateMaxConsumers(maxConsumers);
1✔
729
            return this;
1✔
730
        }
731

732
        /**
733
         * Sets the maximum number of messages in the StreamConfiguration.
734
         * @param maxMsgs the maximum number of messages
735
         * @return The Builder
736
         */
737
        public Builder maxMessages(long maxMsgs) {
738
            this.maxMsgs = validateMaxMessages(maxMsgs);
1✔
739
            return this;
1✔
740
        }
741

742
        /**
743
         * Sets the maximum number of message per subject in the StreamConfiguration.
744
         * @param maxMsgsPerSubject the maximum number of messages
745
         * @return The Builder
746
         */
747
        public Builder maxMessagesPerSubject(long maxMsgsPerSubject) {
748
            this.maxMsgsPerSubject = validateMaxMessagesPerSubject(maxMsgsPerSubject);
1✔
749
            return this;
1✔
750
        }
751

752
        /**
753
         * Sets the maximum number of bytes in the StreamConfiguration.
754
         * @param maxBytes the maximum number of bytes
755
         * @return The Builder
756
         */
757
        public Builder maxBytes(long maxBytes) {
758
            this.maxBytes = validateMaxBytes(maxBytes);
1✔
759
            return this;
1✔
760
        }
761

762
        /**
763
         * Sets the maximum age in the StreamConfiguration.
764
         * @param maxAge the maximum message age
765
         * @return The Builder
766
         */
767
        public Builder maxAge(Duration maxAge) {
768
            this.maxAge = validateDurationNotRequiredGtOrEqZero(maxAge, Duration.ZERO);
1✔
769
            return this;
1✔
770
        }
771

772
        /**
773
         * Sets the maximum age in the StreamConfiguration.
774
         * @param maxAgeMillis the maximum message age
775
         * @return The Builder
776
         */
777
        public Builder maxAge(long maxAgeMillis) {
778
            this.maxAge = validateDurationNotRequiredGtOrEqZero(maxAgeMillis);
1✔
779
            return this;
1✔
780
        }
781

782
        /**
783
         * Sets the maximum message size in the StreamConfiguration.
784
         * @deprecated the server value is a 32-bit signed value. Use {@link #maximumMessageSize(int)} instead.
785
         * @param maxMsgSize the maximum message size
786
         * @return The Builder
787
         */
788
        @Deprecated
789
        public Builder maxMsgSize(long maxMsgSize) {
790
            this.maxMsgSize = (int)validateMaxMessageSize(maxMsgSize);
1✔
791
            return this;
1✔
792
        }
793

794
        /**
795
         * Sets the maximum message size in the StreamConfiguration.
796
         * @param maxMsgSize the maximum message size
797
         * @return The Builder
798
         */
799
        public Builder maximumMessageSize(int maxMsgSize) {
800
            this.maxMsgSize = (int)validateMaxMessageSize(maxMsgSize);
1✔
801
            return this;
1✔
802
        }
803

804
        /**
805
         * Sets the storage type in the StreamConfiguration.
806
         * @param storageType the storage type
807
         * @return The Builder
808
         */        
809
        public Builder storageType(StorageType storageType) {
810
            this.storageType = storageType == null ? StorageType.File : storageType;
1✔
811
            return this;
1✔
812
        }
813

814
        /**
815
         * Sets the number of replicas a message must be stored on in the StreamConfiguration.
816
         * Must be 1 to 5 inclusive
817
         * @param replicas the number of replicas to store this message on
818
         * @return The Builder
819
         */
820
        public Builder replicas(int replicas) {
821
            this.replicas = validateNumberOfReplicas(replicas);
1✔
822
            return this;
1✔
823
        }
824

825
        /**
826
         * Sets the acknowledgement mode of the StreamConfiguration.  if no acknowledgements are
827
         * set, then acknowledgements are not sent back to the client.  The default is false.
828
         * @param noAck true to disable acknowledgements.
829
         * @return The Builder
830
         */        
831
        public Builder noAck(boolean noAck) {
832
            this.noAck = noAck;
1✔
833
            return this;
1✔
834
        }
835

836
        /**
837
         * Sets the template a stream in the form of raw JSON.
838
         * @param templateOwner the stream template of the stream.
839
         * @return the builder
840
         */
841
        public Builder templateOwner(String templateOwner) {
842
            this.templateOwner = emptyAsNull(templateOwner);
1✔
843
            return this;
1✔
844
        }
845

846
        /**
847
         * Sets the discard policy in the StreamConfiguration.
848
         * @param policy the discard policy of the StreamConfiguration
849
         * @return The Builder
850
         */
851
        public Builder discardPolicy(DiscardPolicy policy) {
852
            this.discardPolicy = policy == null ? DiscardPolicy.Old : policy;
1✔
853
            return this;
1✔
854
        }
855

856
        /**
857
         * Sets the duplicate checking window in the StreamConfiguration.  A Duration.Zero
858
         * disables duplicate checking.  Duplicate checking is disabled by default.
859
         * @param window duration to hold message ids for duplicate checking.
860
         * @return The Builder
861
         */
862
        public Builder duplicateWindow(Duration window) {
863
            this.duplicateWindow = validateDurationNotRequiredGtOrEqZero(window, Duration.ZERO);
1✔
864
            return this;
1✔
865
        }
866

867
        /**
868
         * Sets the duplicate checking window in the StreamConfiguration.  A Duration.Zero
869
         * disables duplicate checking.  Duplicate checking is disabled by default.
870
         * @param windowMillis duration to hold message ids for duplicate checking.
871
         * @return The Builder
872
         */
873
        public Builder duplicateWindow(long windowMillis) {
874
            this.duplicateWindow = validateDurationNotRequiredGtOrEqZero(windowMillis);
1✔
875
            return this;
1✔
876
        }
877

878
        /**
879
         * Sets the placement directive object
880
         * @param placement the placement directive object
881
         * @return The Builder
882
         */
883
        public Builder placement(Placement placement) {
884
            this.placement = placement;
1✔
885
            return this;
1✔
886
        }
887

888
        /**
889
         * Sets the republish config object
890
         * @param republish the republish config object
891
         * @return The Builder
892
         */
893
        public Builder republish(Republish republish) {
894
            this.republish = republish;
1✔
895
            return this;
1✔
896
        }
897

898
        /**
899
         * Sets the subjectTransform config object
900
         * @param subjectTransform the subjectTransform config object
901
         * @return The Builder
902
         */
903
        public Builder subjectTransform(SubjectTransform subjectTransform) {
904
            this.subjectTransform = subjectTransform;
1✔
905
            return this;
1✔
906
        }
907

908
        /**
909
         * Sets the consumerLimits config object
910
         * @param consumerLimits the consumerLimits config object
911
         * @return The Builder
912
         */
913
        public Builder consumerLimits(ConsumerLimits consumerLimits) {
914
            this.consumerLimits = consumerLimits;
1✔
915
            return this;
1✔
916
        }
917

918
        /**
919
         * Sets the mirror  object
920
         * @param mirror the mirror object
921
         * @return The Builder
922
         */
923
        public Builder mirror(Mirror mirror) {
924
            this.mirror = mirror;
1✔
925
            return this;
1✔
926
        }
927

928
        /**
929
         * Sets the sources in the StreamConfiguration.
930
         * @param sources the stream's sources
931
         * @return The Builder
932
         */
933
        public Builder sources(Source... sources) {
934
            this.sources.clear();
1✔
935
            return addSources(sources);
1✔
936
        }
937

938
        /**
939
         * Add the sources into the StreamConfiguration.
940
         * @param sources the stream's sources
941
         * @return The Builder
942
         */
943
        public Builder sources(Collection<Source> sources) {
944
            this.sources.clear();
1✔
945
            return addSources(sources);
1✔
946
        }
947

948
        /**
949
         * Add the sources into the StreamConfiguration.
950
         * @param sources the stream's sources
951
         * @return The Builder
952
         */
953
        public Builder addSources(Source... sources) {
954
            return addSources(Arrays.asList(sources));
1✔
955
        }
956

957
        /**
958
         * Sets the sources in the StreamConfiguration.
959
         * @param sources the stream's sources
960
         * @return The Builder
961
         */
962
        public Builder addSources(Collection<Source> sources) {
963
            if (sources != null) {
1✔
964
                for (Source source : sources) {
1✔
965
                    if (source != null && !this.sources.contains(source)) {
1✔
966
                        this.sources.add(source);
1✔
967
                    }
968
                }
1✔
969
            }
970
            return this;
1✔
971
        }
972

973
        /**
974
         * Add a source into the StreamConfiguration.
975
         * @param source a stream source
976
         * @return The Builder
977
         */
978
        public Builder addSource(Source source) {
979
            if (source != null && !this.sources.contains(source)) {
1✔
980
                this.sources.add(source);
1✔
981
            }
982
            return this;
1✔
983
        }
984

985
        /**
986
         * Set whether to seal the stream.
987
         * INTERNAL USE ONLY. Scoped protected for test purposes.
988
         * @param sealed the sealed setting
989
         * @return The Builder
990
         */
991
        protected Builder sealed(boolean sealed) {
992
            this.sealed = sealed;
1✔
993
            return this;
1✔
994
        }
995

996
        /**
997
         * Set whether to allow the rollup feature for a stream
998
         * @param allowRollup the allow rollup setting
999
         * @return The Builder
1000
         */
1001
        public Builder allowRollup(boolean allowRollup) {
1002
            this.allowRollup = allowRollup;
1✔
1003
            return this;
1✔
1004
        }
1005

1006
        /**
1007
         * Set whether to allow direct message access for a stream
1008
         * @param allowDirect the allow direct setting
1009
         * @return The Builder
1010
         */
1011
        public Builder allowDirect(boolean allowDirect) {
1012
            this.allowDirect = allowDirect;
1✔
1013
            return this;
1✔
1014
        }
1015

1016
        /**
1017
         * Set whether to allow unified direct access for mirrors
1018
         * @param mirrorDirect the allow direct setting
1019
         * @return The Builder
1020
         */
1021
        public Builder mirrorDirect(boolean mirrorDirect) {
1022
            this.mirrorDirect = mirrorDirect;
1✔
1023
            return this;
1✔
1024
        }
1025

1026
        /**
1027
         * Set whether to deny deleting messages from the stream
1028
         * @param denyDelete the deny delete setting
1029
         * @return The Builder
1030
         */
1031
        public Builder denyDelete(boolean denyDelete) {
1032
            this.denyDelete = denyDelete;
1✔
1033
            return this;
1✔
1034
        }
1035

1036
        /**
1037
         * Set whether to deny purging messages from the stream
1038
         * @param denyPurge the deny purge setting
1039
         * @return The Builder
1040
         */
1041
        public Builder denyPurge(boolean denyPurge) {
1042
            this.denyPurge = denyPurge;
1✔
1043
            return this;
1✔
1044
        }
1045

1046
        /**
1047
         * Set whether discard policy new with max message per subject applies to existing subjects, not just new subjects.
1048
         * @param discardNewPerSubject the setting
1049
         * @return The Builder
1050
         */
1051
        public Builder discardNewPerSubject(boolean discardNewPerSubject) {
1052
            this.discardNewPerSubject = discardNewPerSubject;
1✔
1053
            return this;
1✔
1054
        }
1055

1056
        /**
1057
         * Set this stream to be sealed. This is irreversible.
1058
         * @return The Builder
1059
         */
1060
        public Builder seal() {
1061
            this.sealed = true;
1✔
1062
            return this;
1✔
1063
        }
1064

1065
        /**
1066
         * Sets the metadata for the configuration
1067
         * @param metadata the metadata map
1068
         * @return The Builder
1069
         */
1070
        public Builder metadata(Map<String, String> metadata) {
1071
            this.metadata = metadata;
1✔
1072
            return this;
1✔
1073
        }
1074

1075
        /**
1076
         * Sets the first sequence to be used. 1 is the default. All values less than 2 are treated as 1.
1077
         * @param firstSeq specify the first_seq in the stream config when creating the stream.
1078
         * @return The Builder
1079
         */
1080
        public Builder firstSequence(long firstSeq) {
1081
            this.firstSequence = firstSeq > 1 ? firstSeq : 1;
1✔
1082
            return this;
1✔
1083
        }
1084

1085
        /**
1086
         * Set to allow per message TTL to true
1087
         * @return The Builder
1088
         */
1089
        public Builder allowMessageTtl() {
1090
            this.allowMessageTtl = true;
1✔
1091
            return this;
1✔
1092
        }
1093

1094
        /**
1095
         * Set allow per message TTL flag
1096
         * @param allowMessageTtl the flag
1097
         * @return The Builder
1098
         */
1099
        public Builder allowMessageTtl(boolean allowMessageTtl) {
1100
            this.allowMessageTtl = allowMessageTtl;
1✔
1101
            return this;
1✔
1102
        }
1103

1104
        /**
1105
         * Set the subject delete marker TTL duration. Server accepts 1 second or more.
1106
         * null has the effect of clearing the subject delete marker TTL
1107
         * @param subjectDeleteMarkerTtl the TTL duration
1108
         * @return The Builder
1109
         */
1110
        public Builder subjectDeleteMarkerTtl(Duration subjectDeleteMarkerTtl) {
1111
            this.subjectDeleteMarkerTtl = validateDurationNotRequiredGtOrEqSeconds(1, subjectDeleteMarkerTtl, null, "Subject Delete Marker Ttl");
1✔
1112
            return this;
1✔
1113
        }
1114

1115
        /**
1116
         * Set the subject delete marker TTL duration in milliseconds. Server accepts 1 second or more.
1117
         * 0 or less has the effect of clearing the subject delete marker TTL
1118
         * @param subjectDeleteMarkerTtlMillis the TTL duration in milliseconds
1119
         * @return The Builder
1120
         */
1121
        public Builder subjectDeleteMarkerTtl(long subjectDeleteMarkerTtlMillis) {
1122
            this.subjectDeleteMarkerTtl = subjectDeleteMarkerTtlMillis <= 0 ? null
1✔
1123
                : validateDurationGtOrEqSeconds(1, subjectDeleteMarkerTtlMillis, "Subject Delete Marker Ttl");
×
1124
            return this;
×
1125
        }
1126

1127
        /**
1128
         * Builds the StreamConfiguration
1129
         * @return a stream configuration.
1130
         */
1131
        public StreamConfiguration build() {
1132
            if (nullOrEmpty(name)) {
1✔
NEW
1133
                throw new IllegalArgumentException("Configuration must have a valid stream name");
×
1134
            }
1135

1136
            return new StreamConfiguration(this);
1✔
1137
        }
1138
    }
1139
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc