Skip to content

Client walkthrough

Generate a client library for a KX service using an OpenAPI client generator

Scope

The examples here use Java, Javascript and the Swagger Codegen generator.

You can follow similar steps for any of the many languages Swagger Codegen supports.

By adapting the commands in this walkthrough, you can also use other code generation-tools.

The examples use the OpenAPI specification for the KXI Service Discovery microservice. OpenAPI specifications for other KXI microservices can easily be substituted.

Prerequisites

Create a folder to use as the root directory for the walkthrough.

mkdir open-api-clients && cd open-api-clients

All commands will be relative to this directory unless otherwise stated.

Download the Swagger Codegen CLI.

$ CLI_VERSION=3.0.26
$ wget -q https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/$CLI_VERSION/swagger-codegen-cli-$CLI_VERSION.jar -O swagger-codegen-cli.jar

Version 3.0.26 is the latest version of the tool available at the time of writing.

Download the KX Service Discovery OpenAPI specification.

wget -q https://code.kx.com/insights/microservices/service-discovery/api/service-discovery.yaml \
    -O discovery.json

Java

Complete the prerequisites.

We are going to

  1. Use the swagger-codegen-cli.jar to generate a Java SDK
  2. Create a project that uses the generated SDK

Generate the SDK

Generate a Java client library using the swagger-codegen-cli.jar from the prerequisites and the discovery.json spec.

$ cat config.json
{
    "hideGenerationTimestamp": "true"
}
$ java -jar swagger-codegen-cli.jar generate -c config.json -l java -i discovery.json -o java-discovery-sdk

There will be an auto-generated README.md in java-discovery-sdk that explains how to use this client library.

Use the SDK

We will cover the steps to use this in a Maven project.

You can now install the SDK locally with Maven using

cd java-discovery-sdk
mvn clean install

If you experience issues installing the SDK, see troubleshooting for possible solutions.

It can now be referenced as a dependency in other local projects if you add the following dependency to your pom.xml

<dependency>
  <groupId>io.swagger</groupId>
  <artifactId>swagger-java-client</artifactId>
  <version>1.0.0</version>
  <scope>compile</scope>
</dependency>

Once this is done you can create an example call that uses the io.swagger.client package as follows

import io.swagger.client.*;
import io.swagger.client.auth.*;
import io.swagger.client.model.*;
import io.swagger.client.api.DiscoveryApi;

import java.io.File;
import java.util.*;

public class DiscoveryApiExample {

    public static void main(String[] args) {

        ApiClient client = new ApiClient();
        client.setBasePath("http://localhost:5000");

        DiscoveryApi apiInstance = new DiscoveryApi(client);

        try {
            ServiceTable result = apiInstance.getServices();
            System.out.println(result);
        } catch (ApiException e) {
            System.err.println("Exception when calling DiscoveryApi#getServices");
            e.printStackTrace();
        }
    }
}

If you run this and there is a valid discovery proxy at localhost:5000 that has some services registered with it, then you will see output similar to

class ServiceTable {
    [class ServiceTableInner {
        uid: RDB:5444
        service: RDB
        ip: 172.18.0.7
        hostname: 4764daa74c43
        port: 5444
        status: UP
        metadata: {instanceId=4764daa74c43:RDB:5444, byteKey=0100000028000000630b0001000000636f6e6e6563746976697479000b00010000006165726f6e00}
    }, class ServiceTableInner {
        uid: LR:5445
        service: LR
        ip: 172.18.0.3
        hostname: 279e7d45bd4a
        port: 5445
        status: UP
        metadata: {instanceId=279e7d45bd4a:LR:5445, byteKey=0100000028000000630b0001000000636f6e6e6563746976697479000b00010000006165726f6e00}
    }, class ServiceTableInner {
        uid: 2c04c966caf4:KXI-DISCOVERY:8761
        service: KXI-DISCOVERY
        ip: 172.18.0.2
        hostname: registry-0
        port: 8761
        status: UP
        metadata: {management.port=8761}
    }]
}

In this example the discovery proxy has three services registered with it: LR,RDB, and KXI-DISCOVERY.

Troubleshooting

Depending on the version of Java you are using, you may need to take extra steps to build and install the autogenerated project.

If you see the error

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.10.4:jar (attach-javadocs) on project
swagger-java-client:   MavenReportException: Error while generating Javadoc: Unable to find javadoc command: The environment
variable JAVA_HOME is not correctly set. -> [Help 1]

during the install, upgrade the version of the maven-javadoc-plugin to 3.3.0

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>3.3.0</version>
    ...
</plugin>

If you see the error

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project
swagger-java-client: Compilation failure: Compilation failure: 
[ERROR] /code/java-discovery-sdk/src/main/java/io/swagger/client/model/ServiceEntry.java:[28,18] package 
javax.annotation does not exist
...

during install, this is because javax.annotation is no longer a part of the JRE from Java 11. This can be resolved by adding it as a dependency explicitly in pom.xml.

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

Javascript

Complete the prerequisites.

We are going to

  1. Use the swagger-codegen-cli.jar to generate a Javascript SDK
  2. Create a project that uses the generated SDK
Versions of npm and node used in this walkthrough
$ npm --version
7.11.2
$ node --version
v12.21.0

Generate the SDK

Generate a JavaScript client library using the swagger-codegen-cli.jar from the prerequisites and the discovery.json spec.

java -jar swagger-codegen-cli.jar generate -l javascript -i discovery.json -o js-discovery-sdk

There will be an autogenerated README.md in js-discovery-sdk that explains how to use this client library, and documentation on the specific classes in docs.

Use the SDK

We will cover the steps to use this in a Node.js project.

First, we install the dependencies for the generated, and edit the package.json to specify that the package type of the SDK is a module.

$ cd js-discovery-sdk
$ npm install
$ vi package.json
{
...
  "type": "module",
...
}
$ cd ..

Create a new folder to house the project that will use the SDK and install the SDK as a dependency

mkdir js-client && cd js-client
npm install ../js-discovery-sdk --save

You should now have a folder structure:

├── node_modules/
├── package-lock.json
└── package.json

We will use this project as a module, so you will need to set the package type to be module in the package.json

$ vi package.json
{
  "type": "module",
...
}

Create a file called main.js that contains

import * as kx from 'kx_insights_service_discovery';

var client = new kx.ApiClient();
client.basePath = "http://localhost:5000";

var api = new kx.DiscoveryApi(client);

api.getServices((error, data, response) => {
  if (error) {
    console.error(error);
  } else {
    console.log(JSON.stringify(data, null, 2));
  }
});

You can run your main.js with

node --experimental-specifier-resolution=node main.js
--experimental-specifier-resolution

The argument --experimental-specifier-resolution=node is required because the generated SDK uses relative paths.

If you run this and there it a valid discovery proxy at localhost:5000 it will print out the services in the discovery registry.

Depending on what is registered with your discovery service you will see something like

[
  {
    "uid": "RDB:5444",
    "service": "RDB",
    "ip": "172.18.0.2",
    "hostname": "4764daa74c43",
    "port": 5444,
    "status": "UP",
    "metadata": {
      "instanceId": "4764daa74c43:RDB:5444",
      "byteKey": "0100000028000000630b0001000000636f6e6e6563746976697479000b00010000006165726f6e00"
    }
  },
  {
    "uid": "LR:5445",
    "service": "LR",
    "ip": "172.18.0.3",
    "hostname": "279e7d45bd4a",
    "port": 5445,
    "status": "UP",
    "metadata": {
      "instanceId": "279e7d45bd4a:LR:5445",
      "byteKey": "0100000028000000630b0001000000636f6e6e6563746976697479000b00010000006165726f6e00"
    }
  },
  {
    "uid": "2c04c966caf4:KXI-DISCOVERY:8761",
    "service": "KXI-DISCOVERY",
    "ip": "172.18.0.5",
    "hostname": "registry-0",
    "port": 8761,
    "status": "UP",
    "metadata": {
      "management.port": "8761"
    }
  }
]

In this example the discovery proxy has three services registered with it: LR,RDB, and KXI-DISCOVERY.