E576 Merge branch '293-more-sync-flags' into dev · objectbox/objectbox-java@f6387d6 · GitHub
[go: up one dir, main page]

Skip to content

Commit f6387d6

Browse files
Merge branch '293-more-sync-flags' into dev
2 parents 7f7dc13 + 2b50013 commit f6387d6

File tree

10 files changed

+308
-74
lines changed

10 files changed

+308
-74
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ For more insights into what changed in the ObjectBox C++ core, [check the Object
99
- The [ObjectBox Gradle plugin](https://github.com/objectbox/objectbox-java-generator) requires JDK 11 and Android
1010
Gradle Plugin 8.1 or newer.
1111

12+
### Sync
13+
14+
- Add simplified `Sync.client(boxStore)` helper method. Move URL and credentials options to builder, add variants that
15+
accept multiple URLs and credentials. Deprecate the existing helper methods.
16+
- Add Sync client builder option to configure Sync behavior using
17+
[SyncFlags](objectbox-java/src/main/java/io/objectbox/sync/SyncFlags.java).
18+
1219
## 5.1.0 - 2026-01-26
1320

1421
- Add [ObjectBoxThreadPoolExecutor](objectbox-java/src/main/java/io/objectbox/ObjectBoxThreadPoolExecutor.java), a

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package io.objectbox.sync;
1818

19+
import java.util.Arrays;
20+
1921
import io.objectbox.BoxStore;
2022
import io.objectbox.BoxStoreBuilder;
2123
import io.objectbox.sync.server.SyncServer;
@@ -50,6 +52,23 @@ public static boolean isHybridAvailable() {
5052
return isAvailable() && isServerAvailable();
5153
}
5254

55+
/**
56+
* Starts building a {@link SyncClient} for the given {@link BoxStore}.
57+
* <p>
58+
* This does not initiate any connection attempts yet: call {@link SyncBuilder#buildAndStart()} to do so. Before,
59+
* you must configure the server URL via {@link SyncBuilder#url(String)} and add credentials via
60+
* {@link SyncBuilder#credentials(SyncCredentials)}.
61+
* <p>
62+
* By default, a Sync client automatically receives updates from the server once login succeeded. To configure this
63+
* differently, call {@link SyncBuilder#requestUpdatesMode(SyncBuilder.RequestUpdatesMode)} with the wanted mode.
64+
*
65+
* @param boxStore The {@link BoxStore} the client should use.
66+
* @return a builder to configure the Sync client
67+
*/
68+
public static SyncBuilder client(BoxStore boxStore) {
69+
return new SyncBuilder(boxStore);
70+
}
71+
5372
/**
5473
* Starts building a {@link SyncClient}. Once done, complete with {@link SyncBuilder#build() build()}.
5574
*
@@ -58,18 +77,31 @@ public static boolean isHybridAvailable() {
5877
* starting with {@code ws://} or {@code wss://} (for encrypted connections), for example
5978
* {@code ws://127.0.0.1:9999}.
6079
* @param credentials {@link SyncCredentials} to authenticate with the server.
80+
* @deprecated Use {@link #client(BoxStore)}, {@link SyncBuilder#url(String)} and
81+
* {@link SyncBuilder#credentials(SyncCredentials)} instead.
6182
*/
83+
@Deprecated
6284
public static SyncBuilder client(BoxStore boxStore, String url, SyncCredentials credentials) {
63-
return new SyncBuilder(boxStore, url, credentials);
85+
return client(boxStore)
86+
.url(url)
87+
.credentials(credentials);
6488
}
6589

6690
/**
6791
* Like {@link #client(BoxStore, String, SyncCredentials)}, but supports passing a set of authentication methods.
6892
*
6993
* @param multipleCredentials An array of {@link SyncCredentials} to be used to authenticate with the server.
94+
* @deprecated Use {@link #client(BoxStore)}, {@link SyncBuilder#url(String)} and
95+
* {@link SyncBuilder#credentials(SyncCredentials)} instead.
7096
*/
97+
@Deprecated
7198
public static SyncBuilder client(BoxStore boxStore, String url, SyncCredentials[] multipleCredentials) {
72-
return new SyncBuilder(boxStore, url, multipleCredentials);
99+
SyncBuilder builder = client(boxStore).url(url);
100+
//noinspection ConstantValue
101+
if (multipleCredentials != null) {
102+
builder.credentials(Arrays.asList(multipleCredentials));
103+
}
104+
return builder;
73105
}
74106

75107
/**

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

Lines changed: 82 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,15 @@
1616

1717
package io.objectbox.sync;
1818

19+
import java.util.ArrayList;
1920
import java.util.Arrays;
20-
import java.util.Collections;
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.TreeMap;
2424

2525
import javax.annotation.Nullable;
2626

2727
import io.objectbox.BoxStore;
28-
import io.objectbox.annotation.apihint.Internal;
2928
import io.objectbox.exception.FeatureNotAvailableException;
3029
import io.objectbox.sync.internal.Platform;
3130
import io.objectbox.sync.listener.SyncChangeListener;
@@ -36,16 +35,15 @@
3635
import io.objectbox.sync.listener.SyncTimeListener;
3736

3837
/**
39-
* A builder to create a {@link SyncClient}; the builder itself should be created via
40-
* {@link Sync#client(BoxStore, String, SyncCredentials)}.
38+
* A builder to create a {@link SyncClient}; the builder itself should be created via {@link Sync#client(BoxStore)}.
4139
*/
4240
@SuppressWarnings({"unused", "WeakerAccess"})
4341
public final class SyncBuilder {
4442

4543
final Platform platform;
4644
final BoxStore boxStore;
47-
@Nullable private String url;
48-
final List<SyncCredentials> credentials;
45+
final List<String> urls = new ArrayList<>();
46+
final List<SyncCredentials> credentials = new ArrayList<>();
4947

5048
@Nullable SyncLoginListener loginListener;
5149
@Nullable SyncCompletedListener completedListener;
@@ -56,6 +54,7 @@ public final class SyncBuilder {
5654

5755
@Nullable
5856
String[] trustedCertPaths;
57+
int flags;
5958
boolean uncommittedAcks;
6059

6160
RequestUpdatesMode requestUpdatesMode = RequestUpdatesMode.AUTO;
@@ -98,47 +97,80 @@ private static void checkSyncFeatureAvailable() {
9897
}
9998
}
10099

101-
private SyncBuilder(BoxStore boxStore, @Nullable String url, @Nullable List<SyncCredentials> credentials) {
102-
checkNotNull(boxStore, "BoxStore is required.");
103-
checkNotNull(credentials, "Sync credentials are required.");
100+
/**
101+
* Creates a builder for a {@link SyncClient}.
102+
* <p>
103+
* Don't use this directly, use the {@link Sync#client} method instead.
104+
*/
105+
SyncBuilder(BoxStore boxStore) {
106+
checkNotNull(boxStore, "boxStore");
104107
this.boxStore = boxStore;
105-
this.url = url;
106-
this.credentials = credentials;
107108
checkSyncFeatureAvailable();
108109
this.platform = Platform.findPlatform(); // Requires APIs only present in Android Sync library
109110
}
110111

111-
@Internal
112-
public SyncBuilder(BoxStore boxStore, String url, @Nullable SyncCredentials credentials) {
113-
this(boxStore, url, credentials == null ? null : Collections.singletonList(credentials));
114-
}
115-
116-
@Internal
117-
public SyncBuilder(BoxStore boxStore, String url, @Nullable SyncCredentials[] multipleCredentials) {
118-
this(boxStore, url, multipleCredentials == null ? null : Arrays.asList(multipleCredentials));
112+
/**
113+
* Adds a Sync server URL the client should connect to.
114+
* <p>
115+
* This is typically a WebSockets URL starting with {@code ws://} or {@code wss://} (for encrypted connections), for
116+
* example if the server is running on localhost {@code ws://127.0.0.1:9999}.
117+
* <p>
118+
* Can be called multiple times to add multiple URLs for high availability and load balancing (like when using an
119+
* ObjectBox Sync Server Cluster). A random URL is selected for each connection attempt.
120+
*
121+
* @param url The URL of the Sync server on which the Sync protocol is exposed.
122+
* @return this builder for chaining
123+
* @see #urls(List)
124+
*/
125+
public SyncBuilder url(String url) {
126+
checkNotNull(url, "url");
127+
this.urls.add(url);
128+
return this;
119129
}
120130

121131
/**
122-
* When using this constructor, make sure to set the server URL before starting.
132+
* Like {@link #url(String)}, but accepts a list of URLs.
133+
*
134+
* @param urls A list of URLs of Sync servers on which the Sync protocol is exposed.
135+
* @return this builder for chaining
136+
* @see #url(String)
123137
*/
124-
@Internal
125-
public SyncBuilder(BoxStore boxStore, @Nullable SyncCredentials credentials) {
126-
this(boxStore, null, credentials == null ? null : Collections.singletonList(credentials));
138+
public SyncBuilder urls(List<String> urls) {
139+
checkNotNull(urls, "urls");
140+
for (String url : urls) {
141+
url(url);
142+
}
143+
return this;
127144
}
128145

129146
/**
130-
* Allows internal code to set the Sync server URL after creating this builder.
147+
* Adds {@link SyncCredentials} to authenticate the client with the server.
148+
* <p>
149+
* The accepted credentials types depend on your Sync server configuration.
150+
*
151+
* @param credentials credentials created using a {@link SyncCredentials} factory method, for example
152+
* {@code SyncCredentials.jwtIdToken(idToken)}.
153+
* @see #credentials(List)
131154
*/
132-
@Internal
133-
SyncBuilder serverUrl(String url) {
134-
this.url = url;
155+
public SyncBuilder credentials(SyncCredentials credentials) {
156+
checkNotNull(credentials, "credentials");
157+
this.credentials.add(credentials);
135158
return this;
136159
}
137160

138-
@Internal
139-
String serverUrl() {
140-
checkNotNull(url, "Sync Server URL is null.");
141-
return url;
161+
/**
162+
* Like {@link #credentials(SyncCredentials)}, but accepts a list of credentials.
163+
*
164+
* @param credentials a list of credentials where each element is created using a {@link SyncCredentials} factory
165+
* method, for example {@code SyncCredentials.jwtIdToken(idToken)}.
166+
* @return this builder for chaining
167+
*/
168+
public SyncBuilder credentials(List<SyncCredentials> credentials) {
169+
checkNotNull(credentials, "credentials");
170+
for (SyncCredentials credential : credentials) {
171+
credentials(credential);
172+
}
173+
return this;
142174
}
143175

144176
/**
@@ -151,8 +183,8 @@ String serverUrl() {
151183
* @see SyncClient#putFilterVariable
152184
*/
153185
public SyncBuilder filterVariable(String name, String value) {
154-
checkNotNull(name, "Filter variable name is null.");
155-
checkNotNull(value, "Filter variable value is null.");
186+
checkNotNull(name, "name");
187+
checkNotNull(value, "value");
156188
filterVariables.put(name, value);
157189
return this;
158190
}
@@ -170,6 +202,16 @@ public SyncBuilder trustedCertificates(String[] paths) {
170202
return this;
171203
}
172204

205+
/**
206+
* Sets bit flags to adjust Sync behavior, like additional logging.
207+
*
208+
* @param flags One or multiple {@link SyncFlags}, combined with bitwise or.
209+
*/
210+
public SyncBuilder flags(int flags) {
211+
this.flags = flags;
212+
return this;
213+
}
214+
173215
/**
174216
* Configure automatic sync updates from the server.
175217
* If automatic sync updates are turned off, they will need to be requested using the sync client.
@@ -265,23 +307,25 @@ public SyncClient build() {
265307
if (boxStore.getSyncClient() != null) {
266308
throw new IllegalStateException("The given store is already associated with a Sync client, close it first.");
267309
}
268-
checkNotNull(url, "Sync Server URL is required.");
269310
return new SyncClientImpl(this);
270311
}
271312

272313
/**
273-
* Builds, {@link SyncClient#start() starts} and returns a Sync client.
314+
* {@link #build() Builds}, {@link SyncClient#start() starts} and returns a Sync client.
274315
*/
275316
public SyncClient buildAndStart() {
276317
SyncClient syncClient = build();
277318
syncClient.start();
278319
return syncClient;
279320
}
280321

281-
private void checkNotNull(@Nullable Object object, String message) {
282-
//noinspection ConstantConditions Non-null annotation does not enforce, so check for null.
322+
/**
323+
* Nullness annotations are only a hint in Java, so explicitly check nonnull annotated parameters
324+
* (see package-info.java for package settings).
325+
*/
326+
private void checkNotNull(@Nullable Object object, String name) {
283327
if (object == null) {
284-
throw new IllegalArgumentException(message);
328+
throw new IllegalArgumentException(name + " must not be null.");
285329
}
286330
}
287331

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.objectbox.sync;
1818

1919
import java.io.Closeable;
20+
import java.util.List;
2021

2122
import javax.annotation.Nullable;
2223

@@ -42,9 +43,19 @@ public interface SyncClient extends Closeable {
4243

4344
/**
4445
* Gets the sync server URL this client is connected to.
46< 1004E span class="diff-text-marker">+
*
47+
* @deprecated Use {@link #getUrls()}
4548
*/
49+
@Deprecated
4650
String getServerUrl();
4751

52+
/**
53+
* Gets the sync server URLs this client may connect to.
54+
* <p>
55+
* See {@link SyncBuilder#url(String)} for notes on multiple URLs.
56+
*/
57+
List<String> getUrls();
58+
4859
/**
4960
* Flag indicating if the sync client was started.
5061
* Started clients try to connect, login, and sync with the sync destination.
@@ -158,13 +169,34 @@ public interface SyncClient extends Closeable {
158169
void removeAllFilterVariables();
159170

160171
/**
161-
* Updates the credentials used to authenticate with the server. This should not be required during regular use.
162-
* The original credentials were passed when building sync client.
172+
* Sets credentials to authenticate the client with the server.
173+
* <p>
174+
* Any credentials that were set before are replaced.
175+
* <p>
176+
* Usually, credentials are passed via {@link SyncBuilder#credentials(SyncCredentials)}, but this can be used to
177+
* update them later, such as when a token expires.
178+
* <p>
179+
* The accepted credentials type depends on your Sync server configuration.
180+
*
181+
* @param credentials credentials created using a {@link SyncCredentials} factory method, for example
182+
* {@code SyncCredentials.jwtIdToken(idToken)}.
183+
* @see #setLoginCredentials(List)
163184
*/
164185
void setLoginCredentials(SyncCredentials credentials);
165186

166187
/**
167-
* Like {@link #setLoginCredentials(SyncCredentials)}, but allows setting multiple credentials.
188+
* Like {@link #setLoginCredentials(SyncCredentials)}, but accepts a list of credentials.
189+
*
190+
* @param credentials a list of credentials where each element is created using a {@link SyncCredentials} factory
191+
* method, for example {@code SyncCredentials.jwtIdToken(idToken)}.
192+
*/
193+
void setLoginCredentials(List<SyncCredentials> credentials);
194+
195+
/**
196+
* Like {@link #setLoginCredentials(SyncCredentials)}, but accepts an array of credentials.
197+
*
198+
* @param multipleCredentials an array of credentials where each element is created using a {@link SyncCredentials}
199+
* factory method, for example {@code SyncCredentials.jwtIdToken(idToken)}.
168200
*/
169201
void setLoginCredentials(SyncCredentials[] multipleCredentials);
170202

0 commit comments

Comments
 (0)
0