Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use example.traits#resourceMetadata
associatedStructures: [ForecastStruct]
)
resource Forecast {
identifiers: { forecastId: ForecastId }
identifiers: {
forecastId: ForecastId
}
}

string ForecastId
Expand Down
10 changes: 8 additions & 2 deletions gradle-plugin-examples/tutorial/service/model/service.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,14 @@ service DrinkService {

@externalDocumentation(wikipedia: "https://en.wikipedia.org/wiki/Order")
resource Order {
identifiers: { id: MenuItemId }
properties: { price: Price, style: Style, type: Type }
identifiers: {
id: MenuItemId
}
properties: {
price: Price
style: Style
type: Type
}
create: CreateOrder
read: GetOrder
}
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
smithyVersion=1.51.0
smithyGradleVersion=1.1.0
smithyJavaVersion=0.0.1
7 changes: 7 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@ includeBuild("gradle-plugin-examples/tutorial")

// Integ test
include(":gradle-plugin-examples:integ:tutorial")

// ---- Smithy-Java examples ----
// templates
includeBuild("smithy-java-examples/quickstart-java")

// integration tests
include(":smithy-java-examples:integ")
4 changes: 4 additions & 0 deletions smithy-java-examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Linting and Validation
The examples in this directory demonstrate the use of the [Smithy Java](https://github.com/smithy-lang/smithy-java) code generator.

Additional examples can be found [in the Smithy Java repository](https://github.com/smithy-lang/smithy-java/tree/main/examples).
30 changes: 30 additions & 0 deletions smithy-java-examples/quickstart-java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Smithy-Java Quickstart

This project provides a template to get started using [Smithy Java](https://github.com/smithy-lang/smithy-java/)
to create Java clients and servers.

For more information on this example, see the [Smithy Java Quickstart Guide](https://smithy.io/2.0/java/quickstart.html).

### Layout
- `lib/`: Common package for the service API model. Shared by both client and server.
- `server/`: Code generated Server that implements stubbed operations code-generated from the service model.
- `client/`: Code generated client that can call the server.
- `plugins/`: A package defining client plugins.

### Usage

To create a new project from this template, use the [Smithy CLI](https://smithy.io/2.0/guides/smithy-cli/index.html)
`init` command as follows:

```console
smithy init -t smithy-java-quickstart
```

### Running and testing server

To run and test the server, run `./gradlew run` from the root of a project created from this
template. That will start the server running on port `8888`.

Once the server is running, you can call the server using curl or by executing the integration tests in `client` subproject:
- `curl`: `curl -H "content-type: application/json" -d '{"coffeeType": "LATTE"}' -X POST localhost:8888/order`
- integration tests: `./gradlew :client:integ`
8 changes: 8 additions & 0 deletions smithy-java-examples/quickstart-java/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

// Add repositories for all subprojects to resolve dependencies.
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
}
65 changes: 65 additions & 0 deletions smithy-java-examples/quickstart-java/client/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
description = "Cafe service client"

plugins {
`java-library`
// Executes smithy-build process to generate client code
id("software.amazon.smithy.gradle.smithy-base")
}

dependencies {
val smithyJavaVersion: String by project

// === Code generators ===
smithyBuild("software.amazon.smithy.java.codegen:plugins:$smithyJavaVersion")

// === Service model ===
implementation(project(":lib"))

// === Client Plugins ===
implementation(project(":plugins"))

// === Client Dependencies ===
// Core client dependency required by generated client code.
implementation("software.amazon.smithy.java:client-core:$smithyJavaVersion")
// Add client implementation of `RestJson1` protocol
implementation("software.amazon.smithy.java:aws-client-restjson:$smithyJavaVersion")

// Test dependencies
testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

afterEvaluate {
val clientPath = smithy.getPluginProjectionPath(smithy.sourceProjection.get(), "java-client-codegen")
sourceSets {
// Add generated client source code to the main sourceSet
main {
java {
srcDir(clientPath)
}
}
// Set up integration testing tasks source set
create("it") {
compileClasspath += main.get().output + configurations["testRuntimeClasspath"] + configurations["testCompileClasspath"]
runtimeClasspath += output + compileClasspath + test.get().runtimeClasspath + test.get().output
}
}
}

tasks {
// Ensure compilation happens after source-code generation
val smithyBuild by getting
compileJava {
dependsOn(smithyBuild)
}

// This is set up integ tests separate from the `test` task to
// avoid automatically running tests as part of build.
val integ by registering(Test::class) {
useJUnitPlatform()
testClassesDirs = sourceSets["it"].output.classesDirs
classpath = sourceSets["it"].runtimeClasspath
// Allow the integ tests to print to stdout/stderr
testLogging.showStandardStreams = true
}
}
12 changes: 12 additions & 0 deletions smithy-java-examples/quickstart-java/client/smithy-build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "1.0",
"plugins": {
"java-client-codegen": {
"service": "com.example#CoffeeShop",
"namespace": "io.smithy.java.client.example",
"headerFile": "../license.txt",
"protocol": "aws.protocols#restJson1",
"defaultPlugins": ["io.smithy.java.example.plugins.ExamplePlugin"]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: MIT-0
*/

package io.smithy.java.client.example;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import io.smithy.java.client.example.client.CoffeeShopClient;
import io.smithy.java.client.example.model.CoffeeType;
import io.smithy.java.client.example.model.CreateOrderInput;
import io.smithy.java.client.example.model.GetMenuInput;
import io.smithy.java.client.example.model.GetOrderInput;
import io.smithy.java.client.example.model.OrderNotFound;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;


public class TestRunner {
private final CoffeeShopClient client = CoffeeShopClient.builder().build();

@Test
public void getMenu() {
var menu = client.getMenu(GetMenuInput.builder().build());
System.out.println(menu);
}

@Test
public void createOrder() throws InterruptedException {
// Create an order
var createRequest = CreateOrderInput.builder().coffeeType(CoffeeType.COLD_BREW).build();
var createResponse = client.createOrder(createRequest);
System.out.println("Created request with id = " + createResponse.id());

// Get the order. Should still be in progress.
var getRequest = GetOrderInput.builder().id(createResponse.id()).build();
var getResponse1 = client.getOrder(getRequest);
System.out.println("Got order with id = " + getResponse1.id());

// Give order some time to complete
System.out.println("Waiting for order to complete....");
TimeUnit.SECONDS.sleep(5);

// Get the order again.
var getResponse2 = client.getOrder(getRequest);
System.out.println("Completed Order :" + getResponse2);
}

@Test
void errorsOutIfOrderDoesNotExist() throws InterruptedException {
var getRequest = GetOrderInput.builder().id(UUID.randomUUID().toString()).build();
var orderNotFound = assertThrows(OrderNotFound.class, () -> client.getOrder(getRequest));
assertEquals(orderNotFound.orderId(), getRequest.id());
}
}
3 changes: 3 additions & 0 deletions smithy-java-examples/quickstart-java/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
smithyVersion=1.51.0
smithyGradleVersion=1.1.0
smithyJavaVersion=0.0.1
23 changes: 23 additions & 0 deletions smithy-java-examples/quickstart-java/lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
description = "Smithy definition of a Cafe service."

plugins {
`java-library`
// Packages the models in this package into a jar for sharing/distribution by other packages
id("software.amazon.smithy.gradle.smithy-jar")
}

dependencies {
val smithyVersion: String by project

// Adds the `@restJson1` protocol trait
api("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
}

// Helps the Smithy IntelliJ plugin identify models
sourceSets {
main {
java {
srcDir("model")
}
}
}
27 changes: 27 additions & 0 deletions smithy-java-examples/quickstart-java/lib/model/common.smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
$version: "2"

namespace com.example

/// An enum describing the types of coffees available
enum CoffeeType {
DRIP
POUR_OVER
LATTE
ESPRESSO
COLD_BREW
}

/// A structure which defines a coffee item which can be ordered
structure CoffeeItem {
/// A type of coffee
@required
type: CoffeeType

@required
description: String
}

/// A list of coffee items
list CoffeeItems {
member: CoffeeItem
}
28 changes: 28 additions & 0 deletions smithy-java-examples/quickstart-java/lib/model/main.smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
$version: "2"

namespace com.example

use aws.protocols#restJson1

/// Allows users to retrieve a menu, create a coffee order, and
/// and to view the status of their orders
@title("Coffee Shop Service")
@restJson1
service CoffeeShop {
version: "2024-08-23"
operations: [
GetMenu
]
resources: [
Order
]
}

/// Retrieve the menu
@http(method: "GET", uri: "/menu")
@readonly
operation GetMenu {
output := {
items: CoffeeItems
}
}
83 changes: 83 additions & 0 deletions smithy-java-examples/quickstart-java/lib/model/order.smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
$version: "2.0"

namespace com.example

/// An Order resource, which has an id and describes an order by the type of coffee
/// and the order's status
resource Order {
identifiers: {
id: Uuid
}
properties: {
coffeeType: CoffeeType
status: OrderStatus
}
read: GetOrder
create: CreateOrder
}

/// Create an order
@idempotent
@http(method: "POST", uri: "/order")
operation CreateOrder {
input := for Order {
@required
$coffeeType
}

output := for Order {
@required
$id

@required
$coffeeType

@required
$status
}
}

/// Retrieve an order
@readonly
@http(method: "GET", uri: "/order/{id}")
operation GetOrder {
input := for Order {
@httpLabel
@required
$id
}

output := for Order {
@required
$id

@required
$coffeeType

@required
$status
}

errors: [
OrderNotFound
]
}

/// An error indicating an order could not be found
@httpError(404)
@error("client")
structure OrderNotFound {
message: String
orderId: Uuid
}

/// An identifier to describe a unique order
@length(min: 1, max: 128)
@pattern("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
string Uuid

/// An enum describing the status of an order
enum OrderStatus {
IN_PROGRESS
COMPLETED
}
3 changes: 3 additions & 0 deletions smithy-java-examples/quickstart-java/lib/smithy-build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"version": "1.0"
}
Loading
Loading