Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Docker and Vaadin Meet Couchbase: Part I

DZone's Guide to

Docker and Vaadin Meet Couchbase: Part I

Learn how you can fire up a web application using Spring Boot, Vaadin, and of course Couchbase (as backend) — all using Docker.

· Database Zone ·
Free Resource

New whitepaper: Database DevOps – 6 Tips for Achieving Continuous Delivery. Discover 6 tips for continuous delivery with Database DevOps in this new whitepaper from Redgate. In 9 pages, it covers version control for databases and configurations, branching and testing, automation, using NuGet packages, and advice for how to start a pioneering Database DevOps project. Also includes further research on the industry-wide state of Database DevOps, how application and database development compare, plus practical steps for bringing DevOps to your database. Read it now free.

Running Couchbase as a Docker container is fairly easy. Simply inherit from the latest, official Couchbase image and add your customized behavior according to your requirement. In this post, I am going to show how you can fire up a web application using Spring Boot, Vaadin, and of course Couchbase (as backend) — all using Docker.

This is part one of a two-part series where I am going to describe ways to run a fully featured web application powered by Couchbase as the NoSQL backend using Docker toolsets. In this post, I will describe the steps to set up and configure a Couchbase environment using Docker; I will also mention ways to Dockerize the web application (in this case, it’s a Spring Boot application with Vaadin) and talk to the Couchbase backend for the CRUD operations.

Prerequisites

Docker needs to be set up and working. Please refer to this link for details of the installation. If you are on macOS or Windows 10, you can go for native Docker packages. If you are on an earlier version of Windows (7 or 8) like me, then you can use Docker Toolbox which comes with Docker machine.

The Application

Ours is a simple CRUD application for maintaining a bookstore. Users of the application can add books by entering information such as title and/or author, and can then view the list of books, edit some information, and even delete the books. The app is built on Spring Boot. The backend is powered by Couchbase 4.6, and for the front-end, I have used Vaadin 7 since it has pretty neat integration with the Spring Boot framework.

The main steps to build this app are listed below:

  • Run and configure Couchbase 4.6, including setting up the bucket and services using Docker.
  • Build the application using Spring Boot, Vaadin, and Couchbase.
  • Dockerize and run the application.

Run Couchbase 4.6 Using Docker

Check your Docker host IP. You can use:

docker-machine ip default to find out the docker_host ip address. You can also check the environment variables by doing  

printenv | grep -i docker_host; it would show something like this ->

DOCKER_HOST=tcp://192.168.99.100:2376

The next task is to write the Dockerfile to run and configure Couchbase. For our application to talk to the Couchbase backend, we need to set up a bucket named “books” and also enable the index query services on the Couchbase node. The Dockerfile to all of this can be found here.

The Dockerfile uses a configuration script to set up the Couchbase node. Couchbase offers REST endpoints that can easily enable services such as querying, N1QL, and index. One can also set up buckets using these REST APIs. The configuration script can be downloaded from here.

Let’s try to build and run the Couchbase image now.

Go to the directory where the Dockerfile is.

Build the image ->

docker build -t <chakrar27>/couchbase:books .

Replace chakrar27 by your image-prefix or docker hub id.

Once the image is built, verify by doing

$ docker images

Image title

Run the image by typing:

docker run -p 8091-8093:8091-8093 -p 8094:8094 -p 11210:11210 chakrar27/couchbase:books

Sample output:

Starting Couchbase Server -- Web UI available at http://<ip>:8091 and logs available in /opt/couchbase/var/lib/couchbase/logs

Start configuring env by calling REST endpoints

Note: Unnecessary use of -X or --request, POST is already inferred.

*   Trying 192.168.99.100...

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0)

> POST /pools/default HTTP/1.1

> Host: 127.0.0.1:8091

> User-Agent: curl/7.49.1-DEV

> Accept: */*

> Content-Length: 55

> Content-Type: application/x-www-form-urlencoded

>

} [55 bytes data]

* upload completely sent off: 55 out of 55 bytes

< HTTP/1.1 200 OK

< Server: Couchbase Server

< Pragma: no-cache

< Date: Fri, 24 Mar 2017 03:20:51 GMT

< Content-Length: 0

< Cache-Control: no-cache

<

100    55    0     0  100    55      0   2966 --:--:-- --:--:-- --:--:--  3666

* Connection #0 to host 127.0.0.1 left intact

*   Trying 127.0.0.1...

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0)

> POST /node/controller/setupServices HTTP/1.1

> Host: 127.0.0.1:8091

> User-Agent: curl/7.49.1-DEV

> Accept: */*

> Content-Length: 32

> Content-Type: application/x-www-form-urlencoded

>

} [32 bytes data]

* upload completely sent off: 32 out of 32 bytes

< HTTP/1.1 200 OK

< Server: Couchbase Server

< Pragma: no-cache

< Date: Fri, 24 Mar 2017 03:20:56 GMT

< Content-Length: 0

< Cache-Control: no-cache

<

100    32    0     0  100    32      0   3389 --:--:-- --:--:-- --:--:--  4000

* Connection #0 to host 127.0.0.1 left intact

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100   180  100   152  100    28   8068   1486 --:--:-- --:--:-- --:--:--  8444

HTTP/1.1 200 OK

Server: Couchbase Server

Pragma: no-cache

Date: Fri, 24 Mar 2017 03:21:01 GMT

Content-Type: application/json

Content-Length: 152

Cache-Control: no-cache

{"storageMode":"memory_optimized","indexerThreads":0,"memorySnapshotInterval":200,"stableSnapshotInterval":5000,"maxRollbackPoints":5,"logLevel":"info"}Note: Unnecessary use of -X or --request, POST is already inferred.

*   Trying 127.0.0.1...

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0)

> POST /settings/web HTTP/1.1

> Host: 127.0.0.1:8091

> User-Agent: curl/7.49.1-DEV

> Accept: */*

> Content-Length: 50

> Content-Type: application/x-www-form-urlencoded

>

} [50 bytes data]

* upload completely sent off: 50 out of 50 bytes

< HTTP/1.1 200 OK

< Server: Couchbase Server

< Pragma: no-cache

< Date: Fri, 24 Mar 2017 03:21:01 GMT

< Content-Type: application/json

< Content-Length: 44

< Cache-Control: no-cache

<

{ [44 bytes data]

100    94  100    44  100    50   1554   1765 --:--:-- --:--:-- --:--:--  2380

* Connection #0 to host 127.0.0.1 left intact

{"newBaseUri":"http://127.0.0.1:8091/"}bucket set up start

bucket name =  books

Note: Unnecessary use of -X or --request, POST is already inferred.

*   Trying 127.0.0.1...

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0)

* Server auth using Basic with user 'Administrator'

> POST /pools/default/buckets HTTP/1.1

> Host: 127.0.0.1:8091

> Authorization: Basic QWRtaW5pc3RyYXRvcjpwYXNzd29yZA==

> User-Agent: curl/7.49.1-DEV

> Accept: */*

> Content-Length: 55

> Content-Type: application/x-www-form-urlencoded

>

} [55 bytes data]

* upload completely sent off: 55 out of 55 bytes

< HTTP/1.1 202 Accepted

< Server: Couchbase Server

< Pragma: no-cache

< Location: /pools/default/buckets/books

< Date: Fri, 24 Mar 2017 03:21:01 GMT

< Content-Length: 0

< Cache-Control: no-cache

<

100    55    0     0  100    55      0    748 --:--:-- --:--:-- --:--:--   820

* Connection #0 to host 127.0.0.1 left intact

bucket set up done

/entrypoint.sh couchbase-server

Verify the configuration by typing http://192.168.99.100:8091 into your favorite browser.

Type Administrator as Username and password in the Password field and click Sign In.

Check the settings of the Couchbase node and verify that it is according to the configure.sh we used above.

The bucket books.

At this point, our back-end Couchbase infrastructure is up and running. We now need to build an application that can use this backend to build something functional.

Build the Application Using Spring Boot, Vaadin, and Couchbase

Go to start.spring.io and add Couchbase as a dependency. This would place spring-data-couchbase libraries in the application classpath. Since Couchbase is considered a first-class citizen of the Spring Boot ecosystem, we can make use of the Spring Boot auto-configuration feature to access the Couchbase bucket at runtime.

Also, add Vaadin as a dependency in the project. We are going to use it for building the UI layer.

The project object model (POM) file can be found here.

We create a Couchbase repository like this:

@ViewIndexed(designDoc = "book")

@N1qlPrimaryIndexed

@N1qlSecondaryIndexed(indexName = "bookSecondaryIndex")

public interface BookStoreRepository extends CouchbasePagingAndSortingRepository<Book, Long> {

        List<Book> findAll();        

        List<Book> findByAuthor(String author);

        List<Book> findByTitleStartsWithIgnoreCase(String title);

        List<Book> findByCategory(String category);

}

The annotations ensure that a View named “book” will be supplied at runtime to support view-based queries. A primary index will be created to support N1QL queries. In addition, a secondary index will also be provided.

The methods have been defined to return List<Book>. We don’t have to provide any implementation since that is already provided behind the scenes by the spring-data-couchbase.

We need to define the entity, which in our case is Book. We annotate it with @Document.

@Document:

public class Book {

        @Id

        private String id = UUID.randomUUID().toString();

        private String title;

        private String author;

        private String isbn;

        private String category;

}

To enable autoconfiguration, use application.properties or an application.yml file as shown below:

spring.couchbase.bootstrap-hosts=127.0.0.1

spring.couchbase.bucket.name=books

spring.couchbase.bucket.password=

spring.data.couchbase.auto-index=true

One thing to note here is that when the application container runs, it would need to connect to the Couchbase container and set up the auto-configuration. The property spring.couchbase.bootstrap-hosts lists the IP address of the Couchbase node. Here, I have specified 127.0.0.1 which is not going to work since, at runtime, the app container will not find the Couchbase container running in that IP. So we need to pass an environment variable (env variable) when running the Docker image of the application.

In order to pass an env variable as mentioned above, we need to write the Dockerfile of the application such that the value of the spring.couchbase.bootstrap-hosts property can be passed as an env variable. Here’s the Dockerfile of the app:

FROM frolvlad/alpine-oraclejdk8:full

VOLUME /tmp

ADD target/bookstore-1.0.0-SNAPSHOT.jar app.jar

RUN sh -c 'touch /app.jar'

CMD java -Dspring.couchbase.bootstrap-hosts=$HOSTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar

As you can see, we are basically overriding the value of the spring.couchbase.bootstrap-hosts property defined in the application.properties file by the env variable HOSTS.

This is pretty much all we have to do to wire Spring Boot with Couchbase.

UI (U and I)

For UI, we make use of the spring-vaadin integration. I am using version 7.7.3 of Vaadin, vaadin-spring version 1.1.0, and “Viritin,” a useful Vaadin add-on. To install Viritin, add the following dependency:

<dependency>

        <groupId>org.vaadin</groupId>

        <artifactId>viritin</artifactId>

        <version>1.57</version>

</dependency>

Annotate the UI class as

@SpringUI

@Theme(“valo”)

public class BookstoreUI extends UI {

//////

}

And then hook the repository methods with the UI elements.

A bean that implements the CommandLineRunner interface is used to prepopulate the database with some initial values.

For full source code, refer to this link.

Dockerize the Application

Using Maven, it’s very easy to Dockerize an application using Spotify’s docker-maven plugin. Please check the pom.xml file plugin section.

Alternatively, you can build using Docker command line ->

docker build -t chakrar27/books:standalone .

And then run the image. Note that we need to pass the value of the variable HOSTS that our app container is going to look for when it tries to connect to the Couchbase container. The run command would look like:

docker run -p 8080:8080 -e HOSTS=192.168.99.100 chakrar27/books:standalone

Once the application is started, navigate to http://192.168.99.100:8080/.

The following page shows up:

An entry can be edited and saved.

There’s also a neat filtering feature provided by the N1QL query running underneath.

Users can also add a new book and delete an existing record. All the CRUD (Create/Read/Update/Delete) features of this simple application are powered by Couchbase N1QL queries, which we enabled by creating the BookStoreRepository, and, in turn, extends the CouchbasePagingAndSortingRepository.

New whitepaper: Database DevOps – 6 Tips for Achieving Continuous Delivery. Discover 6 tips for continuous delivery with Database DevOps in this new whitepaper from Redgate. In 9 pages, it covers version control for databases and configurations, branching and testing, automation, using NuGet packages, and advice for how to start a pioneering Database DevOps project. Also includes further research on the industry-wide state of Database DevOps, how application and database development compare, plus practical steps for bringing DevOps to your database. Read it now free.

Topics:
docker ,vaadin ,nosql ,couchbase ,tutorial ,database

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}