Overview
We start this tutorial with the great news! Finally Knot.x Stack is available.
Let's just cut to the point. In this tutorial we will configure Knot.x instance with a simple page that uses an external datasource (Google API Books) to fetch the dynamic data and display it on our page.
What you’re going to learn:
- How to setup Knot.x instance using Knot.x Stack
- 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 instance
Prerequisites You will need following things to use Knot.x stack:
- JDK 8
- Linux or OSX bash console (for Windows users we recommend using e.g. Ubuntu with Windows Subsystem for Linux).
Download Knot.x distribution and unzip it.
For the purpose of this tutorial let's call the structure of unzipped stack KNOTX_HOME
.
KNOTX_HOME
which is Knot.x instance with all configuration files and dependencies has following structure:
├── bin
│ └── knotx // shell script used to resolve and run knotx instance
├── conf // contains application and logger configuration files
│ ├── application.conf // defines all modules that Knot.x instance is running, provides configuration for Knot.x Core and global variables for other config files
│ ├── bootstrap.json // config retriever options, defines application configuration stores (e.g. points to `application.conf` - the main configuration)
│ ├── default-cluster.xml // basic configuration of Knot.x instance cluster
│ ├── includes // additional modules configuration which are included in `application.conf`
│ │ ├── actionKnot.conf
│ │ ├── dataBridge.conf
│ │ ├── dataSourceHttp.conf
│ │ ├── hbsKnot.conf
│ │ ├── httpRepo.conf
│ │ ├── server.conf
│ └── logback.xml // logger configuration
├── knotx-stack.json // stack descriptor, defines instance libraries and dependencies
├── lib // contains instance libraries and dependencies, instance classpath
│ ├── list of project dependency libraries
│ ├── ...
Now, run
bin/knotx run-knotx
to start the Knot.x instance. You should see that the instance is running with all deployed modules. Following entries should appear in the logs/knotx.log
file:
2018-04-17 09:48:39.849 [vert.x-eventloop-thread-0] INFO i.k.launcher.KnotxStarterVerticle - Knot.x STARTED
Deployed httpRepo=java:io.knotx.repository.http.HttpRepositoryConnectorVerticle [233dced4-658a-422b-870f-51f12a7ced21]
Deployed assembler=java:io.knotx.assembler.FragmentAssemblerVerticle [9a075059-4b73-4f50-9890-d38282e2ace4]
Deployed dataBridge=java:io.knotx.databridge.core.DataBridgeKnot [0c5ac5ea-a196-4678-8f11-e6af84f23e7c]
Deployed dataSourceHttp=java:io.knotx.databridge.http.HttpDataSourceAdapter [ba9429fb-ef52-4241-8c11-94977b0a30c9]
Deployed splitter=java:io.knotx.splitter.FragmentSplitterVerticle [da1384fb-641a-4835-a313-03ecc1c42458]
Deployed hbsKnot=java:io.knotx.knot.templating.HandlebarsKnotVerticle [41875d6a-699a-4099-969f-115292152801]
Deployed server=java:io.knotx.server.KnotxServerVerticle [1d044822-8c95-4ae4-b2f8-6886412400eb]
Congratulation! That's it. You have your own basic Knot.x instance running.
Hello Service configuration
Lets now configure Knot.x to do the magic for us. We need to do following things:
- provide the page template, for the tutorial purpose we will use
fileSystemRepo
, - provide the datasource, we will use the Google Books API.
All configuration options and default values, such as address fields, for each Knot.x module are described directly in the configuration files of those modules in
conf
.
Templates repository configuration
By default fileSystemRepo
is not enabled in Knot.x Stack, because its purposes are purely academical.
It is not designed to be used as a production ready solution (you should use httpRepo
there).
Edit the conf/application.conf
file and
add the following entry to
modules
"fileSystemRepo=io.knotx.repository.fs.FilesystemRepositoryConnectorVerticle"
By doing that you let Knot.x instance to start
FilesystemRepositoryConnector
with the namefileSystemRepo
. It will be later referenced by this name in configurations.uncomment
fileSystemRepo.address
in theglobal.repositories
section to define the Event Bus address of Filesystem Repository.fileSystemRepo.address = knotx.core.repository.filesystem
- Save the changes in
conf/application.conf
. You may see that Knot.x instance reloaded modules andfileSystemRepo
is now one of available modules. No restart required!
Deployed httpRepo=java:io.knotx.repository.http.HttpRepositoryConnectorVerticle [c81f07ae-9345-482a-bd7f-af3e261876e0]
Deployed assembler=java:io.knotx.assembler.FragmentAssemblerVerticle [d8010ea9-6b65-482b-a37c-2139bf154413]
Deployed dataBridge=java:io.knotx.databridge.core.DataBridgeKnot [db7b7503-71e0-40e0-adde-9012c885d581]
Deployed splitter=java:io.knotx.splitter.FragmentSplitterVerticle [ed249e56-92c3-486d-827a-ad506a7e0ac3]
Deployed hbsKnot=java:io.knotx.knot.templating.HandlebarsKnotVerticle [b19ea9d2-59ed-4926-9365-3579af42895b]
Deployed fileSystemRepo=java:io.knotx.repository.fs.FilesystemRepositoryConnectorVerticle [0879f874-1276-44b9-b746-585ab19f7d25]
Deployed dataSourceHttp=java:io.knotx.databridge.http.HttpDataSourceAdapter [9caebb6a-18ed-474f-9182-56efdd180771]
Deployed server=java:io.knotx.server.KnotxServerVerticle [0c5f5136-c925-4f93-88b3-d24233a54988]
Now, let's configure fileSystemRepo
to read files from the local filesystem.
Create content
directory in KNOTX_HOME
and put there following page template with Knot.x snippet (<script data-knotx-knots="databridge,handlebars">...
):
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">
<script data-knotx-knots="databridge,handlebars"
data-knotx-databridge-name="bookslist"
type="text/knotx-snippet"></script>
</div>
</div>
</body>
</html>
Create conf/includes/fileSystemRepo.conf
file with the following:
# Event bus address on which the File System Repository connector listens on. Default is 'knotx.core.repository.filesystem'
# Here below, we use a global constant defined in `conf/application.conf`
address = ${global.repositories.fileSystemRepo}
# Path to the directory on the local filesystem which will be the root for requested templates
catalogue = "./content/"
This way we define the content
directory that will to be our file repository.
Next we need to reference it at the end of conf/application.conf
file by adding the following:
config.fileSystemRepo {
options.config {
include required("includes/fileSystemRepo.conf")
}
}
Replace httpRepo
with fileSystemRepo
in conf/server.conf
in defaultFlow
section.
...
# Configuration of a default flow - aka Templating mode
defaultFlow {
# List of the Knot.x templates repositories supported by the Server
repositories = [
{
path = ".*"
address = ${global.repositories.fileSystemRepo}
}
]
...
Connecting the datasource
As you probably noticed in the template snippet, bookslist
datasource is defined (data-knotx-databridge-name="bookslist"
).
Let's now define it in the configuration.
To do so, open conf/includes/dataBridge.conf
and add the bookslist
data definition:
# Event bus settings
address = ${global.bridge.address}
# List of mappings between data definition aliases and datasources.
# You can define here as many data definitions definitions as required for your project.
dataDefinitions = [
# Definition of the single datasource to be used in the HTML snippets.
# You can define an array of such data definitions here.
{
# Name of the data definition that will be used in HTML snippets
name = bookslist
# Arbitrary parameters to be send to datasources adapter. In this case we send the query that is part of request path to google books API
params {
path= "/books/v1/volumes?q=java"
}
# Event bus address of the datasources adapter that is responsible for handling physicall communication with a data source
adapter = ${global.bridge.dataSource.http.address}
}
]
Now, as we have the bookslist
data definition, let's edit conf/includes/dataSourceHttp.conf
file and configure Adapter available
under ${global.bridge.dataSource.http.address}
which evaluates into knotx.bridge.datasource.http
address.
Set up service entry and enable SSL by setting ssl = true in the clientOptions configuration.
# Event bus address of the Basic HTTP Datasource
address = ${global.bridge.dataSource.http.address}
clientOptions {
maxPoolSize = 1000
idleTimeout = 120 # seconds
# If your datasources are using SSL you'd need to configure here low level details on how the
# SSL connection is to be maintaned. Currently, if configured all defined in 'datasources' section
# will use SSL
ssl = true
}
# List of datasource services that are supported by this datasource adapter.
# You can define here as many service definitions as required for your project.
services = [
{
# A regexp.
# Any request to the service made by the adapter, is being made to the service with a given
# physical conenction details, only if the given path matching this path regexp
path = "/books.*"
# A domain or IP of actual HTTP service the adapter will talk to
domain = "www.googleapis.com"
# HTTP port of the service, since this is SSL connection, port wourld be 443
port = 443
# List of request headers that will be send to the given service endpoint.
# Each header can be use wildcards '*' to generalize list, we pass all headers here.
# For the purpose of this tutorial, we deny all request headers.
allowedRequestHeaders = [ ]
# Additional request query parameters to be send in each request. We don't need here any.
queryParams {}
# Additional headers to be send in each request to the service. We don't need here any.
additionalHeaders {}
}
]
# Statically defined HTTP request header sent in every request to any datasource
customRequestHeader {
name = X-User-Agent
value = Knot.x
}
Save the configuration file, Knot.x will reload its modules once again.
The last thing left, open http://localhost:8092/books.html - Voilà!