Skip to content

Commit

Permalink
(DOCSP-31727): Java SDK Migrate PBS to FS Updates (mongodb#2921)
Browse files Browse the repository at this point in the history
## Pull Request Info

### Jira

- https://jira.mongodb.org/browse/DOCSP-31727

### Staged Changes

- [Sync
Data](https://docs-mongodbcom-staging.corp.mongodb.com/realm/docsworker-xlarge/DOCSP-31727/sdk/java/sync/):
Remove PBS mentions
- [Partition-Based
Sync](https://docs-mongodbcom-staging.corp.mongodb.com/realm/docsworker-xlarge/DOCSP-31727/sdk/java/sync/partition-based-sync/):
New page with moved PBS info and PBS to FS migration info
- [Configure & Open a Synced
Realm](https://docs-mongodbcom-staging.corp.mongodb.com/realm/docsworker-xlarge/DOCSP-31727/sdk/java/sync/configure-and-open-a-synced-realm/):
Remove PBS info, update the "Synchronous Reads & Writes on the UI
Thread" `Important` callout to show FS code examples

### Reminder Checklist

If your PR modifies the docs, you might need to also update some
corresponding
pages. Check if completed or N/A.

- [x] Create Jira ticket for corresponding docs-app-services update(s),
if any
- [x] Checked/updated Admin API
- [x] Checked/updated CLI reference

### Review Guidelines


[REVIEWING.md](https://github.com/mongodb/docs-realm/blob/master/REVIEWING.md)
  • Loading branch information
dacharyc authored Jul 31, 2023
1 parent 48d3979 commit c6d39c8
Show file tree
Hide file tree
Showing 9 changed files with 393 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,59 @@ public void onSuccess(Realm realm) {
expectation.await();
}

@Test
public void openARealmForReadWriteUIThread() {
Expectation expectation = new Expectation();
activity.runOnUiThread (() -> {
// instantiate a Realm App connection
String appID = YOUR_APP_ID; // replace this with your App ID
App app = new App(new AppConfiguration.Builder(appID)
.build());
// authenticate a user
Credentials credentials = Credentials.anonymous();
app.loginAsync(credentials, it -> {
if (it.isSuccess()) {
User user = it.get();
// add an initial subscription to the sync configuration
// :snippet-start: fs-allow-queries-on-ui-thread
SyncConfiguration config = new SyncConfiguration.Builder(user)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("springPeepers",
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
// :remove-start:
.inMemory()
.waitForInitialRemoteData(2112, TimeUnit.MILLISECONDS)
// :remove-end:
.build();

Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread.");
// :remove-start:
realm.close();
expectation.fulfill();
// :remove-end:
}
});
// :snippet-end:
} else {
Log.e("EXAMPLE", "Failed to log in: " + it.getError().getErrorMessage());
}
});
});
expectation.await();
}

@Test
public void explicitlyNamedSubscription() {
Expectation expectation = new Expectation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,69 @@ class FlexibleSyncTest : RealmTest() {
expectation.await()
}

@Test
fun openARealmForReadWriteUIThread() {
val expectation = Expectation()
activity!!.runOnUiThread {

// instantiate a Realm App connection
val appID: String = YOUR_APP_ID // replace this with your App ID
val app = App(
AppConfiguration.Builder(appID)
.build()
)
// authenticate a user
val credentials = Credentials.anonymous()
app.loginAsync(
credentials
) { it: App.Result<User?> ->
if (it.isSuccess) {
val user = it.get()

// add an initial subscription to the sync configuration
// :snippet-start: fs-allow-queries-on-ui-thread
val config = SyncConfiguration.Builder(app.currentUser())
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"springPeepers",
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
// :remove-start:
.inMemory()
.waitForInitialRemoteData(2112, TimeUnit.MILLISECONDS)
// :remove-end:
.build()

Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
)
// :remove-start:
realm.close()
expectation.fulfill()
// :remove-end:
}
})
// :snippet-end:
} else {
Log.e(
"EXAMPLE",
"Failed to log in: " + it.error.errorMessage
)
}
}
}
expectation.await()
}

@Test
fun explicitlyNamedSubscription() {
val expectation = Expectation()
Expand Down
2 changes: 1 addition & 1 deletion examples/java/sync/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.31"
ext.kotlin_version = "1.6.0"
repositories {
google()
jcenter()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("springPeepers",
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();

Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread.");
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
val config = SyncConfiguration.Builder(app.currentUser())
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"subscriptionName",
realm.where(Frog::class.java)
.equalTo("species", "springPeepers")
)
)
}
.build()

Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
)
}
})
35 changes: 35 additions & 0 deletions source/includes/java-synchronous-reads-writes-ui-thread-fs.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.. important:: Synchronous Reads and Writes on the UI Thread

By default, you can only read or write to a realm in your
application's UI thread using
:ref:`asynchronous transactions <java-async-api>`. That is,
you can only use ``Realm`` methods whose name ends with the word
``Async`` in the main thread of your Android application unless you
explicitly allow the use of synchronous methods.

This restriction exists for the benefit of your application users:
performing read and write operations on the UI thread can lead to
unresponsive or slow UI interactions, so it's usually best to handle
these operations either asynchronously or in a background thread.
However, if your application requires the use of synchronous
realm reads or writes on the UI thread, you can explicitly allow
the use of synchronous methods with the following
``SyncConfiguration`` options:

.. tabs-realm-languages::

.. tab::
:tabid: java

.. literalinclude:: /examples/generated/java/sync/FlexibleSyncTest.snippet.fs-allow-queries-on-ui-thread.java
:language: java
:emphasize-lines: 2,3
:copyable: false

.. tab::
:tabid: kotlin

.. literalinclude:: /examples/generated/java/sync/FlexibleSyncTest.snippet.fs-allow-queries-on-ui-thread.kt
:language: kotlin
:emphasize-lines: 2,3
:copyable: false
35 changes: 6 additions & 29 deletions source/sdk/java/sync.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Sync Data Between Devices - Java SDK
Check Upload & Download Progress </sdk/java/sync/sync-progress>
Check the Network Connection </sdk/java/sync/network-connection>
Background Sync </sdk/java/sync/background-sync>
Partition-Based Sync </sdk/java/sync/partition-based-sync>

.. contents:: On this page
:local:
Expand All @@ -29,16 +30,6 @@ an :ref:`Atlas App Services backend <realm-cloud>`. When a client
device is online, Sync asynchronously synchronizes data in a
background thread between the device and your backend App.

When you use Sync in your client application, your implementation must match
the Sync Mode you select in your backend App configuration. The Sync Mode
options are:

- Flexible Sync
- Partition-Based Sync

You can only use one Sync Mode for your application. You cannot mix
Partition-Based Sync and Flexible Sync within the same App.

.. seealso::

:ref:`enable-realm-sync`
Expand Down Expand Up @@ -72,25 +63,6 @@ To use Flexible Sync in your client application, open a synced realm
with a flexible sync configuration. Then, manage subscriptions
to determine which documents to sync.

Group Updates for Improved Performance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. include:: /includes/sync-memory-performance.rst

.. _java-partition-based-sync-fundamentals:

Partition-Based Sync
--------------------

When you select :ref:`Partition-Based Sync <partition-based-sync>` for your
backend App configuration, your client implementation must include a
partition value. This is the value of the :ref:`partition key
<partition-key>` field you select when you configure Partition-Based Sync.

The partition value determines which data the client application can access.

You pass in the partition value when you open a synced realm.

.. _java-sync-data:

Sync Data
Expand All @@ -109,3 +81,8 @@ local data, a background thread efficiently integrates, uploads, and downloads c
could appear to hang as it waits for the background sync thread to finish a write
transaction. Therefore, it's a best practice :ref:`never to write on the main thread
when using Sync <java-threading-three-rules>`.

Group Updates for Improved Performance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. include:: /includes/sync-memory-performance.rst
76 changes: 20 additions & 56 deletions source/sdk/java/sync/configure-and-open-a-synced-realm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,67 +40,20 @@ like opening a local realm, except you use ``SyncConfiguration``
to customize the settings for synced realms.

.. _java-synced-realm-configuration:
.. _java-flexible-sync-open-realm:

Synced Realm Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~

To configure settings for a realm, create a
:java-sdk:`SyncConfiguration <io/realm/mongodb/sync/SyncConfiguration.html>` with a
:java-sdk:`SyncConfiguration.Builder <io/realm/mongodb/sync/SyncConfiguration.Builder.html>`.
The following example configures a synced realm with:

- partition-based Sync
- synchronous reads explicitly allowed on the UI thread
- synchronous writes explicitly allowed on the UI thread
- explicit waiting for all backend changes to synchronize to the device
before returning an open realm
- automatic compaction when launching the realm to save file space

.. warning:: Production Applications Should Handle Client Resets

Applications used in production environments should handle client
reset errors. To learn more, see :ref:`Reset a Client Realm
<java-client-resets>`.

.. tabs-realm-languages::

.. tab::
:tabid: kotlin

.. literalinclude:: /examples/generated/java/sync/OpenARealmTest.snippet.configure-a-realm.kt
:language: kotlin

.. tab::
:tabid: java

.. literalinclude:: /examples/generated/java/sync/OpenARealmTest.snippet.configure-a-realm.java
:language: java

.. include:: /includes/java-synchronous-reads-writes-ui-thread.rst

.. _java-open-synced-realm:
.. _java-open-a-synced-realm-while-online:

Open a Synced Realm While Online
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. include:: /includes/java-open-synced-realm.rst

.. _java-open-a-synced-realm-while-offline:

Open a Synced Realm While Offline
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can open a synced realm when offline with the exact same syntax
that you use to :ref:`open a synced realm while online
<java-open-a-synced-realm-while-online>`. Not all SDKs follow this
pattern, so cross-platform developers should consult the documentation
for each SDK to learn more.

.. _java-flexible-sync-open-realm:

Open a Synced Realm with a Flexible Sync Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To open a synced realm, call
:java-sdk:`getInstanceAsync()
<io/realm/Realm.html#getInstanceAsync-io.realm.RealmConfiguration-io.realm.Realm.Callback->`,
passing in a :java-sdk:`SyncConfiguration <io/realm/mongodb/sync/SyncConfiguration.html>`
object.

When your application uses Flexible Sync, call
the :java-sdk:`initialSubscriptions()
Expand All @@ -109,9 +62,7 @@ sync configuration builder method
with an instance of
:java-sdk:`SyncConfiguration.InitialFlexibleSyncSubscriptions()
<io/realm/mongodb/sync/SyncConfiguration.InitialFlexibleSyncSubscriptions.html>`
to open a synced realm. While partition-based Sync requires a partition
value when you instantiate your ``SyncConfiguration``, you should omit
the partition value when you use Flexible Sync. In the ``configure()`` method, instantiate
to open a synced realm. In the ``configure()`` method, instantiate
an ``UnmanagedSubscription`` with a name and query using
:java-sdk:`Subscription.create()
<io/realm/mongodb/sync/Subscription.html#create(java.lang.String,io.realm.RealmQuery)>`.
Expand Down Expand Up @@ -141,6 +92,19 @@ parameter to add it to your subscriptions:
For more information about subscriptions, see
:ref:`Subscribe to Queryable Fields <java-sync-subscribe-to-queryable-fields>`.

.. include:: /includes/java-synchronous-reads-writes-ui-thread-fs.rst

.. _java-open-a-synced-realm-while-offline:

Open a Synced Realm While Offline
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can open a synced realm when offline with the exact same syntax
that you use to :ref:`open a synced realm while online
<java-open-a-synced-realm-while-online>`. Not all SDKs follow this
pattern, so cross-platform developers should consult the documentation
for each SDK to learn more.

.. _java-close-a-synced-realm:

Close a Realm
Expand Down
Loading

0 comments on commit c6d39c8

Please sign in to comment.