A newer version of this documentation is available.

View Latest

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.

      Development-type Scenarios
      • 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

      1. Create a new project folder and add a build.gradle file containing the following:

      2. 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.

      3. 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, where db is the name of your Sync Gateway database
      4. 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();
              }
            }
      5. 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
      6. Create an index.html file in src/main/web app with the following content:

      7. Create a showDbItems.jsp file in src/main/web app with the following content:

      8. Build, deploy and run the app using tomcatRun

        GradleMenuWebApp
        1. Point your browser to: localhost:8080/gettingstarted

          This opens the browser at your index.html page.

        2. 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.

      The GettingStarted app will:

      • 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

        cblOutput
      Before starting your app ensure you have started both your Couchbase Server and Sync Gateway instances.