Build and Run
Description — Build and run a starter app to validate your install of Couchbase Lite on Java
Abstract — This content provides sample code and instructions that enable you to test your Couchbase Lite for java installation.
Related Content — Install | Prerequisites | Build and Run |
Build a Getting Started App
This section explains how to validate your configured build environment by building a starter app that uses many of Couchbase Lite on Java’s more common features.
The GettingStarted app demonstrates how to use Couchbase Lite on Java. Console and Web App versions are available.
-
Console App
-
Web App
-
About the Starter App
Ensure you added the Couchbase Lite dependency to your build.gradle file
|
Create, build and run a new project using the following GettingStarted.java
code:
CouchbaseLite.init();
(1)
// Create a database
System.out.println("Starting DB");
DatabaseConfiguration cfg = new DatabaseConfiguration();
Database database = null;
try {
database = new Database( "mydb", cfg);
} catch (CouchbaseLiteException e) {
e.printStackTrace();
}
(2)
// Create a new document (i.e. a record) in the database.
MutableDocument mutableDoc =
new MutableDocument().setString("version", "2.0")
.setString("type", "SDK");
(3)
// Save it to the database.
try {
database.save(mutableDoc);
} catch (CouchbaseLiteException e) {
e.printStackTrace();
}
(4)
// Retrieve and update a document.
mutableDoc =
database.getDocument(mutableDoc.getId())
.toMutable()
.setString("language", "Kotlin");
try {
database.save(mutableDoc);
} catch (CouchbaseLiteException e) {
e.printStackTrace();
}
(5)
// Retrieve immutable document and log the document ID
// generated by the database and some document properties
Document document = database.getDocument(mutableDoc.getId());
System.out.println( String.format("Document ID :: %s", document.getId()));
System.out.println( String.format("Learning :: %s:", document.getString("language")));
(6)
// Create a query to fetch documents of type SDK.
Query listQuery = QueryBuilder.select(SelectResult.all())
.from(DataSource.database(database))
.where(Expression.property("type").equalTo(Expression.string("SDK")));
try {
for (Result result : listQuery.execute().allResults()) {
for ( String k : result.getDictionary(0).getKeys()) {
System.out.println( k + " = " + result.getDictionary(0).getString(k));
}
// String.format("Number of rows :: %n",
// rs.size()));
}
} catch (CouchbaseLiteException e) {
e.printStackTrace();
}
// (7)
// OPTIONAL -- if you have Sync Gateway Installed you can try replication too
// Create a replicator to push and pull changes to and from the cloud.
// Be sure to hold a reference somewhere to prevent the Replicator from being GCed
// BasicAuthenticator basAuth = new BasicAuthenticator("sync-gateway", "password".toCharArray());
//ReplicatorConfiguration replConfig =
// new ReplicatorConfiguration(database,
// URLEndpoint( URI("ws://localhost:4984/getting-started-db")),
// ReplicatorType.PUSH_AND_PULL,
// basAuth);
//
//Replicator replicator = new Replicator(replConfig);
// Listen to replicator change events.
// Version using Kotlin Flows to follow shortly ...
//replicator.addChangeListener(new ReplicatorChangeListener() {
// @Override
// public void changed(@NonNull ReplicatorChange change) {
// if (change.getStatus().getError() != null) {
// System.out.println( "Error code :: ${err.code}");
// }
// }
// });
// Start replication.
// replicator.start();
}
}
1 | Create a database |
2 | Create a mutable document |
3 | Save document to database |
4 | Retrieve the document as mutable and change the language to Java and save it |
5 | Retrieve document as immutable and log it ID |
6 | Query the database output count and id to log |
7 | Optionally, initiate a replication |
On running the app, you should see the document ID and property printed to the console together with a query result showing the number of rows in the database.
This shows the document was successfully persisted to the database.
See [About the Getting Started App] for more on the app itself
This section explains how to set-up a build project to create Couchbase Lite on Java web apps using gradle and Intellij IDEA.
Steps
-
Create a new project folder and add a
build.gradle
file containing the following: -
Within Intellij IDEA, open the new project folder
If you don’t have auto-import enabled, then accept the Import from Gradle prompt that appears at the bottom right of the screen.
-
Create a Java class GettingStarted using this code:
//@WebServlet( value = "/GettingStarted") //public class GettingStartedWebApp extends javax.servlet.http.HttpServlet { public class GettingStartedWebApp { private static final String DB_DIR = "/usr/local/var/tomcat/data"; (1) private static final String DB_NAME = "getting-started"; /* Credentials declared this way purely for expediency in this demo - use OAUTH in production code */ private static final String DB_USER = "sync_gateway"; private static final String DB_PASS = "password"; // private static final String SYNC_GATEWAY_URL = "ws://127.0.0.1:4984/db" + DB_NAME; private static final String SYNC_GATEWAY_URL = "ws://127.0.0.1:4984/getting-started"; (2) private static final String NEWLINETAG = "<br />"; private String MYRESULTS; private int NUMROWS; private Random RANDOM = new Random(); protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { outputMessage("Servlet started :: doGet Invoked"); doPost(request, response); } protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { NUMROWS = 0; MYRESULTS = ""; outputMessage("Servlet started :: doPost Invoked"); String url = "/showDbItems.jsp"; try { MYRESULTS = testCouchbaseLite(); } catch (CouchbaseLiteException | URISyntaxException | InterruptedException e) { e.printStackTrace(); } finally { outputMessage(String.format("CouchbaseLite Test Ended :: There are %d rows in DB", NUMROWS)); } request.setAttribute("myRowCount", NUMROWS); request.setAttribute("myResults", MYRESULTS); getServletContext() .getRequestDispatcher(url) .forward(request, response); outputMessage("Servlet Ended :: doPost Exits"); } public String testCouchbaseLite() throws CouchbaseLiteException, URISyntaxException, InterruptedException, ServletException { int randPtr = RANDOM.nextInt(5) + 1; long syncTotal = 0; Double randVn = RANDOM.nextDouble() + 1; List<String> listLangs = new ArrayList<String>(Arrays.asList("Java", "Swift", "C#.Net", "Objective-C", "C++", "Cobol")); List<String> listTypes = new ArrayList<String>(Arrays.asList("SDK", "API", "Framework", "Methodology", "Language", "IDE")); String Prop_Id = "id"; String Prop_Language = "language"; String Prop_Type = "type"; String Prop_Version = "version"; String searchStringType = "SDK"; // Get and configure database // Note initialisation of CouchbaseLite is done in ServletContextListener outputMessage("== Opening DB and doing initial sync"); Database database = DatabaseManager.manager().getDatabase(DB_NAME,DB_DIR,DB_PASS); // Initial DB sync prior to local updates syncTotal = DatabaseManager.manager().runOneShotReplication(database, SYNC_GATEWAY_URL, DB_USER, DB_PASS); outputMessage(String.format("Inital number of rows synchronised = %d", syncTotal)); // Create a new document (i.e. a record) in the database. outputMessage("== Adding a record"); MutableDocument mutableDoc = new MutableDocument() .setDouble(Prop_Version, randVn) .setString(Prop_Type, listTypes.get(RANDOM.nextInt(listTypes.size() - 1))); // Save it to the database. try { database.save(mutableDoc); } catch (CouchbaseLiteException e) { throw new ServletException("Error saving a document", e); } // Update a document. outputMessage("== Updating added record"); mutableDoc = database.getDocument(mutableDoc.getId()).toMutable(); mutableDoc.setString(Prop_Language, listLangs.get(RANDOM.nextInt(listLangs.size() - 1))); // Save it to the database. try { database.save(mutableDoc); } catch (CouchbaseLiteException e) { throw new ServletException("Error saving a document", e); } outputMessage("== Retrieving record by id"); Document newDoc = database.getDocument(mutableDoc.getId()); // Show the document ID (generated by the database) and properties outputMessage("Document ID :: " + newDoc.getId()); outputMessage("Learning " + newDoc.getString(Prop_Language)); // Create a query to fetch documents of type SDK. outputMessage("== Executing Query 1"); Query query = QueryBuilder.select(SelectResult.all()) .from(DataSource.database(database)) .where(Expression.property(Prop_Type).equalTo(Expression.string(searchStringType))); try{ ResultSet result = query.execute(); outputMessage(String.format("Query returned %d rows of type %s", result.allResults().size(), searchStringType)); } catch (CouchbaseLiteException e) { e.printStackTrace(); } // Create a query to fetch all documents. outputMessage("== Executing Query 2"); Query queryAll = QueryBuilder.select(SelectResult.expression(Meta.id), SelectResult.property(Prop_Language), SelectResult.property(Prop_Version), SelectResult.property(Prop_Type)) .from(DataSource.database(database)); try { for (Result thisDoc : queryAll.execute()) { NUMROWS++; outputMessage(String.format("%d ... Id: %s is learning: %s version: %.2f type is %s", NUMROWS, thisDoc.getString(Prop_Id), thisDoc.getString(Prop_Language), thisDoc.getDouble(Prop_Version), thisDoc.getString(Prop_Type))); } } catch (CouchbaseLiteException e) { e.printStackTrace(); } outputMessage(String.format("Total rows returned by query = %d", NUMROWS)); // Do final single-shot replication to incorporate changed NumRows outputMessage("== Doing final single-shot sync"); syncTotal = DatabaseManager.manager().runOneShotReplication(database, SYNC_GATEWAY_URL, DB_USER, DB_PASS); outputMessage(String.format("Total rows synchronised = %d", syncTotal)); database.close(); return MYRESULTS; } public void outputMessage(String msg) { String thisMsg = "Null message"; if (msg.length() > 0) { thisMsg = msg; } System.out.println(msg); MYRESULTS = MYRESULTS + msg + NEWLINETAG; } }
1 It is advisable to set a specific directory path for the database. 2 The app will start a replicator pointing to ws://localhost:4984/db
, wheredb
is the name of your Sync Gateway database -
Create a Java class Listener using this code:
// import javax.servlet.ServletContextEvent; // import javax.servlet.ServletContextListener; // import javax.servlet.annotation.WebListener; // // @WebListener // public class Application implements ServletContextListener { public class GsWebApp_Listener { @Override public void contextInitialized(ServletContextEvent event) { DatabaseManager.manager().init(); } }
-
Create a Java class Database Manager using this code:
//import com.couchbase.lite.*; //import java.net.URI; //import java.net.URISyntaxException; public class DatabaseManager { private static DatabaseManager instance; private Database database; public static synchronized DatabaseManager manager() { if (instance == null) { instance = new DatabaseManager(); } return instance; } public synchronized void init() { CouchbaseLite.init(); (1) } public synchronized Database getDatabase(String parDbname, String parDbDir, String parDbPass) { if (database == null) { try { DatabaseConfiguration config = new DatabaseConfiguration(); config.setDirectory(parDbDir); (2) config.setEncryptionKey(new EncryptionKey(parDb_PASS)); (3) database = new Database(parDbname, config); } catch (CouchbaseLiteException e) { throw new IllegalStateException("Cannot create database", e); } } return database; } public synchronized long runOneShotReplication( Database parDb, String parURL, String parName, String parPassword) throws InterruptedException { long syncTotal = 0; // Set replicator endpoint URI sgURI = null; try { sgURI = new URI(parURL); } catch (URISyntaxException e) { e.printStackTrace(); } URLEndpoint targetEndpoint = new URLEndpoint(sgURI); // Configure replication System.out.println("== Synchronising DB :: Configuring replicator"); ReplicatorConfiguration replConfig = new ReplicatorConfiguration(parDb, targetEndpoint); replConfig.setReplicatorType(ReplicatorConfiguration.ReplicatorType.PUSH_AND_PULL); replConfig.setContinuous(false); // make this a single-shot replication cf. a continuous replication // Add authentication. // outputMessage("== Synchronising DB :: Setting authenticator"); replConfig.setAuthenticator(new BasicAuthenticator(parName, parPassword)); // Create replicator (be sure to hold a reference somewhere that will prevent the Replicator from being GCed) // outputMessage("== Synchronising DB :: Creating replicator"); Replicator replicator = new Replicator(replConfig); // Listen to replicator change events. // System.out.println("== Synchronising DB :: Adding listener"); replicator.addChangeListener(change -> { if (change.getStatus().getError() != null) { System.err.println("Error code :: " + change.getStatus().getError().getCode()); } }); // Start replication. // outputMessage("== Synchronising DB :: Starting"); replicator.start(); // Check status of replication and wait till it is completed while ((replicator.getStatus().getActivityLevel() != Replicator.ActivityLevel.STOPPED) && (replicator.getStatus().getActivityLevel() != Replicator.ActivityLevel.IDLE)) { Thread.sleep(1000); } syncTotal = replicator.getStatus().getProgress().getTotal(); replicator.stop(); // outputMessage("== Synchronising DB :: Completed "); return replicator.getStatus().getProgress().getTotal(); } }
1 This is the only API that differs from the Java (android) version. It accepts no parameters and should be called once only 2 It is advisable to set a specific directory path for the database. 3 You can optionally AES-256 encrypt the database by providing a key -
Create an
index.html
file insrc/main/web app
with the following content: -
Create a
showDbItems.jsp
file insrc/main/web app
with the following content: -
Build, deploy and run the app using
tomcatRun
-
Point your browser to:
localhost:8080/gettingstarted
This opens the browser at your index.html page.
-
Select the here link
This launches the servlet and displays the results in
showdDbItems.jsp
. They are also added to the catalina.out log file.
-
-
Create a database
The app creates its database in the
/getting-started.cblite2
directory relative to its root location when run (See: Finding a Database File).
Explicitly state your required database location when creating your database (see: Finding a Database File for how to do this) |
-
Add content to the DB
-
Run a simple query counting the DB rows
-
Start a one-shot, bi-directional replication using Sync Gateway and Couchbase Server
-
Produce a simple report on the db Contents
Before starting your app ensure you have started both your Couchbase Server and Sync Gateway instances. |