6 Back-end API

In addition to the full API provided by the Java system and any additional JAR files you add, Kiss comes with an API that assists with the development of business application with Kiss. These API’s may be broadly grouped as follows:

  1. Database API
  2. JSON API
  3. Utilities

An overview of these APIs is contained in this chapter. Detailed documentation is contained in the JavaDocs (See Creating JavaDocs) and in the Kiss book, which provides comprehensive coverage with worked examples.

6.1 Database API

Kiss comes with a powerful library for accessing SQL databases. Code for this is located under org.kissweb.database It is currently being used in production environments. This API provides the following benefits:

As shipped, this library supports PostgreSQL, Microsoft Server, Oracle, MySQL, and SQLite.

The detailed documentation for the database utilities is in the JavaDocs which you must generate. (See Creating JavaDocs.) This section provides an overview.

The Kiss database routines revolve around four main classes as follows:

Connection

This represents a connection to an SQL database.

Command

This represents a single action or command against the database.

Cursor

If the action is a select, the Cursor represents a pointer into the result set.

Record

This class represents a single row within a table or result set.

The Connection class contains several convenience methods that are used in simple cases where only a single action is being performed. These methods should not be used when multiple simultaneous actions are taking place at once (by that single thread). This issue is not a problem in multi-user or multi-threaded situations. It is only a problem when a single thread is doing one action while another action is still open.

You will notice that your REST services are passed a Connection argument. Kiss automatically forms a unique connection for each REST service call and closes it when the call is done. Therefore, you will not normally need to create your own connection. Additionally, Kiss automatically starts a new transaction with each REST service and commits it when the service is done. However, if the service throws any exception, the transaction is rolled back instead.

You would not normally write SQL for single record adds, updates, and deletes. Using the Record API, Kiss automatically generates these statements for you.

In addition to the above, these utilities provide full support for transactions and parameters.

6.2 Microservices

Microservices are classes that may be added, changed, or deleted while the system is running. In spite of this, however, all microservices are fully compiled and run at full speed. This has two major advantages.

First, in a development environment, all development may be done without the need to bring the development server down, rebuild, re-deploy, and reboot the development server. This means development time is significantly reduced. Additionally, IDE debuggers function in an environment such as this, so the debugging process may proceed normally.

Second, in a production environment, the system may be upgraded without disrupting existing users on the system. Of course, users actively using the exact features you have just changed could be affected (if their front-end and back-end do not agree). A simple re-try would put everything back in sync.

Kiss microservices are on a class basis. What that means is that a microservice is always a single and whole class. You cannot have more than one class in a microservice. Microservices can call core components of the system just as regular methods can. However, if one wishes to have one microservice call another microservice, the calling mechanism is a little more clunky. However, using this clunkier mechanism retains all of the dynamic features of the system.

Defining microservices in Kiss involves defining a normal class just as you would write a class in any circumstance. No special configuration, wiring, declarations, or additional steps are required. Microservice additions, changes, and deletions take effect as soon as you save the source file. All microservices are compiled at runtime by the system automatically, so there is no compilation step that you need to perform.

The only caveat to the above is that remote microservices (described below) expect a certain method signature (standard arguments). This is only to assure that the front-end and back-end can communicate as expected. Local microservices do not have this requirement.

6.2.1 Microservice Language

In Kiss, microservices can be written in Java, Groovy, or Common Lisp. However, Groovy microservices have been used exclusively in all current environments that we are aware of. Therefore, Groovy microservices are best tested.

The reasons Groovy was used are as follows:

  1. Groovy was the easiest and most natural to implement.
  2. Groovy runs as fast as Java and has full and natural access to all Java facilities.
  3. The actual loading of Groovy services is the fastest of the three languages.
  4. Groovy is largely a super-set of Java so if you know Java, you basically know Groovy. Learning of additional Groovy facilities can occur over time.
  5. Groovy offers a small number of conveniences over Java.

Having said all this, however, all three languages are fully supported and there are no known bugs in any of the supported languages.

6.2.2 Types of Microservices

There are two types of microservices as follows:

  1. Remote (REST) Services
  2. Local Services

Remote services are generally called by a (likely JavaScript) front-end or a remote client typically over HTTP or HTTPS. Local services are services that are called locally, from within the system as, for example, one microservice calling a method in a different microservice.

6.2.3 Remote Microservices

In Kiss, remote microservices appear to the outside world as typical REST services. They may be called by a JavaScript front-end, web service client, or any other facility that can talk to REST services.

Kiss REST services are asynchronous HTTP or HTTPS services. Internally they are processed utilizing a thread pool to assure optimal CPU utilization. The number of threads in the thread pool is controlled by a configuration parameter given in the application.ini file.

Kiss comes with JavaScript code so that Kiss REST services can be easily accessed from a typical front-end. This code resides in a single file and can and has been used by alternative front-ends such as Angular and React.

There is no need to handle authentication. Kiss handles that automatically. So, when your web method is called, you know who they are and that they have been authenticated.

6.2.4 Defining Remote Services

Remote REST microservices typically reside under the backend/services directory. You can organize them any way you like. A microservice is equivalent to a class. The class name is the microservice name. The methods in that class that have a certain signature (a particular set of arguments) are the web methods.

A REST web microservice has the following signature:

void myMethod(JSONObject injson, 
              JSONObject outjson, 
              Connection db, 
              ProcessServlet servlet) {
...
}
injson

This is a JSON object that contains all of the arguments passed in from the front-end.

outjson

This is a JSON object that will contain all of the results sent back to the front-end. Whatever is put in this object gets sent back to the front-end.

db

This is a database connection that can be used to access the SQL database. The connection is unique and independent of all other services.

servlet

This object provides access to various system facilities uniquely related to this call.

See JSON and the JavaDoc for additional information.

6.2.5 Local Microservices

Local microservices are simply regular classes. They typically reside in the backend/services directory organized any way you like. Although methods within a particular microservice/class can call each other in the normal way, there is an extra step required for one microservice to call a method in a different microservice. One of the reasons for this is so the system can be certain the latest version of the service is loaded and that it is fully compiled before you attempt to use it.

In Groovy, a method in one class/microservice can call a method in a different class/microservice via the following methods.

  • GroovyService.run
  • GroovyService.getMethod

See the Javadoc.

6.2.6 Exceptions

Kiss defines three exception classes named UserException, LogException and ServerException. These exceptions are designed to be thrown from within your web services.

UserException is used to abort the web service due to some sort of user error. An error message and possible error code are returned to the front-end. The front-end displays the error message in a popup and tells the web front-end that the web service failed by returning _Success = false. Nothing is logged on the back-end. This was not an error in the back-end. It is good for notices to the user that something was wrong with their data.

LogException is like UserException except that it additionally leaves the message on the back-end log. This is useful for debugging purposes.

ServerException is like UserException except that it additionally leaves a message and stack trace on the back-end log. This is useful for debugging purposes.

6.3 JSON

The first two arguments to all REST methods are injson and outjson. injson is a JSONObject that contains the data passed in from the front-end. outjson is a pre-initialized, empty JSONObject that will be returned to the front-end. The REST service should read the data passed in from injson, perform any needed processes, and put the result into outjson to be returned to the front-end.

The two main data types are JSONObject and JSONArray. Common methods include getString(), getInt(), getBoolean(), getDouble(), getJSONArray(), has(), and put(). See the JavaDocs for the complete API.

6.4 Large Language Models

Kiss provides a high-level interface to the Ollama large language model (LLM), the OpenAI (chatGPT) server, and the Anthropic (Claude) server. This makes it easy for you to add LLM features to your application.

6.4.1 Ollama

Before this can function, however, you must have access to an Ollama server, either running on your local machine or a remote machine.

  • See https://ollama.com for information about installing the Ollama server.
  • The Kiss class org.kissweb.llm.Ollama implements the interface.
  • Kiss comes with a complete demo of this functionality.

6.4.2 OpenAI (chatGPT)

Unlike the Ollama server, which runs locally, the chatGPT server runs on the cloud-based OpenAI server. In order to use this server, you must have an account with them. Once you get an account, you will need an API Key to interface with their server. Once you have this API Key, you may query chatGPT.

The single KISS class that interfaces with OpenAI is named OpenAI.

Typical usage would look as follows:

    String apiKey = "xxxxxxxxxxxxxxx";
    OpenAI chatGPT = new OpenAI(apiKey, "gpt-3.5-turbo")
    String result = chatGPT.send("Who is president Bush?")

The static method setUrl(String url) can be used to override the default OpenAI endpoint URL. This is useful for proxies, gateways, or OpenAI-compatible endpoints. Since it is a global setting, changing the URL affects all instances.

See that class for documentation.

6.4.3 Anthropic (Claude)

Like OpenAI, the Anthropic server runs in the cloud. In order to use it, you must have an account with Anthropic. Once you get an account, you will need an API Key to interface with their server. Once you have this API Key, you may query Claude.

The single KISS class that interfaces with Anthropic is named Anthropic.

Typical usage would look as follows:

    String apiKey = "xxxxxxxxxxxxxxx";
    Anthropic claude = new Anthropic(apiKey, "claude-sonnet-4-20250514");
    String result = claude.send("Who is president Bush?");

The class also supports streaming responses and image inputs.

The static method setUrl(String url) can be used to override the default Anthropic endpoint URL. This is useful for proxies, gateways, or Anthropic-compatible endpoints. The static method setVersion(String version) can be used to override the anthropic-version request header value (e.g., 2023-06-01). Both are global settings that affect all instances.

See that class for documentation.

6.5 Utilities

Kiss includes an ever-growing set of utilities to help deal with common tasks. These utilities are located under the src/main/core/org/kissweb directory and have names such as DateTime.java, NumberFormat, etc. These utilities are documented in the JavaDocs.

6.6 Global Logout Handler

Kiss provides a mechanism to execute custom code whenever a user logs out (manually or due to inactivity timeout). The handler is configured in KissInit.groovy using UserCache.setLogoutHandler(), which accepts a Consumer<UserData>.

A basic example:

UserCache.setLogoutHandler({ UserData ud ->
    println "User ${ud.getUsername()} is logging out"
} as Consumer<UserData>)

The UserData object provides methods such as getUsername(), getUserId(), getUuid(), and getUserData(String key). If you need database access in the handler, open a new connection with MainServlet.openNewConnection() and close it in a finally block.

To log out from the front-end, call Server.logout().

For detailed examples and usage patterns, see the Kiss book and the JavaDocs.