⚠ Currently, Couchbase Lite 2.0 is available for Android only. The SDK cannot be used in Java applications.
Create or open an existing Android Studio project and install Couchbase Lite using the following method.
-
Add the following in the
dependencies
section of the application’s build.gradle (the one in the app folder).dependencies { implementation 'com.couchbase.lite:couchbase-lite-android:2.1.0-DB001' }
-
In the top-level build.gradle file, add the following Couchbase Maven repository in the
allprojects
section.allprojects { repositories { google() jcenter() maven { url "http://mobile.maven.couchbase.com/maven2/dev/" } } }
-
Next, add the following in the
dependencies
section of the application’s build.gradle (the one in the app folder).dependencies { implementation 'com.couchbase.lite:couchbase-lite-android-ee:2.1.0-DB001' }
Open MainActivity.java in Android Studio and copy the following code in the didStart
method. This snippet demonstrates how to run basic CRUD operations, a simple Query and running bi-directional replications with Sync Gateway.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
Build and run. You should see the document ID and property printed to the console. The document was successfully persisted to the database.
Platform | Runtime architectures | Minimum API Level |
---|---|---|
Android |
armeabi-v7a |
19 |
Android |
arm64-v8a |
21 |
Android |
x86 |
19 |
The API has changed in Couchbase Lite 2.0 and will require porting an application that is using Couchbase Lite 1.x API to the Couchbase Lite 2.0 API. To update an Xcode project built with Couchbase Lite 1.x:
-
Remove the existing Couchbase Lite dependency from the Android Studio project.
-
Install the Couchbase Lite 2.0 framework in your project (see the installation options). At this point, there will be many compiler warnings. Refer to the examples on this page to learn about the new API.
-
Build & run your application.
Databases that were created with Couchbase Lite 1.2 or later can be used with Couchbase Lite 2.0. Upon detecting it is a 1.x database file, Couchbase Lite will automatically upgrade it to 2.0. This feature is only available for the default storage type (i.e not a ForestDB database). Additionally, the automatic migration feature does not support encrypted databases, so if the 1.x database is encrypted you will first need to disable encryption using the Couchbase Lite 1.x API (see the 1.x Database Guide).
For conflicts in the 1.x database, the automatic upgrade process copies the default winning revision to the new 2.0 database and does NOT copy any conflicting revisions. This functionality is related to the way conflicts are being handled in Couchbase Lite 2.0 (see Handling Conflicts). Optionally, existing conflicts in the 1.x database can be resolved with the 1.x API prior to the database being upgraded to 2.0.
Attachments that were persisted in the 1.x database will be copied to the 2.0 database. In Couchbase Lite 2.0, the Attachment
API has been renamed to Blob
API. The functionally is identical but the internal schema for attachments has changed. In 1.x they were stored under the _attachments
field and in Couchbase Lite 2.0 they are stored anywhere in the document like other value types. The automatic upgrade functionality will not update the internal schema for attachments, so they will still be accessible under the _attachments
field. The following example shows how to retrieve an attachment that was created in a 1.x database with the 2.0 API.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The replication protocol used in Couchbase Lite 2.0 has been re-designed from the ground up and it is not backwards compatible with the 1.x replication protocol. Therefore, to use replication with Couchbase Lite 2.x, the target Sync Gateway instance must also be upgraded to 2.x.
Sync Gateway 2.x will continue to accept clients that connect through the 1.x protocol. It will automatically use the 1.x replication protocol when a Couchbase Lite 1.x client connects through "http://localhost:4984/db" and the 2.0 replication protocol when a Couchbase Lite 2.0 client connects through "ws://localhost:4984/db". This allows for a smoother transition to get all your user base onto a version of your application built with Couchbase Lite 2.x.
As the top-level entity in the API, new databases can be created using
the Database
class by passing in a name, configuration, or both. The
following example creates a database using the Database(String name, DatabaseConfiguration config)
method.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
Just as before, the database will be created in a default location.
Alternatively, the Database(string name, DatabaseConfiguration config)
initializer can be used to provide specific options in the
DatabaseConfiguration
object such as the database directory.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
When the application is running on the Android emulator, you can locate the application’s data folder and access the database file by using the adb CLI tools. For example, to list the different databases on the emulator, you can run the following commands.
$ adb shell
$ su
$ cd /data/data/{APPLICATION_ID}/files
$ ls
The adb pull command can be used to pull a specific database to your host machine.
$ adb root
$ adb pull /data/data/{APPLICATION_ID}/files/{DATABASE_NAME}.cblite2 .
The log messages are split into different domains (LogDomains
) which
can be tuned to different log levels. The following example enables
verbose
logging for the replicator
and query
domains.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
If your app needs to sync a lot of data initially, but that data is fairly static and won’t change much, it can be a lot more efficient to bundle a database in your application and install it on the first launch. Even if some of the content changes on the server after you create the app, the app’s first pull replication will bring the database up to date.
To use a prebuilt database, you need to set up the database, build the
database into your app bundle as a resource, and install the database
during the initial launch. After your app launches, it needs to check
whether the database exists. If the database does not exist, the app
should copy it from the app bundle using the
Database.copy(File path, String name, DatabaseConfiguration config)
method as shown below.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
In Couchbase Lite, a document’s body takes the form of a JSON object — a collection of key/value pairs where the values can be different types of data such as numbers, strings, arrays or even nested objects. Every document is identified by a document ID, which can be automatically generated (as a UUID) or specified programmatically; the only constraints are that it must be unique within the database, and it can’t be changed.
The following methods/initializers can be used:
-
The
MutableDocument()
initializer can be used to create a new document where the document ID is randomly generated by the database. -
The
MutableDocument(withID: String)
initializer can be used to create a new document with a specific ID. -
The
database.getDocument(String id)
method can be used to get a document. If it doesn’t exist in the database, it will returnnull
. This method can be used to check if a document with a given ID already exists in the database.
The following code example creates a document and persists it to the database.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
By default, when a document is read from the database it is immutable.
The document.toMutable()
method should be used to create an instance
of the document which can be updated.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
Changes to the document are persisted to the database when the
save
method is called.
The Document
class now offers a set of
property accessors
for various scalar types, including boolean, integers, floating-point
and strings. These accessors take care of converting to/from JSON
encoding, and make sure you get the type you’re expecting.
In addition, as a convenience we offer Date
accessors. Dates are a
common data type, but JSON doesn’t natively support them, so the
convention is to store them as strings in ISO-8601 format. The following
example sets the date on the createdAt
property and reads it back
using the document.getDate(String key)
accessor method.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
If the property doesn’t exist in the document it will return the default
value for that getter method (0 for getInt
, 0.0 for getFloat
etc.).
To check whether a given property exists in the document, you should use
the
Document.Contains(String key)
method.
If you’re making multiple changes to a database at once, it’s faster to group them together. The following example persists a few documents in batch.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
At the local level this operation is still transactional: no other
Database
instances, including ones managed by the replicator can make
changes during the execution of the block, and other instances will not
see partial changes. But Couchbase Mobile is a distributed system, and
due to the way replication works, there’s no guarantee that Sync Gateway
or other devices will receive your changes all at once.
We’ve renamed "attachments" to "blobs". The new behavior
should be clearer too: a Blob
is now a normal object that can appear
in a document as a property value. In other words, you just instantiate
a Blob
and set it as the value of a property, and then later you can
get the property value, which will be a Blob
object. The following
code example adds a blob to the document under the avatar
property.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The Blob
API lets you access the contents as in-memory data (a Data
object) or as a InputStream
. It also supports an optional type
property that by convention stores the MIME type of the contents.
In the example above, "image/jpeg" is the MIME type and "avatar" is the
key which references that Blob
. That key can be used to retrieve the
Blob
object at a later time.
When a document is synchronized, the Couchbase Lite replicator will add
an _attachments
dictionary to the document’s properties if it contains
a blob. A random access name will be generated for each Blob
which is
different to the "avatar" key that was used in the example above. On the
image below, the document now contains the _attachments
dictionary
when viewed in the Couchbase Server Admin Console.
A blob also has properties such as "digest"
(a SHA-1 digest of the
data), "length"
(the length in bytes), and optionally "content_type"
(the MIME type.) The data is not stored in the document, but in a
separate content-addressable store, indexed by the digest.
This Blob
can be retrieved on the Sync Gateway REST API at
localhost:4984/justdoit/user.david/blob_1.
Notice that the blob identifier in the URL path is "blob_1" (not
"avatar").
Database queries have changed significantly. Instead of the map/reduce views used in 1.x, they’re now based on expressions, of the form "return _ from documents where , ordered by _", with semantics based on Couchbase’s N1QL query language.
There are several parts to specifying a query:
-
SELECT: specifies the projection, which is the part of the document that is to be returned.
-
FROM: specifies the database to query the documents from.
-
JOIN: specifies the matching criteria in which to join multiple documents.
-
WHERE: specifies the query criteria that the result must satisfy.
-
GROUP BY: specifies the query criteria to group rows by.
-
ORDER BY: specifies the query criteria to sort the rows in the result.
With the SELECT statement, you can query and manipulate JSON data. With projections, you retrieve just the fields that you need and not the entire document.
A SelectResult represents a single return value of the query statement. You can specify a comma separated list of SelectResult
expressions in
the select statement of your query. For instance the following select
statement queries for the document _id
as well as the type
and
name
properties of all documents in the database. In the query result,
we print the _id
and name
properties of each row using the property
name getter method.
{
"_id": "hotel123",
"type": "hotel",
"name": "Apple Droid"
}
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The SelectResult.all()
method can be used to query all the properties
of a document. In this case, the document in the result is embedded in a
dictionary where the key is the database name. The following snippet
shows the same query using SelectResult.all()
and the result in JSON.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
[
{
"travel-sample": {
"callsign": "MILE-AIR",
"country": "United States",
"iata": "Q5",
"icao": "MLA",
"id": 10,
"name": "40-Mile Air",
"type": "airline"
}
},
{
"travel-sample": {
"callsign": "TXW",
"country": "United States",
"iata": "TQ",
"icao": "TXW",
"id": 10123,
"name": "Texas Wings",
"type": "airline"
}
}
]
Similar to SQL, you can use the where clause to filter the documents to
be returned as part of the query. The select statement takes in an
Expression
. You can chain any number of Expressions in order to
implement sophisticated filtering capabilities.
The comparison operators can be used in the WHERE statement to specify on which
property to match documents. In the example below, we use the equalTo
operator to query documents where the type
property equals "hotel".
{
"_id": "hotel123",
"type": "hotel",
"name": "Apple Droid"
}
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
Collection operators are useful to check if a given value is present in an array.
The following example uses the Function.arrayContains
to find
documents whose public_likes
array property contain a value equal to
"Armani Langworth".
{
"_id": "hotel123",
"name": "Apple Droid",
"public_likes": ["Armani Langworth", "Elfrieda Gutkowski", "Maureen Ruecker"]
}
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The IN
operator is useful when you need to explicitly list out the values to test against. The following example looks for documents whose first
, last
or username
property value equals "Armani".
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The
like
operator can be used for string matching. It is recommended to use the
like
operator for case insensitive matches and the regex
operator
(see below) for case sensitive matches.
In the example below, we are looking for documents of type landmark
where the name property exactly matches the string "Royal engineers
museum". Note that since like
does a case insensitive match, the
following query will return "landmark" type documents with name matching
"Royal Engineers Museum", "royal engineers museum", "ROYAL ENGINEERS
MUSEUM" and so on.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
We can use %
sign within a like
expression to do a wildcard match
against zero or more characters. Using wildcards allows you to have some
fuzziness in your search string.
In the example below, we are looking for documents of type
"landmark"
where the name property matches any string that begins with "eng"
followed by zero or more characters, the letter "e", followed by zero or
more characters. The following query will return "landmark" type
documents with name matching "Engineers", "engine", "english egg" ,
"England Eagle" and so on. Notice that the matches may span word
boundaries.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
We can use _
sign within a like expression to do a wildcard match
against a single character.
In the example below, we are looking for documents of type "landmark"
where the name
property matches any string that begins with "eng"
followed by exactly 4 wildcard characters and ending in the letter "r".
The following query will return "landmark" type
documents with the
name
matching "Engineer", "engineer" and so on.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The regex
expression can be used for case sensitive matches. Similar
to wildcard like
expressions, regex
expressions based pattern
matching allow you to have some fuzziness in your search string.
In the example below, we are looking for documents of type
"landmark"
where the name property matches any string (on word boundaries) that
begins with "eng" followed by exactly 4 wildcard characters and ending
in the letter "r". The following query will return "landmark" type
documents with name matching "Engine", "engine" and so on. Note that the
\b
specifies that the match must occur on word boundaries.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The JOIN clause enables you to create new input objects by combining two or more source objects.
The following example uses a JOIN clause to find the airline details
which have routes that start from RIX. This example JOINS the document
of type "route" with documents of type "airline" using the document ID
(_id
) on the "airline" document and airlineid
on the "route"
document.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
You can perform further processing on the data in your result set before the final projection is generated. The following example looks for the number of airports at an altitude of 300 ft or higher and groups the results by country and timezone.
{
"_id": "airport123",
"type": "airport",
"country": "United States",
"geo": { "alt": 456 },
"tz": "America/Anchorage"
}
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
There are 138 airports on the Europe/Paris timezone located in France and above 300 ft
There are 29 airports on the Europe/London timezone located in United Kingdom and above 300 ft
There are 50 airports on the America/Anchorage timezone located in United States and above 300 ft
There are 279 airports on the America/Chicago timezone located in United States and above 300 ft
There are 123 airports on the America/Denver timezone located in United States and above 300 ft
It is possible to sort the results of a query based on a given expression result. The example below returns documents of type equal to "hotel" sorted in ascending order by the value of the title property.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
Aberdyfi
Achiltibuie
Altrincham
Ambleside
Annan
Ardèche
Armagh
Avignon
Creating indexes can speed up the performance of queries. While indexes make queries faster, they also make writes slightly slower, and the Couchbase Lite database file slightly larger. As such, it is best to only create indexes when you need to optimize a specific case for better query performance.
The following example creates a new index for the type
and name
properties.
{
"_id": "hotel123",
"type": "hotel",
"name": "Apple Droid"
}
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
If there are multiple expressions, the first one will be the primary key, the second the secondary key, etc.
Note: Every index has to be updated whenever a document is updated, so too many indexes can hurt performance. Thus, good performance depends on designing and creating the right indexes to go along with your queries.
To run a full-text search (FTS) query, you must have created a full-text
index on the expression being matched. Unlike regular queries, the index
is not optional. The following example inserts documents and creates an
FTS index on the name
property.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
Multiple properties to index can be specified in the index creation method.
With the index created, an FTS query on the property that is being
indexed can be constructed and ran. The full-text search criteria is
defined as a FullTextExpression
. The left-hand side is the full-text
index to use and the right-hand side is the pattern to match.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
In the example above, the pattern to match is a word, the full-text
search query matches all documents that contain the word 'buy' in the
value of the doc.name
property.
Full-text search is supported in the following languages: danish, dutch, english, finnish, french, german, hungarian, italian, norwegian, portuguese, romanian, russian, spanish, swedish and turkish.
The pattern to match can also be in the following forms:
-
prefix queries: the query expression used to search for a term prefix is the prefix itself with a '*' character appended to it. For example:
"'lin*'" -- Query for all documents containing a term with the prefix "lin". This will match -- all documents that contain "linux", but also those that contain terms "linear", --"linker", "linguistic" and so on.
-
overriding the property name that is being indexed: Normally, a token or token prefix query is matched against the document property specified as the left-hand side of the
match
operator. This may be overridden by specifying a property name followed by a ":" character before a basic term query. There may be space between the ":" and the term to query for, but not between the property name and the ":" character. For example:'title:linux problems' -- Query the database for documents for which the term "linux" appears in -- the document title, and the term "problems" appears in either the title -- or body of the document.
-
phrase queries: a phrase query is a query that retrieves all documents that contain a nominated set of terms or term prefixes in a specified order with no intervening tokens. Phrase queries are specified by enclosing a space separated sequence of terms or term prefixes in double quotes ("). For example:
"'"linux applications"'" -- Query for all documents that contain the phrase "linux applications".
-
NEAR queries: A NEAR query is a query that returns documents that contain a two or more nominated terms or phrases within a specified proximity of each other (by default with 10 or less intervening terms). A NEAR query is specified by putting the keyword "NEAR" between two phrase, token or token prefix queries. To specify a proximity other than the default, an operator of the form "NEAR/" may be used, where is the maximum number of intervening terms allowed. For example:
"'database NEAR/2 "replication"'" -- Search for a document that contains the phrase "replication" and the term -- "database" with not more than 2 terms separating the two.
-
AND, OR & NOT query operators: The enhanced query syntax supports the AND, OR and NOT binary set operators. Each of the two operands to an operator may be a basic FTS query, or the result of another AND, OR or NOT set operation. Operators must be entered using capital letters. Otherwise, they are interpreted as basic term queries instead of set operators. For example:
'couchbase AND database' -- Return the set of documents that contain the term "couchbase", and the -- term "database". This query will return the document with docid 3 only.
When using the enhanced query syntax, parenthesis may be used to specify the precedence of the various operators. For example:
'("couchbase database" OR "sqlite library") AND linux' -- Query for the set of documents that contains the term "linux", and at least -- one of the phrases "couchbase database" and "sqlite library".
It’s very common to sort full-text results in descending order of
relevance. This can be a very difficult heuristic to define, but
Couchbase Lite comes with a ranking function you can use.
In the OrderBy
array, use a string of the form Rank(X)
, where X
is
the property or expression being searched, to represent the ranking of
the result.
Couchbase Mobile 2.0 uses a new replication protocol based on WebSockets.
To use this protocol with Couchbase Lite 2.0, the replication URL should specify WebSockets as the URL scheme (see the "Starting a Replication" section below). Mobile clients using Couchbase Lite 1.x can continue to use http as the URL scheme. Sync Gateway 2.0 will automatically use the 1.x replication protocol when a Couchbase Lite 1.x client connects through "http://localhost:4984/db" and the 2.0 replication protocol when a Couchbase Lite 2.0 client connects through "ws://localhost:4984/db".
Download Sync Gateway and start it from the command line with the configuration file created above.
~/Downloads/couchbase-sync-gateway/bin/sync_gateway
For platform specific installation instructions, refer to the Sync Gateway installation guide.
Replication can be bidirectional, this means you can start a
push
/pull
replication with a single instance. The replication’s
parameters can be specified through the
ReplicatorConfiguration
object; for example, if you wish to start a push
only or pull
only
replication.
The following example creates a pull
replication with Sync Gateway.
class MyClass {
Database database;
Replicator replicator; // (1)
void startReplication() {
URI uri = null;
try {
uri = new URI("ws://10.0.2.2:4984/db"); // (2)
} catch (URISyntaxException e) {
e.printStackTrace();
}
Endpoint endpoint = new URLEndpoint(uri);
ReplicatorConfiguration config = new ReplicatorConfiguration(database, endpoint);
config.setReplicatorType(ReplicatorConfiguration.ReplicatorType.PULL);
this.replicator = new Replicator(config);
this.replicator.start();
}
}
-
A replication is an asynchronous operation. To keep a reference to the
replicator
object, you can set it as an instance property. -
The URL scheme for remote database URLs has changed in Couchbase Lite 2.0. You should now use
ws:
, orwss:
for SSL/TLS connections. In this example the hostname is10.0.2.2
because the Android emulator runs in a VM that is generally accessible on10.0.2.2
from the host machine (see Android Emulator networking documentation).
Couchbase Lite 2.0 uses WebSockets as the communication protocol to transmit data. Some load balancers are not configured for WebSocket connections by default (NGINX for example); so it might be necessary to explicitly enable them in the load balancer’s configuration (see Load Balancers).
By default, the WebSocket protocol uses compression to optimize for
speed and bandwidth utilization. The level of compression is set on Sync Gateway and
can be tuned in the configuration file
(replicator_compression
).
As always, when there is a problem with replication, logging is your friend. The following example increases the log output for activity related to replication with Sync Gateway.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The replication.Status.Activity
property can be used to check the
status of a replication. For example, when the replication is actively
transferring data and when it has stopped.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
The following table lists the different activity levels in the API and the meaning of each one.
State | Meaning |
---|---|
|
The replication is finished or hit a fatal error. |
|
The replicator is offline as the remote host is unreachable. |
|
The replicator is connecting to the remote host. |
|
The replication caught up with all the changes available from
the server. The |
|
The replication is actively transferring data. |
If an error occurs, the replication status will be updated with an
Error
which follows the standard HTTP error codes. The following
example monitors the replication for errors and logs the error code to
the console.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
When a permanent error occurs (i.e 404
: not found, 401
:
unauthorized), the replicator (continuous or one-shot) will stop
permanently. If the error is temporary (i.e waiting for the network to
recover), a continuous replication will retry to connect indefinitely
and if the replication is one-shot it will retry for a limited number of
times. The following error codes are considered temporary by the
Couchbase Lite replicator and thus will trigger a connection retry.
-
408
: Request Timeout -
429
: Too Many Requests -
500
: Internal Server Error -
502
: Bad Gateway -
503
: Service Unavailable -
504
: Gateway Timeout -
1001
: DNS resolution error
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
In Couchbase Lite 2.0, document conflicts are automatically resolved. This
functionality aims to simplify the default behavior of conflict handling
and save disk space (conflicting revisions will no longer be stored in
the database). There are 2 different save
method signatures to specify
how to handle a possible conflict:
-
save(document: MutableDocument)
: when concurrent writes to an individual record occur, the conflict is automatically resolved and only one non-conflicting document update is stored in the database. The Last-Write-Win (LWW) algorithm is used to pick the winning revision. -
save(document: MutableDocument, concurrencyControl: ConcurrencyControl)
: attempts to save the document with a concurrency control. The concurrency control parameter has two possible values:-
lastWriteWins
: The last operation wins if there is a conflict. -
failOnConflict
: The operation will fail if there is a conflict.
-
Similarly to the save operation, the delete operation also has two method signatures to specify how to handle a possible conflict:
-
delete(document: Document)
: The last write will win if there is a conflict. -
delete(document: Document, concurrencyControl: ConcurrencyControl)
: attemps to delete the document with a concurrency control. The concurrency control parameter has two possible values:-
lastWriteWins
: The last operation wins if there is a conflict. -
failOnConflict
: The operation will fail if there is a conflict.
-
Database replicas is available in the Enterprise Edition only (https://www.couchbase.com/downloads). Starting in Couchbase Lite 2.0, replication between two local databases is now supported. It allows a Couchbase Lite replicator to store data on secondary storage. It would be especially useful in scenarios where a user’s device is damaged and the data needs to be moved to a different device. Note that the code below won’t compile if you’re running the Community Edition of Couchbase Lite.
Couchbase Lite supports certificate pinning. Certificate pinning is a technique that can be used by applications to "pin" a host to it’s certificate. The certificate is typically delivered to the client by an out-of-band channel and bundled with the client. In this case, Couchbase Lite uses this embedded certificate to verify the trustworthiness of the server and no longer needs to rely on a trusted third party for that (commonly referred to as the Certificate Authority).
The openssl
command can be used to create a new self-signed
certificate and convert the .pem
file to a .cert
file (see
creating
your own self-signed certificate). You should then have 3 files:
cert.pem
, cert.cer
and key.pem
.
The cert.pem
and key.pem
can be used in the Sync Gateway
configuration (see
installing
the certificate).
On the Couchbase Lite side, the replication must be configured with the
cert.cer
file.
link:{examplesdir}/java/code-snippets/app/src/main/java/com/couchbase/code_snippets/MainActivity.java[role=include]
This example loads the certificate from the application sandbox, then converts it to the appropriate type to configure the replication object.
The Couchbase Lite API is thread safe except for calls to mutable objects:
MutableDocument
, MutableDictionary
and MutableArray
.
-
Support for Log redaction of sensitive information when logging is enabled.
Enhancements
Bugs
-
#1217 2.0: Todo Sample bug Fix and implement remaining features
-
#1234 2.0: Replicator continuous pull status completed and total number out of sync
-
#1247 2.0: Push Replication Causing Errors
-
#1273 2.0: Replicator Activity Level stays in Busy state
-
#1347 2.0: How do we properly stop puller Replicator and delete database ?
-
#1470 2.0: In My App with CB Lite DB020(Android), ConflictResolver is called endless loop during three device or much more!
-
#1499 2.0: Repl Bad URL returns 19 instead of 15 on API 24 ARM emulator
-
#1500 2.0: LoadTest.testUpdate() causes memory error with Android API 19 Arm Emulator
-
#1501 2.0: ReplicatorTest > testPushDoc fails
-
#1512 2.0: ReplicatorTest > testPullDoc fails
-
#1581 2.0 : LiveQuery threading issue
-
#1609 2.0: testSelfSignedSSLPinned() unit test failure
-
#1610 Exception from the cpp layer in my android app on load tests
-
#1615 2.0: NullPointerException: Attempt to invoke virtual method 'boolean com.couchbase.litecore.C4QueryEnumerator.next()' on a null object reference
-
#1620 NOT operator not working for FTS
-
#1630 2.0: make public Index interface
-
#1651 2.0: C4DocumentTest.testPut() fails
-
#1652 App crash with deleteDocument with concurrencyControl
-
#1693 DB023 - Crazy amount of dbListenerTokens - makes the DB run slow
Known Issues
-
#1685 Replicator in Android get stuck at busy state when it goes back to online from offline (Genymotion)
-
#1702 ValueIndexItem.expression(Expression) is implemented with CBL Android 2.0.0 release. This API will be available with 2.1.0 release
-
#1665: it is currently not possible to enable code shrinking (
minifyEnabled: true
) in an Android Studio project that uses Couchbase Lite 2.0. As a workaround, code shrinking can be disabled for Couchbase Lite classes and its dependencies by adding the following in proguard-rules.pro.# OkHttp3 -dontwarn okhttp3.** -dontwarn okio.** -dontwarn javax.annotation.** -dontwarn org.conscrypt.** # A resource is loaded with a relative path so the package of this class must be preserved. -keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase # CBL2.x -keep class com.couchbase.litecore.**{ *; } -keep class com.couchbase.lite.**{ *; }