Skip to content

Adding implementation dependency changes behaviour of plugin #162

@timocov

Description

@timocov

Hello there,

Description

The use case where I'm running into this issue is the following - I have a repo with 2 modules (model and service). The model module contains of all of smithy files, the service is suppose to be a server implementation of the model. The plugin works fine if I set up everything according to the guides (i.e. dependency models are added via smithyBuild configuration, all smithy-cli plugins are added via smithyBuild configuration), but once I add any dependency to implementation configuration, the build starts failing because smithy can't find the model.

Here is the repro example: bug-smithy.zip

Steps to reproduce:

  1. unzip the file
  2. cd into the folder
  3. ./gradlew build - the build should succeeded
  4. uncomment implementation("software.amazon.smithy.java:core:+") line in service/build.gradle.kts
  5. ./gradlew build - the build fails with
Projection source failed: software.amazon.smithy.model.node.ExpectationNotMetException: Shape not found in model: smithy.example#SampleService
software.amazon.smithy.model.node.ExpectationNotMetException: Shape not found in model: smithy.example#SampleService
	at software.amazon.smithy.model.Model.lambda$expectShape$1(Model.java:702)
	at java.base/java.util.Optional.orElseThrow(Optional.java:403)
	at software.amazon.smithy.model.Model.expectShape(Model.java:702)
	at software.amazon.smithy.model.Model.expectShape(Model.java:719)
	at software.amazon.smithy.codegen.core.directed.CodegenDirector.lambda$flattenPaginationInfoIntoOperations$9(CodegenDirector.java:341)
	at software.amazon.smithy.codegen.core.directed.CodegenDirector.performModelTransforms(CodegenDirector.java:450)
	at software.amazon.smithy.codegen.core.directed.CodegenDirector.run(CodegenDirector.java:379)
	at software.amazon.smithy.java.codegen.server.JavaServerCodegenPlugin.execute(JavaServerCodegenPlugin.java:49)

Investigation

Upon my investigation, it feels like the problem is that here as getModelDiscoveryClasspath we assign runtimeClasspath which then later goes into libClasspath which goes into discoveryClasspath and which later gets checked whether it is empty and it defines the behaviour. This feels a bit weird to me.

Solution

Based on the documentation it feels like adding smithy-cli related dependencies (plugins, models) via smithyBuild configuration is the right way (we don't need to have a model at a runtime of services/clients/etc in most of the cases), and smithyBuild configuration should be used for discovery instead of runtimeClasspath.

Workarounds

There are 2 workarounds for this (at least what I've found):

  1. Adding a model as runtimeOnly dependency as well. It might be an option, but it has unnecessary side-effects that in some cases might prevent from using it.

  2. To create an empty projection (e.g. external) and mark it as a source projection in smithy extension without providing projectionSourceTags:

smithy {
    sourceProjection.set("external")
}

But this feels very counter-intuitive, and it works simply because if you do it this way, then the plugin uses buildClasspath as libClasspath here (which essentially includes everything from smithyBuild). Whilst it seems working, it generates an unnecessary and misleading warning message:

No projection source tags were set for the projection `null`, so the projection will not have any sources in it other than files found in the sources of the package being built.

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