MCPcopy Index your code
hub / github.com/HTTP-RPC/Kilo

github.com/HTTP-RPC/Kilo @6.4.5

Chat with this repo
repository ↗ · DeepWiki ↗ · release 6.4.5 ↗ · + Follow
1,238 symbols 4,798 edges 116 files 267 documented · 22%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Releases Maven Central javadoc

Introduction

Kilo is an open-source framework for creating and consuming web APIs in Java. It also includes a number of general-purpose developer productivity features. The project's name comes from the nautical K or Kilo flag, which means "I wish to communicate with you":

Classes provided by the Kilo framework include:

Each is discussed in more detail below. Java 21 or later is required.

WebService

WebService is an abstract base class for web services. It extends the similarly abstract HttpServlet class and provides a thin, resource-oriented layer on top of the standard servlet API.

For example, the following service implements some simple mathematical operations:

@WebServlet(urlPatterns = "/math/*", loadOnStartup = 0)
@Description("Math service.")
public class MathService extends WebService {
    @RequestMethod("GET")
    @ResourcePath("sum")
    @Description("Calculates the sum of two numbers.")
    public double getSum(
        @Description("The first number.") double a,
        @Description("The second number.") double b
    ) {
        return a + b;
    }

    @RequestMethod("GET")
    @ResourcePath("sum")
    @Description("Calculates the sum of a list of numbers.")
    public double getSum(
        @Description("The numbers to add.") List<Double> values
    ) {
        var total = 0.0;

        for (var value : values) {
            total += value;
        }

        return total;
    }
}

The RequestMethod annotation associates an HTTP verb such as GET or POST with a service method, or "handler". The optional ResourcePath annotation associates a handler with a specific path, or "endpoint", relative to the servlet. WebService selects the best method to execute based on the values provided by the caller. For example, this request would invoke the first method:

GET /math/sum?a=2&b=4

while this would invoke the second:

GET /math/sum?values=1&values=2&values=3

In either case, the service would return the value 6 in response.

The optional Description annotation is used to document a service implementation and is discussed in more detail later.

Method Parameters

Method parameters may be any of the following types:

  • Byte/byte
  • Short/short
  • Integer/int
  • Long/long
  • Float/float
  • Double/double
  • Boolean/boolean
  • String
  • java.time.Instant
  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime
  • java.time.Duration
  • java.time.Period
  • java.util.UUID
  • enum

Additionally, these types are supported for multi-value parameters:

  • java.util.List
  • java.util.Set/SequencedSet/SortedSet
  • array/varargs

For body content, the following types are also supported:

  • java.util.Map/SequencedMap/SortedMap
  • bean/record

Unspecified values are automatically converted to 0 or false for primitive types. If no values are provided for a multi-value parameter, an empty instance (not null) will be passed to the method.

If an argument cannot be coerced to the expected type, an HTTP 403 (forbidden) response will be returned. If no method is found that matches the provided arguments, HTTP 405 (method not allowed) will be returned.

Note that service classes must be compiled with the -parameters flag so that parameter names are available at runtime.

Required Parameters

Parameters that must be provided by the caller can be indicated by the Required annotation. For example, the following service method accepts a single required owner argument:

@RequestMethod("GET")
public List<Pet> getPets(@Required String owner) throws SQLException {
    ... 
}

List, Set, and array parameters are implicitly required, since these values will never be null (though they may be empty). For all other parameter types, HTTP 403 will be returned if a required value is not provided.

Custom Parameter Names

The Name annotation can be used to associate a custom name with a method parameter. For example:

@WebServlet(urlPatterns = "/members/*", loadOnStartup = 0)
public class MemberService extends WebService {
    @RequestMethod("GET")
    public List<Person> getMembers(
        @Name("first_name") String firstName,
        @Name("last_name") String lastName
    ) {
        ...
    }
}

This method could be invoked as follows:

GET /members?first_name=j*&last_name=smith

Path Variables

Path variables (or "keys") are specified by a "?" character in a handler's resource path. For example, the itemID argument in the method below is provided by a path variable:

@RequestMethod("GET")
@ResourcePath("items/?")
@Description("Returns detailed information about a specific item.")
public ItemDetails getItem(
    @Description("The item ID.") Integer itemID
) throws SQLException { ... }

Path parameters must precede query parameters in the method signature and are implicitly required. Values are mapped to method arguments in declaration order.

Body Content

Body content is declared as the final parameter in a POST or PUT handler. For example, this method accepts an item ID as a path variable and an instance of ItemDetails as a body argument:

@RequestMethod("PUT")
@ResourcePath("items/?")
@Description("Updates an item.")
public void updateItem(
    @Description("The item ID.") Integer itemID,
    @Description("The updated item.") ItemDetails item
) throws SQLException { ... }

Like path parameters, body parameters are implicitly required. By default, content is assumed to be JSON and is automatically converted to the appropriate type. However, a body parameter of type org.w3c.dom.Document can be used to indicate that the method expects XML content.

Requests may also be submitted as form data. WebService collects parameter values into a single body argument that is passed to the handler method. For multi-part requests, jakarta.servlet.http.Part values are translated to instances of java.nio.file.Path.

A body parameter of type Void indicates that a handler either does not accept a body or will process the input stream directly.

Return Values

Return values are converted to JSON as follows:

  • Boolean/boolean: boolean
  • Number/numeric primitive: number
  • CharSequence: string
  • Iterable: array
  • java.util.Map, bean, or record type: object

Character or char values are converted to a number. Instances of java.util.Date or java.time.Instant are converted to a number representing epoch time in milliseconds. Instances of other types are converted to their string representations.

Alternatively, a method may return an instance of org.w3c.dom.Document to produce an XML response.

By default, HTTP 200 (OK) is returned when a service method completes successfully. However, if the method is annotated with Creates, HTTP 201 (created) will be returned instead. If the method is annotated with Accepts, HTTP 202 (accepted) will be returned. If the handler's return type is void or Void, HTTP 204 (no content) will be returned.

If a service method returns null, an HTTP 404 (not found) response will be returned.

Exceptions

If an exception is thrown by a service method and the response has not yet been committed, the exception message (if any) will be returned as plain text in the response body. Error status is determined as follows:

  • IllegalArgumentException or UnsupportedOperationException - HTTP 403 (forbidden)
  • NoSuchElementException - HTTP 404 (not found)
  • IllegalStateException - HTTP 409 (conflict)
  • Any other exception - HTTP 500 (internal server error)

Database Connectivity

For services that require database connectivity, the following method can be used to obtain a JDBC connection object associated with the current invocation:

protected static Connection getConnection() { ... }

The connection is established via the openConnection() method, which returns null by default. Service classes must override this method to provide a valid connection instance.

Auto-commit is disabled so an entire request will be processed within a single transaction. If the request completes successfully, the transaction is committed. Otherwise, it is rolled back.

Request and Repsonse Properties

The following methods provide access to the request and response objects associated with the current invocation:

protected static HttpServletRequest getRequest() { ... }
protected static HttpServletResponse getResponse() { ... }

For example, a service might use the request to read directly from the input stream, or use the response to return a custom header.

The response object can also be used to produce a custom result. If a service method commits the response by writing to the output stream, the method's return value (if any) will be ignored by WebService. This allows a service to return content that cannot be easily represented as JSON, such as image data.

Inter-Service Communication

A reference to any active service can be obtained via the getInstance() method of the WebService class. This can be useful when the implementation of one service depends on functionality provided by another service, for example.

Alternatively, the Instance annotation can be used to automatically inject a service instance into a member variable:

private @Instance MathService mathService = null;

Content Generation

The PageServlet class facilitates generation of document-oriented content such as invoices or reports. It supports read-only database access and shares a connection instance with WebService.

The abstract execute() method is called to produce the page data. An HTML template with the same name as the implementing class will be automatically applied to the value returned by this method, unless the method commits the response by writing to the output stream directly. This allows an implementation to support alternate representations such as CSV.

As with WebService, service instances are automatically injected into annotated fields. See MathServlet or PetServlet for more information.

API Documentation

An index of all active services can be found at the application's context root:

GET http://localhost:8080/kilo-test

Documentation for a specific service can be viewed by appending ".html" to the service's base URL:

GET http://localhost:8080/kilo-test/catalog.html

Implementations can provide additional information about service types and operations using the Description annotation. For example:

@WebServlet(urlPatterns = "/catalog/*", loadOnStartup = 0)
@Description("Catalog service.")
public class CatalogService extends AbstractDatabaseService {
    @RequestMethod("GET")
    @ResourcePath("items")
    @Description("Returns a list of all items in the catalog.")
    public List<Item> getItems() throws SQLException {
        ...
    }

    ...
}

Descriptions can also be associated with bean types, records, and enums:

@Table("item")
@Description("Represents a catalog item.")
public interface Item {
    @Name("id")
    @Column("id")
    @PrimaryKey
    @Description("The item's ID.")
    Integer getID();
    void setID(Integer id);

    @Column("description")
    @Index
    @Description("The item's description.")
    @Required
    String getDescription();
    void setDescription(String description);

    @Column("price")
    @Description("The item's price.")
    @Required
    Double getPrice();
    void setPrice(Double price);
}
@Description("Represents an x/y coordinate pair.")
public record Coordinates(
    @Description("The x-coordinate.")
    @Required
    int x,

    @Description("The y-coordinate.")
    @Required
    int y
) {
}
@Description("Represents a size option.")
public enum Size implements Numeric {
    @Description("A small size.") SMALL(10),
    @Description("A medium size.") MEDIUM(20),
    @Description("A large size.") LARGE(30);

    private final int value;

    Size(int value) {
        this.value = value;
    }

    @Override
    public int value() {
        return value;
    }
}

Deprecated elements will be identified as such in the output.

WebServiceProxy

The WebServiceProxy class is used to submit API requests to a server. It provides the following constructor, which accepts a string representing the HTTP method to execute and

Extension points exported contracts — how you extend this code

RequestHandler (Interface)
Represents a request handler. [8 implementers]
kilo-client/src/main/java/org/httprpc/kilo/WebServiceProxy.java
Example (Interface)
(no doc) [4 implementers]
kilo-test/src/test/java/org/httprpc/kilo/examples/Examples.java
Modifier (Interface)
Represents a modifier. [6 implementers]
kilo-client/src/main/java/org/httprpc/kilo/io/TemplateEncoder.java
MemberServiceProxy (Interface)
(no doc) [1 implementers]
kilo-test/src/test/java/org/httprpc/kilo/test/MemberServiceProxy.java
ResponseHandler (Interface)
Represents a response handler. [3 implementers]
kilo-client/src/main/java/org/httprpc/kilo/WebServiceProxy.java
CatalogServiceProxy (Interface)
(no doc) [1 implementers]
kilo-test/src/test/java/org/httprpc/kilo/test/CatalogServiceProxy.java
ErrorHandler (Interface)
Represents an error handler. [1 implementers]
kilo-client/src/main/java/org/httprpc/kilo/WebServiceProxy.java
FilmServiceProxy (Interface)
(no doc) [1 implementers]
kilo-test/src/test/java/org/httprpc/kilo/test/FilmServiceProxy.java

Core symbols most depended-on inside this repo

entry
called by 440
kilo-client/src/main/java/org/httprpc/kilo/util/Collections.java
listOf
called by 247
kilo-client/src/main/java/org/httprpc/kilo/util/Collections.java
mapOf
called by 203
kilo-client/src/main/java/org/httprpc/kilo/util/Collections.java
append
called by 148
kilo-client/src/main/java/org/httprpc/kilo/sql/QueryBuilder.java
coerce
called by 77
kilo-client/src/main/java/org/httprpc/kilo/beans/BeanAdapter.java
write
called by 50
kilo-client/src/main/java/org/httprpc/kilo/io/TemplateEncoder.java
put
called by 49
kilo-client/src/main/java/org/httprpc/kilo/beans/BeanAdapter.java
get
called by 42
kilo-client/src/main/java/org/httprpc/kilo/beans/BeanAdapter.java

Shape

Method 1,067
Class 118
Interface 47
Enum 6

Languages

Java100%

Modules by API surface

kilo-server/src/main/java/org/httprpc/kilo/WebService.java93 symbols
kilo-client/src/test/java/org/httprpc/kilo/sql/QueryBuilderTest.java90 symbols
kilo-client/src/main/java/org/httprpc/kilo/beans/BeanAdapter.java69 symbols
kilo-test/src/main/java/org/httprpc/kilo/test/TestService.java68 symbols
kilo-test/src/test/java/org/httprpc/kilo/test/WebServiceProxyTest.java56 symbols
kilo-client/src/test/java/org/httprpc/kilo/beans/TestBean.java56 symbols
kilo-client/src/main/java/org/httprpc/kilo/sql/QueryBuilder.java50 symbols
kilo-client/src/main/java/org/httprpc/kilo/WebServiceProxy.java48 symbols
kilo-client/src/test/java/org/httprpc/kilo/io/TemplateEncoderTest.java44 symbols
kilo-client/src/test/java/org/httprpc/kilo/beans/TestInterface.java34 symbols
kilo-client/src/test/java/org/httprpc/kilo/util/IterablesTest.java33 symbols
kilo-client/src/test/java/org/httprpc/kilo/beans/BeanAdapterTest.java32 symbols

For agents

$ claude mcp add Kilo \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact