Java Reference

Controllers

Introduction

The @ApiController annotation, used at the class level, tells the KOS system that this particular class has REST endpoints. In other words, the class has "request" mappings for the HTTP GET/PUT/POST/DELETE methods. The KOS system must know which classes have endpoints, as it uses that information to determine where to dispatch various HTTP requests to.

Overview

The following annotations are documented in this article:

  • @ApiController

  • @ApiEndpoint

  • @HandleVariable

  • @PathVariable

  • @RequestBody

  • @RequestParam

  • @Tracker

In addition, these two intefaces are discussed:

  • HttpRequest

  • HttpResponse

As is the class:

  • ResponseEnvelope

API Endpoints

API endpoints are URLs that act as access points to a software application’s resources. When clients interact with an API, they send an HTTP request to one of these URLs. Those endpoints may accept information, return information, and/or perform some action.

Some things to note in this article:

  • All objects are transferred to and from KOS endpoints in JSON format.

  • All return values are enclosed in a response envelope (see next section).

  • All "desc" (description) annotation elements are multi-line and Markdown-capable.

  • All controllers are documented on-the-fly at runtime by hitting the "{base}/openapi" endpoint.

  • In the documentation regarding URLs, the "{base}" value is either:

    • http(s)://hostname:port/api/kos (for a standard app)

    • http(s)://hostname:port/api/system (for a system app)

Source code for this and most other Java reference pages is available on GitHub.

API Components

ResponseEnvelope

The ResponseEnvelope class encapsulates the response from all KOS HTTP/REST endpoints. These are automatically created by KOS, so you should never have to create one.

API: ResponseEnvelope class
@Getter @Setter  // adds getters and setters to all fields
public class ResponseEnvelope<T> {
    private int status;
    private ResponseVersion version;
    private T data;
    private String error;
}

A typical response might then look like, "data" is the payload:

ResponseEnvelope example
{
  "status": 200,
  "version": {
    "major": "1",
    "minor": "23"
  },
  "data": {
    "user": {
      "firstName": "Fred",
      "lastName": "Flintstone"
    }
  },
  "error": null
}

@ApiController

The @ApiController annotation can only be used on classes. The "value" parameter represents the base URL path that all subsequent methods have.

API: @ApiController annotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiController {

    /**
     * Base path for mappings.
     */
    String base();

    /**
     * Title of the controller for OpenApi docs.
     */
    String title() default "";

    /**
     * Description of the controller for OpenApi docs.
     */
    String desc() default "";
}
@ApiController example
/**
 * All endpoint URLs in this class are prefixed with "/mycontroller".
 */
@ApiController(
        base = "/mycontroller",
        title = "These endpoints related to foo",
        desc = "This is a more detailed description.")
public class MyController {
}

@ApiEndpoint

The @ApiEndpoint annotation is used on endpoints methods inside an @ApiController class. They specify the endpoint’s URL, HTTP method, description, and optional parameter descriptions.

One of the methods, with URL path, is required, as is the description.

API: @ApiEndpoint annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiEndpoint {

    /**
     * Sets the URL path of the associated GET operation.
     */
    String GET() default "";

    /**
     * Sets the URL path of the associated PUT operation.
     */
    String PUT() default "";

    /**
     * Sets the URL path of the associated POST operation.
     */
    String POST() default "";

    /**
     * Sets the URL path of the associated DELETE operation.
     */
    String DELETE() default "";

    /**
     * Description of the endpoint.
     */
    String desc();

    /**
     * Documents the URL parameters. Name of @Param should match a named parameter
     * in the request handler.
     */
    Param[] params() default {};

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Param {

        /**
         * Name of a parameter in the request handler. Name must match
         * for the documentation to be displayed.
         */
        String name();

        /**
         * Description of the parameter.
         */
        String desc();
    }
@ApiEndpoint example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "GET {base}/mycontroller/fetch" is hit,
     * then this method is called.
     */
    @ApiEndpoint(GET = "/fetch", desc = "This is what this endpoint does")
    public SomeBeanType fetch() {
        // fetch SomeBeanType here and return it
    }
}

@ApiVersion

The @ApiVersion annotation gives you the ability to document each endpoint with a version number. This version information is returned in the payload envelope, so that clients can determine how to process the payload in those cases where the payload changes over time. It can be used on classes and methods.

The version number string is in "major.minor" format. For example, "1.1", "2.17", etc.

All methods without an explicit version number are at version "1.0".

@ApiVersion example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "POST {base}/mycontroller/method1" is called,
     * this method returns version "1.0" in the payload envelope.
     */
    @ApiEndpoint(POST = "/method1", desc = "")
    public void method1() {
    }

    /**
     * When "POST {base}/mycontroller/method2" is called,
     * this method returns version "4.56" in the payload envelope.
     */
    @ApiVersion("4.56")
    @ApiEndpoint(PUT = "/method2", desc = "")
    public void method2() {
    }
}

@HandleVariable

The @HandleVariable annotation binds a method variable to a bean handle.

@HandleVariable example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "GET {base}/mycontroller/br-549" is called,
     * the object whose handle is "br-549" is passed in the "bean" variable.
     */
    @ApiEndpoint(GET = "/something/{handle}", desc = "")
    public void getBean(@HandleVariable("handle") SomeBean someBean) {
        // use the someBean object
    }
}

@PathVariable

The @PathVariable annotation binds a method variable to a path parameter. The method variable must be a common type, such as String, Integer, Long, Float, Double, or Boolean.

In the example below, note:

  • the multi-line endpoint description, and

  • a description of the "id" variable using the params = @Param annotation, which is used to document URL path parameters. See @ApiEndpoint for more info.

@PathVariable example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "GET {base}/mycontroller/user/63" is called,
     * the method parameter "id" has a value of 63.
     */
    @ApiEndpoint(GET = "/user/{id}", desc = """
        This is a multi-line description that can go on and on and on.
        It can be in Markdown format and can contain blank lines.""",
        params = @Param(name = "id", desc = "The unique 6-digit integer"))
    public SomeBeanType getBean(@PathVariable("id") Integer id) {
        // return
    }
}

@RequestBody

The @RequestBody annotation indicates that the body of the request should be parsed in an object and made available in the associated method parameter.

@RequestBody example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "POST {base}/mycontroller/user/save" is called,
     * the method parameter "userBean" is populated from the request's body.
     */
    @ApiEndpoint(POST = "/user/save", desc = "")
    public void saveUser(@RequestBody UserBean userBean) {
        // process userBean object
    }
}

@RequestParam

The @RequestParam annotation binds a method variable to a query parameter.

In the following, if the input URL is something like http://myserver.com/api/tolower?variable=ThisIsAString, then the method will return "thisisastring".

@RequestParam example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "GET {base}/mycontroller/user/list?order=firstName&limit=10" is called,
     * the method parameter "order" contains "firstName", and
     * the method parameter "limit" is 10.
     * As you can see, "order" is required, but "limit" is not.
     */
    @ApiEndpoint(GET = "/user/list", desc = "")
    public List<UserBean> listUsers(
            @RequestParam(value = "order", required = true) String order,
            @RequestParam(value = "limit", defaultValue = 20) Integer limit) {
        // process request
    }
}

@ResponseStream

The @ResponseStream annotation indicates that the response is a "raw output stream". Used then when a request method serves content such as a file or other stream of bytes.

@ResponseStream example
@ApiController(base = "/mycontroller")
public class MyController {

    /**
     * When "GET {base}/mycontroller/file/data.json" is called,
     * the method parameter "fileName" contains "data.json".
     * The resulting stream of bytes is returned to the httpResponse.getOutputStream().
     */
    @ApiEndpoint(GET = "/file/{name}", desc = "")
    @ResponseStream
    public void serveContent(HttpResponse httpResponse, @PathVariable("name") String fileName) {
        // send bytes to the httpResponse's output stream
    }
}

@Tracker

The @Tracker annotation binds a method parameter to a special tracker variable. Please read the Javadocs for a more detailed explanation.

@Tracker example
@ApiController(base = "/mycontroller")
public class MyController {

    @ApiEndpoint(POST = "/pump/{pump}/start", desc = "")
    public void startPump(@HandleVariable("pump") Pump pump, @Tracker String tracker) {
        pumpService.start(pump, tracker);
    }
}

HttpRequest

The HttpRequest interface abstracts out the common request methods used by the KOS system dispatcher.

API: HttpRequest interface
public interface HttpRequest extends AttributeAware {

    String getPath();
    RequestMethod getMethod();

    InputStream getInputStream() throws IOException;
    JsonNode getJsonBody();

    String getParameter(String name);
    MultiValueMap<String, String> getParameters();

    InetSocketAddress getClientAddress();

    String getHeader(String name);
    Collection<String> getHeaders(String name);
    Collection<String> getHeaderNames();
}
HttpRequest example
@ApiController(base = "/mycontroller")
public class MyController {

    @ApiEndpoint(GET = "/whatever", desc = "")
    public void startPump(HttpRequest httpRequest) {
        // use the httpRequest variable
    }
}

HttpResponse

The HttpResponse interface abstracts out the common response methods used by the KOS system dispatcher.

API: HttpResponse interface
public interface HttpResponse {

    OutputStream getOutputStream() throws IOException;

    void setHeader(String name, String val);
    void setDateHeader(String name, long date);

    int getStatus();
    void setStatus(int status);

    void sendError(int status) throws IOException;
}
HttpResponse example
@ApiController(base = "/mycontroller")
public class MyController {

    @ApiEndpoint(GET = "/whatever", desc = "")
    public void startPump(HttpResponse httpResponse) {
        // use the httpResponse variable
    }
}

Summary

This article explained the REST controller API of the KOS SDK.

RESTful API

This following annotations, interfaces, and classes comprise the KOS REST controller API:

  • @ApiController

  • @ApiEndpoint

  • @HandleVariable

  • @PathVariable

  • @RequestBody

  • @RequestParam

  • @Tracker

  • HttpRequest

  • HttpResponse

  • ResponseEnvelope

Next up, we’ll examine how to make RESTful calls using the KOS ApiClient component.

Previous
Next
On this page
Java Development
Seamlessly transition from Legacy+ systems to Freestyle microdosing and advanced distributed dispense systems.
UI Development
Using KOS SDKs, integrating Consumer and Non-consumer facing UIs becomes seamless, giving you less hassle and more time to create.
Video Library
Meet some of our development team, as they lead you through the tools, features, and tips and tricks of various KOS tools.
Resources
Familiarize yourself with KOS terminology, our reference materials, and explore additional resources that complement your KOS journey.
Copyright © 2024 TCCC. All rights reserved.