Skip to content

Commit 2651b9a

Browse files
luigi617luigi
andauthored
Service sdk readme (#1391)
Co-authored-by: luigi <[email protected]>
1 parent 4e86b3e commit 2651b9a

File tree

6 files changed

+400
-0
lines changed

6 files changed

+400
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Smithy Kotlin Service Codegen (SKSC)
2+
3+
## Overview
4+
5+
This project generate **service-side code** from Smithy models, producing **complete service stubs**, including routing, serialization/deserialization, authentication, and validation, so developers can focus entirely on implementing business logic.
6+
7+
While Ktor is the default backend, the architecture is framework-agnostic, allowing future support for other server frameworks.
8+
9+
10+
## Getting Started
11+
12+
- Get an [introduction to Smithy](https://smithy.io/2.0/index.html)
13+
- Follow [Smithy's quickstart guide](https://smithy.io/2.0/quickstart.html)
14+
- See the [Guide](docs/GettingStarted.md) to learn how to use SKSC to generate service.
15+
- See a [Summary of Service Support](docs/FEATURES.md) to learn which features are supported
16+
17+
18+
## Development
19+
20+
### Module Structure
21+
22+
- `constraints` – directory that contains the constraints validation generator.
23+
- `ConstraintsGenerator.kt` - main generator for constraints.
24+
- `ConstraintUtilsGenerator` - generator for constraint utilities.
25+
- For each constraint trait, there is a dedicated file.
26+
- `ktor` – directory that stores all features generators specific to Ktor.
27+
- `ktorStubGenerator.kt` – main generator for ktor framework service stub generator.
28+
- `ServiceStubConfiguration.kt` – configuration file for the service stub generator.
29+
- `ServiceStubGenerator.kt` – abstract service stub generator file.
30+
- `ServiceTypes.kt` – file that includes service component symbols.
31+
- `utils.kt` – utilities file.
32+
33+
### Testing
34+
35+
The **service code generation tests** are located in `tests/codegen/service-codegen-tests`. These end-to-end tests generate the service, launch the server, send HTTP requests to validate functionality, and then shut down the service once testing is complete. This process typically takes around 2 minutes. To run tests specifically for SKSC, use the following command:
36+
```bash
37+
./gradlew :tests:codegen:service-codegen-tests:test
38+
```
39+
40+
## Feedback
41+
42+
You can provide feedback or report a bug by submitting an [issue](https://github.com/smithy-lang/smithy-kotlin/issues/new/choose).
43+
This is the preferred mechanism to give feedback so that other users can engage in the conversation, +1 issues, etc.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Summary
2+
3+
---
4+
5+
### Features Support
6+
7+
| **Features** | **Description** |
8+
|-----------------------------------|-------------------------------------------------------------------------------------------------|
9+
| Service Framework | Abstracted service framework interface and base implementation with Ktor as the default backend |
10+
| CBOR Protocol | Support for CBOR serialization / deserialization and CBOR protocol traits |
11+
| Json Protocol | Support for Json serialization / deserialization and Json protocol traits |
12+
| Routing | Per-operation routing generation with Ktor DSL; ties to handler and validation |
13+
| Error Handler | Unified exception handling logic mapped to HTTP status codes and support for error trait |
14+
| Authentication (bearer) | Bearer token authentication middleware with model-driven configuration |
15+
| Authentication (SigV4 and SigV4A) | SigV4 and SigV4A authentication middleware with model-driven configuration |
16+
| Logging | Structured logging setup |
17+
| Constraints Checker | Validation logic generated from Smithy traits and invoked pre-handler |
18+
| Unit Test | Covers serialization/deserialization, routing, validation, and integration tests |
19+
20+
### Smithy Protocol Traits Support
21+
22+
| **Traits** | **CBOR Protocol** | **Json Protocol** |
23+
|--------------------------|-------------------|-------------------|
24+
| http | Yes | Yes |
25+
| httpError | Yes | Yes |
26+
| httpHeader | Not supported | Yes |
27+
| httpPrefixHeader | Not supported | Yes |
28+
| httpLabel | Not supported | Yes |
29+
| httpQuery | Not supported | Yes |
30+
| httpQueryParams | Not supported | Yes |
31+
| httpPayload | Not supported | Yes |
32+
| jsonName | Not supported | Yes |
33+
| timestampFormat | Not supported | Yes |
34+
| httpChecksumRequired | Not supported | Not implemented yet |
35+
| requestCompression | Not implemented yet | Not implemented yet |
36+
37+
### Constraint Traits Support
38+
39+
| **Traits** | **CBOR Protocol** | **Json Protocol** |
40+
|-----------------|------------------------------|------------------------------|
41+
| required | Yes | Yes |
42+
| length | Yes | Yes |
43+
| pattern | Yes | Yes |
44+
| private | Yes (handled by Smithy) | Yes (handled by Smithy) |
45+
| range | Yes | Yes |
46+
| uniqueItems | Yes | Yes |
47+
| idRef | Not implemented yet | Not implemented yet |
48+
49+
50+
### Future Features
51+
52+
| Feature | Description |
53+
|-----------------------------------|-------------------------------------------------------------------------------------------------|
54+
| Additional Protocols | XML, Ec2Query, AWSQuery protocols |
55+
| Middleware / Interceptors | Cross-cutting logic support (e.g., metrics, headers, rate limiting) via middleware architecture |
56+
| API Versioning | Built-in support for versioned APIs to maintain backward compatibility |
57+
| gRPC / WebSocket Protocol Support | High-performance binary RPC and real-time bidirectional communication |
58+
| Metrics & Tracing | Observability support with metrics, logs, and distributed tracing for debugging and monitoring |
59+
| Caching Middleware | Per-route or global cache support to improve response times and reduce backend load |
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Getting Started
2+
3+
### Step 1: Build & Publish Codegen to Local Maven
4+
First, in **this repository**, build and publish the code generator locally:
5+
```bash
6+
./gradlew :codegen:smithy-kotlin-codegen:build
7+
./gradlew publishToMavenLocal
8+
```
9+
10+
### Step 2: Create a New Kotlin Project
11+
Now, create a **new Kotlin project** where you will use the Smithy Kotlin service code generator. You can find a full example demo project [here](../../../../../../../../../../../../examples/service-codegen)
12+
13+
From this point forward, **all steps apply to the new Kotlin project** you just created.
14+
15+
16+
### Step 3: Configure `build.gradle.kts` in the New Project
17+
18+
```kotlin
19+
plugins {
20+
alias(libs.plugins.kotlin.jvm)
21+
id("software.amazon.smithy.gradle.smithy-jar") version "1.3.0" // check for latest version
22+
application
23+
}
24+
25+
repositories {
26+
mavenLocal()
27+
mavenCentral()
28+
}
29+
30+
val codegenVersion = "0.35.2-SNAPSHOT"
31+
val smithyVersion = "1.60.2"
32+
33+
dependencies {
34+
smithyBuild("software.amazon.smithy.kotlin:smithy-kotlin-codegen:$codegenVersion")
35+
implementation("software.amazon.smithy.kotlin:smithy-aws-kotlin-codegen:$codegenVersion")
36+
implementation("software.amazon.smithy:smithy-model:$smithyVersion")
37+
implementation("software.amazon.smithy:smithy-build:$smithyVersion")
38+
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
39+
...
40+
}
41+
```
42+
43+
44+
### Step 4: Create `smithy-build.json` in the New Project
45+
This is an example of smithy-build.json.
46+
```json
47+
{
48+
"version": "1.0",
49+
"outputDirectory": "build/generated-src",
50+
"plugins": {
51+
"kotlin-codegen": {
52+
"service": "com.demo#DemoService",
53+
"package": {
54+
"name": "com.demo.server",
55+
"version": "1.0.0"
56+
},
57+
"build": {
58+
"rootProject": true,
59+
"generateServiceProject": true,
60+
"optInAnnotations": [
61+
"aws.smithy.kotlin.runtime.InternalApi",
62+
"kotlinx.serialization.ExperimentalSerializationApi"
63+
]
64+
},
65+
"serviceStub": {
66+
"framework": "ktor"
67+
}
68+
}
69+
}
70+
}
71+
```
72+
73+
**Notes:**
74+
- The most important fields are:
75+
- **`outputDirectory`** — defines where the generated service code will be placed in your new project.
76+
- **`service`** — must match your Smithy model’s `<namespace>#<service shape name>`.
77+
- **`serviceStub.framework`** — defines the server framework for generated code. Currently only `"ktor"` is supported.
78+
79+
### Step 5: Define Your Smithy Model in the New Project
80+
81+
Create a `model` directory and add your `.smithy` files.
82+
Example `model/greeter.smithy`:
83+
84+
```smithy
85+
$version: "2.0"
86+
namespace com.demo
87+
88+
use aws.protocols#restJson1
89+
use smithy.api#httpBearerAuth
90+
91+
@restJson1
92+
@httpBearerAuth
93+
service DemoService {
94+
version: "1.0.0"
95+
operations: [
96+
SayHello
97+
]
98+
}
99+
100+
@http(method: "POST", uri: "/greet", code: 201)
101+
operation SayHello {
102+
input: SayHelloInput
103+
output: SayHelloOutput
104+
errors: [
105+
CustomError
106+
]
107+
}
108+
109+
@input
110+
structure SayHelloInput {
111+
@required
112+
@length(min: 3, max: 10)
113+
name: String
114+
@httpHeader("X-User-ID")
115+
id: Integer
116+
}
117+
118+
@output
119+
structure SayHelloOutput {
120+
greeting: String
121+
}
122+
123+
@error("server")
124+
@httpError(500)
125+
structure CustomError {
126+
msg: String
127+
@httpHeader("X-User-error")
128+
err: String
129+
}
130+
```
131+
132+
### Step 6: Generate the Service in the New Project
133+
134+
Run:
135+
```bash
136+
gradle build
137+
```
138+
139+
If you want to clean previously generated code:
140+
```bash
141+
gradle clean
142+
```
143+
144+
### Step 7: Run the Generated Service
145+
146+
The generated service will be in the directory specified in `smithy-build.json` (`outputDirectory`).
147+
You can start it by running:
148+
```bash
149+
gradle run
150+
```
151+
By default, it listens on port **8080**.
152+
153+
### Step 8: Adjust Service Configuration
154+
155+
You can override runtime settings (such as port or HTTP engine) using command-line arguments:
156+
```bash
157+
gradle run --args="port 8000 engineFactory cio"
158+
```
159+
You can find all available settings [here](https://github.com/smithy-lang/smithy-kotlin/blob/16bd523e2ccd6177dcc662466107189b013a818d/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/ServiceStubGenerator.kt#L179C1-L186C38)
160+
161+
---
162+
163+
## Notes
164+
- **Business Logic**: Implement your own logic in the generated operation handler interfaces.
165+
- **Configuration**: Adjust port, engine, auth, and other settings via `ServiceFrameworkConfig` or CLI args.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* This file was generated by the Gradle 'init' task.
3+
*
4+
* This generated file contains a sample Kotlin application project to get you started.
5+
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.14.2/userguide/building_java_projects.html in the Gradle documentation.
6+
*/
7+
8+
plugins {
9+
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
10+
alias(libs.plugins.kotlin.jvm)
11+
12+
id("software.amazon.smithy.gradle.smithy-jar") version "1.3.0"
13+
// Apply the application plugin to add support for building a CLI application in Java.
14+
application
15+
}
16+
17+
repositories {
18+
// Use Maven Central for resolving dependencies.
19+
mavenCentral()
20+
mavenLocal()
21+
}
22+
23+
val codegenVersion = "0.35.2-SNAPSHOT"
24+
val smithyVersion = "1.60.2"
25+
26+
dependencies {
27+
smithyBuild("software.amazon.smithy.kotlin:smithy-kotlin-codegen:$codegenVersion")
28+
implementation("software.amazon.smithy.kotlin:smithy-aws-kotlin-codegen:$codegenVersion")
29+
implementation("software.amazon.smithy:smithy-model:$smithyVersion")
30+
implementation("software.amazon.smithy:smithy-build:$smithyVersion")
31+
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
32+
// Use the Kotlin JUnit 5 integration.
33+
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
34+
35+
// Use the JUnit 5 integration.
36+
testImplementation(libs.junit.jupiter.engine)
37+
38+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
39+
40+
// This dependency is used by the application.
41+
implementation(libs.guava)
42+
}
43+
44+
// Apply a specific Java toolchain to ease working on different environments.
45+
java {
46+
toolchain {
47+
languageVersion = JavaLanguageVersion.of(21)
48+
}
49+
}
50+
51+
tasks.named<Test>("test") {
52+
// Use JUnit Platform for unit tests.
53+
useJUnitPlatform()
54+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// model/greeter.smithy
2+
$version: "2.0"
3+
4+
namespace com.demo
5+
6+
use aws.protocols#restJson1
7+
use smithy.api#httpBearerAuth
8+
9+
@restJson1
10+
@httpBearerAuth
11+
service DemoService {
12+
version: "1.0.0"
13+
operations: [
14+
SayHello
15+
]
16+
}
17+
18+
@http(method: "POST", uri: "/greet", code: 201)
19+
operation SayHello {
20+
input: SayHelloInput
21+
output: SayHelloOutput
22+
errors: [
23+
CustomError
24+
]
25+
}
26+
27+
@input
28+
structure SayHelloInput {
29+
@required
30+
@length(min: 3, max: 10)
31+
name: String
32+
33+
@httpHeader("X-User-ID")
34+
id: Integer
35+
}
36+
37+
@output
38+
structure SayHelloOutput {
39+
greeting: String
40+
}
41+
42+
@error("server")
43+
@httpError(500)
44+
structure CustomError {
45+
msg: String
46+
47+
@httpHeader("X-User-error")
48+
err: String
49+
}

0 commit comments

Comments
 (0)