Skip to content

Java Client "Missing required service schema" error #662

Open
@djordjijeK

Description

@djordjijeK

Hi,

I have the following setup:

Gradle smithy module:

// src/main/smithy
$version: "2"

namespace krivokapic.djordjije.smithy.metrics.model

use aws.protocols#restJson1

@documentation("This service models a simple RESTful API for metric ingestion and retrieval.")
@restJson1
service MetricsService {
    version: "2025-04-20"
    operations: [
        PutMetric
    ]
}

@documentation("Write a new metric.")
@http(method: "POST", uri: "/metric")
operation PutMetric {
    input: PutMetricInput
    output: PutMetricOutput
    errors: [
        ValidationError
    ]
}

@documentation("Input for PutMetric operation.")
structure PutMetricInput {
    @required
    source: String

    @required
    metric: Metric
}

@documentation("Output for PutMetric operation.")
structure PutMetricOutput {
    @required
    metric: Metric

    @required
    timestamp: Timestamp
}

@documentation("Structure representing a metric.")
structure Metric {
    @required
    metricName: String

    instanceId: String

    @required
    value: MetricValue

    @required
    unit: MetricUnit
}

union MetricValue {
    intValue: Integer
    doubleValue: Double
    stringValue: String
}

enum MetricUnit {
    NONE
    BYTES
    COUNT
    PERCENT
    MILLISECONDS
}
// smithy-build.json
{
    "version": "1.0",
    "outputDirectory": "build/smithy"
}
// build.gradle.kts
plugins {
    id("java-library")
    id("software.amazon.smithy.gradle.smithy-jar").version("1.2.0")
}


repositories {
    mavenCentral()
}


dependencies {
    implementation("software.amazon.smithy:smithy-model:1.56.0")
    implementation("software.amazon.smithy:smithy-aws-traits:1.56.0")
}


tasks.named("compileJava") {
    dependsOn("smithyBuild")
}

I am trying to generate a Java client with the following configuration (second Gradle module):

// smithy-build.json
{
    "version": "1.0",
    "outputDirectory": "build/smithy",
    "plugins": {
        "java-client-codegen": {
            "service": "krivokapic.djordjije.smithy.metrics.model#MetricsService",
            "namespace": "krivokapic.djordjije.smithy.metrics.client",
            "protocol": "aws.protocols#restJson1"
        }
    }
}
plugins {
    id("application")
    id("software.amazon.smithy.gradle.smithy-jar").version("1.2.0")
}


repositories {
    mavenCentral()
}


dependencies {
    smithyBuild("software.amazon.smithy.java:plugins:0.0.2")

    implementation(project(":smithy"))
    implementation("software.amazon.smithy.java:client-core:0.0.2")
    implementation("software.amazon.smithy.java:aws-client-restjson:0.0.2")
}


afterEvaluate {
    val clientPath = smithy.getPluginProjectionPath(smithy.sourceProjection.get(), "java-client-codegen")

    sourceSets {
        main {
            java {
                srcDir(clientPath)
            }
        }
    }
}


tasks.named("compileJava") {
    dependsOn("smithyBuild")
}

I get the generated code and this is what I am trying to execute:

        MetricsServiceClient metricsServiceClient = MetricsServiceClient.builder()
            .endpointResolver(EndpointResolver.staticHost("http://localhost:8080"))
            .build();

        PutMetricOutput metric = metricsServiceClient.putMetric(PutMetricInput.builder()
            .source("SOURCE")
            .metric(Metric.builder()
                .metricName("NAME")
                .instanceId("INSTANCE")
                .value(MetricValue.builder().intValue(10).build())
                .unit(MetricUnit.COUNT)
                .build())
            .build());

I am getting the following error:

Exception in thread "main" java.lang.NullPointerException: Missing required service schema
	at java.base/java.util.Objects.requireNonNull(Objects.java:259)
	at software.amazon.smithy.java.client.core.ClientConfig.<init>(ClientConfig.java:91)
	at software.amazon.smithy.java.client.core.ClientConfig$Builder.build(ClientConfig.java:569)
	at software.amazon.smithy.java.client.core.Client.<init>(Client.java:49)
	at krivokapic.djordjije.smithy.metrics.client.client.MetricsServiceClientImpl.<init>(MetricsServiceClientImpl.java:33)
	at krivokapic.djordjije.smithy.metrics.client.client.MetricsServiceClient$Builder.build(MetricsServiceClient.java:78)
	at krivokapic.djordjije.MetricsClientMain.main(MetricsClientMain.java:17)

Looking at the generated code I have the following:


package krivokapic.djordjije.smithy.metrics.client.model;

import software.amazon.smithy.java.core.schema.ApiService;
import software.amazon.smithy.java.core.schema.Schema;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.utils.SmithyGenerated;

/**
 * Service API schema
 */
@SmithyGenerated
public final class MetricsServiceApiService implements ApiService {
    private static final MetricsServiceApiService $INSTANCE = new MetricsServiceApiService();
    private static final Schema $SCHEMA = Schema.createService(ShapeId.from("krivokapic.djordjije.smithy.metrics.model#MetricsService"));

    /**
     * Get an instance of this {@code ApiService}.
     *
     * @return An instance of this class.
     */
    public static MetricsServiceApiService instance() {
        return $INSTANCE;
    }

    private MetricsServiceApiService() {}

    @Override
    public Schema schema() {
        return $SCHEMA;
    }
}

But this ApiService is never populated in the Config object. As a sanity check, I generated from the CLI examples from your repository e.g. https://github.com/smithy-lang/smithy-java/blob/main/examples/end-to-end/README.md and I get the exact same problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions