API description
The API (Application Programming Interface) allows internal and external clients to access and use the functionality of the service. A well-designed API makes it easy for users to understand how to use the service but also influences scalability and flexibility, as it should be easily updated and extended without affecting the applications that use it. As a best practice, you should separate the structures that define the external APIs from those that define the domain state model, so each can evolve independently.
Protocol-first Approach
In the Protocol-first SDKs, Kalix requires you to use Protocol buffers to describe the contract for an API. Protocol Buffers is a language and platform agnostic, extensible description model. To create and deploy a service, you define APIs and Entity data structures in a .proto
file, each API being a gRPC service.
Protocol Buffer example
Depending on the component (Views, Actions, or Entities) you choose, the options you can define can differ. For a detailed overview of all options, check out the respective guide for the component you want to implement. Next, we have an example of the definition of a Value Entity
:
syntax = "proto3"; (1)
package shopping.product.api; (2)
import "kalix/annotations.proto"; (3)
import "google/api/annotations.proto";
message Order { (4)
string orderID = 2; [(kalix.field).entity_key = true]; (5)
repeated OrderItem items = 3;
}
message OrderItem {
string productID = 1;
int32 quantity = 2;
float price = 3;
}
service OrderBackendService { (6)
option (kalix.service) = { (7)
type: SERVICE_TYPE_ENTITY
component: "shopping.product.domain.ProductPopularityValueEntity"
};
rpc AddOrder (Order) returns (Order) { (8)
option (google.api.http) = {
post: "/order/{orderID}",
body: "*"
};
}
}
1 | Specify the version of the Protobuf syntax, Kalix uses proto3. |
2 | Packages prevent name clashes between protocol messages, similar to how packages work in programming languages. |
3 | Imports allow you to use definitions from other protobuf files. You’ll always need kalix/annotations.proto , other imports are optional. In this case google/api/annotations.proto adds the ability to expose services with HTTP endpoints. |
4 | Messages represent the request and response of API calls and are used to define the data structure of the data you want to persist (also known as state). These structures can be as simple or as complex as you need for your use case. |
5 | This annotation defines which field in your message uniquely identifies the instance of your entity. |
6 | A gRPC service defines how external clients can interact with your business logic. |
7 | This annotation is used by the Kalix codegen tools to specify what type of code needs to be generated (in this case an entity) and the fully qualified name (package name and entity name) of the message that represents the state. |
8 | Every service has one or more RPC methods that specify the functionality of your service. Each method will be handled by a function in your code. The google.api.http option tells Kalix that this RPC method should get a gRPC and an HTTP endpoint. |
The implementation, your code, ties these .proto
files together as shown in the image below: