Getting Started with Docker

Piotr Marcinkowski
2.0.0

Overview

In this tutorial, we will setup a simple project based on the Knot.x Starter Kit template. Will configure Knot.x with a simple page that uses an external datasource (Google Books API) to fetch the dynamic data and display it on our page.

What you’re going to learn:

  • How to setup a Knot.x project with customization based on the Knot.x Starter Kit template
  • How to transform a static HTML into the dynamic content and configure Knot.x to use REST services to get data
  • How to use the data from such services to dynamically populate HTML

Setup basic Knot.x project

Prerequisites You will need the following things to use Knot.x:

Download the Latest Knot.x Starter Kit release and unzip it.

Project has the following structure:

├── docker
|   ├── Dockerfile                // Docker file with image definition.
├── functional                    // Keep here your functional tests. Example implementation included
├── gradle                        // Gradle wrapper and common gradle scripts
├── knotx                         // Knotx configuration which will be copied to docker image
├── modules                       // Sub-modules of your project
│   ├── ...                       // example modules implementation

Configuration

Let's now configure Knot.x to do the magic for us. We need to do two things:

All configuration options and default values, for each Knot.x module, are described on github. For example fsRepoConnectorHandler configuration

HTML Template

Create a knotx/repository/content directory in your project and put there following page template with Knot.x snippet (<knotx:snippet data-knotx-task="bookslist">...):

books.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Knot.x</title>
  <link href="https://bootswatch.com/4/superhero/bootstrap.min.css" rel="stylesheet"/>
</head>
<body>
<div class="container-fluid">
  <div class="row">
    <div class="col-sm-12">
      <div class="panel panel-default">
        <div class="panel-heading">Books list</div>
        <div class="panel-body">
          This page lists Java related books provided by <a
            href="https://www.googleapis.com/books/v1/volumes?q=java">Googleapis book service</a>.
        </div>
      </div>
    </div>
  </div>
  <div class="row">
   <knotx:snippet data-knotx-task="bookslist">
      {{#each _result.items}}
        <div class="col-sm-3">
        <div class="card">
          <img class="card-img-top"
             src="{{volumeInfo.imageLinks.thumbnail}}"
             alt="{{volumeInfo.title}}">
          <div class="card-block">
            <h4 class="card-title">{{volumeInfo.title}}</h4>
            <p class="card-text">
              {{#each volumeInfo.authors as |author|}}
                {{author}}{{#unless @last}}, {{/unless}}
              {{/each}}<br />
              Published: {{volumeInfo.publishedDate}}
            </p>
          </div>
         </div>
      </div>
      {{/each}}
    </knotx:snippet>

    </div>
</div>
</body>
</html>

Templates repository configuration

We will use fsRepoConnectorHandler, its purposes are purely academical. It is not designed to be used as a production ready solution (you should use httpRepoConnectorHandler there).

Create knorx/conf/routes/handlers/fsRepoConnectorHandler.conf file with the following:

# Path to the directory on the local filesystem which will be the root for requested templates
catalogue = "/usr/local/knotx/repository/"

This way we define the repository directory that will be our files content repository.

openapi.yml

Open knotx/conf/openapi.yml and add following path definition:

  /content/*:
    get:
      operationId: content-get
      responses:
        default:
          description: Remote repository template processing

By doing this you define the operation which should be executed for path /content/*.

operations.conf

Now, you need to define operation content-get. Open knotx/conf/routes/operations.con Add in routingOperations array following definition:

  {
    operationId = content-get
    handlers = ${config.server.handlers.common.request} [
      {
        name = fsRepoConnectorHandler
        config = {include required(classpath("routes/handlers/fsRepoConnectorHandler.conf"))}
      },
      {
        name = htmlFragmentsSupplier
      },
      {
        name = fragmentsHandler
        config = {include required(classpath("routes/handlers/fragmentsHandler.conf"))}
      },
      {
        name = fragmentsAssembler
      }
    ] ${config.server.handlers.common.response}
  }

Task configuration

As you probably noticed the Knot.x snippet you defined in the books.html template file pointed to the bookslist task. Let's define it.

Create knotx/conf/routes/handlers/fragmentsHandler.conf and add following code:

tasks {
  bookslist {
    action = books
    onTransitions {
      _success {
        action = te-hbs
      }
    }
  }
}

actions {
  books {
    factory = http
    config {
      endpointOptions {
        path = "/books/v1/volumes?q=java"
        domain = www.googleapis.com
        port = 443
        allowedRequestHeaders = ["Content-Type"]
      }
      webClientOptions {
        ssl = true
      }
    }
  }
  te-hbs {
    factory = knot
    config {
      address = knotx.knot.te.handlebars
      deliveryOptions {
        sendTimeout = 1000
      }
    }
  }
}

Above file will be processed by fragmentsHandler. We will cover more sophisticated example in the configurable API gateway tutorial

Docker

Configuration

Knot.x Starter Kit project builds docker image. Edit gradle.properties and change property docker.image.name:

docker.image.name=knotx-example/getting-started

Run

Now we are ready to run. First, build your docker image

$ gradlew clean build

Run Knot.x instance:

docker run -p8092:8092 knotx-example/getting-started

Final page

http://localhost:8092/content/payment.html