Skip to content

Commit 3085052

Browse files
SyncClient: avoid credentials NPE, simplify constructors #252
Also link docs instead of duplicating them.
1 parent f0744ce commit 3085052

File tree

5 files changed

+49
-43
lines changed

5 files changed

+49
-43
lines changed

objectbox-java/src/main/java/io/objectbox/sync/Sync.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,9 @@ public static SyncBuilder client(BoxStore boxStore, String url, SyncCredentials
6464
}
6565

6666
/**
67-
* Starts building a {@link SyncClient}. Once done, complete with {@link SyncBuilder#build() build()}.
67+
* Like {@link #client(BoxStore, String, SyncCredentials)}, but supports passing a set of authentication methods.
6868
*
69-
* @param boxStore The {@link BoxStore} the client should use.
70-
* @param url The URL of the Sync server on which the Sync protocol is exposed. This is typically a WebSockets URL
71-
* starting with {@code ws://} or {@code wss://} (for encrypted connections), for example
72-
* {@code ws://127.0.0.1:9999}.
73-
* @param multipleCredentials An array of {@link SyncCredentials} to be used to authenticate the user.
69+
* @param multipleCredentials An array of {@link SyncCredentials} to be used to authenticate with the server.
7470
*/
7571
public static SyncBuilder client(BoxStore boxStore, String url, SyncCredentials[] multipleCredentials) {
7672
return new SyncBuilder(boxStore, url, multipleCredentials);

objectbox-java/src/main/java/io/objectbox/sync/SyncBuilder.java

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 ObjectBox Ltd. All rights reserved.
2+
* Copyright 2019-2025 ObjectBox Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ public final class SyncBuilder {
4242

4343
final Platform platform;
4444
final BoxStore boxStore;
45-
String url;
45+
@Nullable private String url;
4646
final List<SyncCredentials> credentials;
4747

4848
@Nullable SyncLoginListener loginListener;
@@ -94,41 +94,32 @@ private static void checkSyncFeatureAvailable() {
9494
}
9595
}
9696

97-
98-
@Internal
99-
public SyncBuilder(BoxStore boxStore, SyncCredentials credentials) {
97+
private SyncBuilder(BoxStore boxStore, @Nullable String url, @Nullable List<SyncCredentials> credentials) {
10098
checkNotNull(boxStore, "BoxStore is required.");
10199
checkNotNull(credentials, "Sync credentials are required.");
102-
checkSyncFeatureAvailable();
103-
this.platform = Platform.findPlatform();
104100
this.boxStore = boxStore;
105-
this.credentials = Collections.singletonList(credentials);
101+
this.url = url;
102+
this.credentials = credentials;
103+
checkSyncFeatureAvailable();
104+
this.platform = Platform.findPlatform(); // Requires APIs only present in Android Sync library
106105
}
107106

108107
@Internal
109-
public SyncBuilder(BoxStore boxStore, SyncCredentials[] multipleCredentials) {
110-
checkNotNull(boxStore, "BoxStore is required.");
111-
if (multipleCredentials.length == 0) {
112-
throw new IllegalArgumentException("At least one Sync credential is required.");
113-
}
114-
checkSyncFeatureAvailable();
115-
this.platform = Platform.findPlatform();
116-
this.boxStore = boxStore;
117-
this.credentials = Arrays.asList(multipleCredentials);
108+
public SyncBuilder(BoxStore boxStore, String url, @Nullable SyncCredentials credentials) {
109+
this(boxStore, url, credentials == null ? null : Collections.singletonList(credentials));
118110
}
119111

120112
@Internal
121-
public SyncBuilder(BoxStore boxStore, String url, SyncCredentials credentials) {
122-
this(boxStore, credentials);
123-
checkNotNull(url, "Sync server URL is required.");
124-
this.url = url;
113+
public SyncBuilder(BoxStore boxStore, String url, @Nullable SyncCredentials[] multipleCredentials) {
114+
this(boxStore, url, multipleCredentials == null ? null : Arrays.asList(multipleCredentials));
125115
}
126116

117+
/**
118+
* When using this constructor, make sure to set the server URL before starting.
119+
*/
127120
@Internal
128-
public SyncBuilder(BoxStore boxStore, String url, SyncCredentials[] multipleCredentials) {
129-
this(boxStore, multipleCredentials);
130-
checkNotNull(url, "Sync server URL is required.");
131-
this.url = url;
121+
public SyncBuilder(BoxStore boxStore, @Nullable SyncCredentials credentials) {
122+
this(boxStore, null, credentials == null ? null : Collections.singletonList(credentials));
132123
}
133124

134125
/**
@@ -140,6 +131,12 @@ SyncBuilder serverUrl(String url) {
140131
return this;
141132
}
142133

134+
@Internal
135+
String serverUrl() {
136+
checkNotNull(url, "Sync Server URL is null.");
137+
return url;
138+
}
139+
143140
/**
144141
* Configures a custom set of directory or file paths to search for trusted certificates in.
145142
* The first path that exists will be used.
@@ -261,7 +258,7 @@ public SyncClient buildAndStart() {
261258
return syncClient;
262259
}
263260

264-
private void checkNotNull(Object object, String message) {
261+
private void checkNotNull(@Nullable Object object, String message) {
265262
//noinspection ConstantConditions Non-null annotation does not enforce, so check for null.
266263
if (object == null) {
267264
throw new IllegalArgumentException(message);

objectbox-java/src/main/java/io/objectbox/sync/SyncClient.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 ObjectBox Ltd. All rights reserved.
2+
* Copyright 2019-2025 ObjectBox Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -128,14 +128,13 @@ public interface SyncClient extends Closeable {
128128
void setSyncTimeListener(@Nullable SyncTimeListener timeListener);
129129

130130
/**
131-
* Updates the login credentials. This should not be required during regular use.
131+
* Updates the credentials used to authenticate with the server. This should not be required during regular use.
132132
* The original credentials were passed when building sync client.
133133
*/
134134
void setLoginCredentials(SyncCredentials credentials);
135135

136136
/**
137-
* Updates the login credentials. This should not be required during regular use.
138-
* It allows passing login credentials that the client can use to authenticate with the server.
137+
* Like {@link #setLoginCredentials(SyncCredentials)}, but allows setting multiple credentials.
139138
*/
140139
void setLoginCredentials(SyncCredentials[] multipleCredentials);
141140

objectbox-java/src/main/java/io/objectbox/sync/SyncClientImpl.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 ObjectBox Ltd. All rights reserved.
2+
* Copyright 2019-2025 ObjectBox Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ public final class SyncClientImpl implements SyncClient {
6161

6262
SyncClientImpl(SyncBuilder builder) {
6363
this.boxStore = builder.boxStore;
64-
this.serverUrl = builder.url;
64+
this.serverUrl = builder.serverUrl();
6565
this.connectivityMonitor = builder.platform.getConnectivityMonitor();
6666

6767
long boxStoreHandle = builder.boxStore.getNativeStore();
@@ -189,6 +189,9 @@ public void setSyncListener(@Nullable SyncListener listener) {
189189

190190
@Override
191191
public void setLoginCredentials(SyncCredentials credentials) {
192+
if (credentials == null) {
193+
throw new IllegalArgumentException("credentials must not be null");
194+
}
192195
if (credentials instanceof SyncCredentialsToken) {
193196
SyncCredentialsToken credToken = (SyncCredentialsToken) credentials;
194197
nativeSetLoginInfo(getHandle(), credToken.getTypeId(), credToken.getTokenBytes());
@@ -204,6 +207,9 @@ public void setLoginCredentials(SyncCredentials credentials) {
204207

205208
@Override
206209
public void setLoginCredentials(SyncCredentials[] multipleCredentials) {
210+
if (multipleCredentials == null) {
211+
throw new IllegalArgumentException("credentials must not be null");
212+
}
207213
for (int i = 0; i < multipleCredentials.length; i++) {
208214
SyncCredentials credentials = multipleCredentials[i];
209215
boolean isLast = i == (multipleCredentials.length - 1);

tests/objectbox-java-test/src/test/java/io/objectbox/sync/SyncTest.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 ObjectBox Ltd. All rights reserved.
2+
* Copyright 2020-2025 ObjectBox Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,12 +16,13 @@
1616

1717
package io.objectbox.sync;
1818

19-
import io.objectbox.exception.FeatureNotAvailableException;
2019
import org.junit.Test;
2120

21+
import java.nio.charset.StandardCharsets;
22+
2223
import io.objectbox.AbstractObjectBoxTest;
24+
import io.objectbox.exception.FeatureNotAvailableException;
2325

24-
import java.nio.charset.StandardCharsets;
2526

2627
import static org.junit.Assert.assertArrayEquals;
2728
import static org.junit.Assert.assertFalse;
@@ -31,6 +32,8 @@
3132

3233
public class SyncTest extends AbstractObjectBoxTest {
3334

35+
private static final String SERVER_URL = "wss://127.0.0.1";
36+
3437
/**
3538
* Ensure that non-sync native library correctly reports sync client availability.
3639
* <p>
@@ -54,9 +57,14 @@ public void serverIsNotAvailable() {
5457

5558
@Test
5659
public void creatingSyncClient_throws() {
60+
// If no credentials are passed
61+
assertThrows(IllegalArgumentException.class, () -> Sync.client(store, SERVER_URL, (SyncCredentials) null));
62+
assertThrows(IllegalArgumentException.class, () -> Sync.client(store, SERVER_URL, (SyncCredentials[]) null));
63+
64+
// If no Sync feature is available
5765
FeatureNotAvailableException exception = assertThrows(
5866
FeatureNotAvailableException.class,
59-
() -> Sync.client(store, "wss://127.0.0.1", SyncCredentials.none())
67+
() -> Sync.client(store, SERVER_URL, SyncCredentials.none())
6068
);
6169
String message = exception.getMessage();
6270
assertTrue(message, message.contains("does not include ObjectBox Sync") &&
@@ -67,7 +75,7 @@ public void creatingSyncClient_throws() {
6775
public void creatingSyncServer_throws() {
6876
FeatureNotAvailableException exception = assertThrows(
6977
FeatureNotAvailableException.class,
70-
() -> Sync.server(store, "wss://127.0.0.1", SyncCredentials.none())
78+
() -> Sync.server(store, SERVER_URL, SyncCredentials.none())
7179
);
7280
String message = exception.getMessage();
7381
assertTrue(message, message.contains("does not include ObjectBox Sync Server") &&

0 commit comments

Comments
 (0)