Controllers

Introduction

One class you will frequently see in KOS applications is the Controller. Controllers denote a type of class which stores RESTful HTTP endpoints. These endpoints can then be used for controlling various parts of an Application. Most typically they are used by UI to interact with the back end. Other times you may use a controller as a simple way to test various components, or as a method for two applications to communicate with one another. Regardless, in this article we will go through a sample controller, explaining what everything does, and the various features contained therein.

The Basics

For a class to be denoted as a controller it must be annotated with the @ApiController annotation. Within this annotation one must specify the controller base, which will prefix all the endpoint url paths. Developers may also, if they so choose, specify a title, description, and version. This information will be visible in the KOS Studio “API browser” tool and Postman. It’s worth noting that while any class can technically serve as a controller, the convention is to have dedicated controller classes whose sole responsibility is to define and organize endpoints. Keeping to this convention is especially helpful when organizing multiple controllers within the same project, as often occurs.

Moving on to the endpoints themselves. Each endpoint has its own handler method annotated with @ApiEndpoint, which only requires a url path and description. The url path is linked to the endpoint’s operation type. @ApiEndpoint supports four types of operations; GET, PUT, POST, and DELETE. It should be noted that KOS will automatically prefix the endpoint paths with the parent app’s app id. This is important because if the app id is ever changed, so too will all the endpoints. That aside, below is a sample controller with a single GET endpoint. When a value is returned from an endpoint in kos, that value is serialized into a json, before being sent to the client.

Beyond specifying the url and description for each endpoint, there are a plethora of options which can be used in endpoint annotation. If you wish to view these in their entirety, please consult the javadocs. Now that we have defined a sample controller, the last step toward making it functional is to instantiate it and add it to the context like so. Doing so will make the API visible in the “API Browser” and the endpoints usable.

Endpoint Arguments

There will often be times that you will wish to pass an argument to a handler. There exist a number of ways to do this in KOS. A developer can denote a specific kind of argument using its respective annotation when passing it to the request handler. For now, we will just be covering how to use path variables, handle variables, and the body. These are some of the most commonly used types. To see all the argument types and their respective annotations, please see the javadocs. To demonstrate the use of these three kinds of arguments, below is a sample controller which uses all three in different endpoints.

The most basic way of passing an argument is to use a path variable. When you use a path variable, you are expecting a string to be present within the url path, and extracting it. The location of the path variable is indicated with curly brackets, within which sits a variable name of your choosing; in this case “sampleArg”. Then, with the @PathVariable annotation, this same variable is passed as an integer argument to the request handler. Now the path variable can be used within the request handler. In the context of path variables, type checking is enforced.

Sometimes a user may want to reference a specific class instance through an endpoint. KOS already provides a system for this. Any class that implements the HandleAware<T> interface will have an associated unique string, known as a handle path. This handle path can then be passed to an endpoint as a handle variable, allowing the appropriate class instance to be retrieved via the @HandleVariable in the request handler. This pattern is commonly used to access and manipulate specific pieces of hardware via endpoints. To see more about handles and their unique functionality, please see this article: HandlePaths

Finally, for times when it becomes necessary to pass entire objects though an endpoint, KOS offers developers a simple way to read the body of the incoming request. Using the @RequestBody annotation, the body can be de-serialized from a json into its appropriate class, by specifying the class as the type in the request handler arguments.

Ultimately, controllers are a cornerstone of KOS development, and it is highly recommended that anyone developing on the platform have a thorough understanding of them.

Other Features

For situations in which you want more control over the HTTP response, you can access the response as an argument of the handler method like so:

Accessing the response directly like this allows you to directly modify the header, connection, and status of the response. To see more on the various methods associated with HttpResponse please reference the javadocs here: HttpResponse.

Good Practices

For times when the handler method must throw an exception, it is good practice to throw a ReasonException. Reason exceptions are a kind of RuntimeException that contain a reason code, and sometimes reason data. A reason code is a string, typically written in camel case, which indicates an error in a human-readable format. Reason codes essentially substitute error codes and allow the user to easily understand the cause of the exception without the need for a error code lookup table. ReasonException can have data objects attached to them for times when it is beneficial to include more information about the . Reason exceptions are designed to be json serializable. For these reasons, they are particularly useful for endpoints, as they can clearly communicate issues to the front end. To learn more about the ReasonException you can visit the javadocs here: ReasonException