Skip to content

Translate paginators on the Smithy path - #7463

Merged
Fred1155 merged 1 commit into
feature/master/smithy-migrationfrom
bole/smithy_paginators
Oct 30, 2026
Merged

Fred1155 merged 1 commit into
feature/master/smithy-migrationfrom
bole/smithy_paginators

Conversation

@Fred1155

@Fred1155 Fred1155 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Motivation and Context

For now on the Smithy path, the step that builds the intermediate model passed an empty paginator map and never marked an operation as paginated. So a client generated from a Smithy model had no paginator classes (such as ListThingsIterable and ListThingsPublisher) and no listThingsPaginator(...) client methods.

This PR fills that gap. Smithy describes pagination with the @paginated trait on an operation, for example:

@paginated(inputToken: "nextToken", outputToken: "nextToken", items: "things", pageSize: "maxResults")
operation ListThings { ... }

@paginated covers most paginators, but not everything paginators-1.json can say. In paginators-1.json:

  • Tokens: an operation can list several input and output tokens. S3 ListObjectVersions uses KeyMarker and VersionIdMarker.
  • Stop condition: an operation can stop on a boolean field (more_results, such as IAM's IsTruncated) rather than on a missing token.
  • Result keys: an operation can list several result keys, each of which becomes an item method on the paginator class. CloudWatch DescribeAlarms returns MetricAlarms, CompositeAlarms, and LogAlarms.

@paginated allows one token each way, no stop field, and one items path. For those paginators, this PR adds a codegen trait, software.amazon.awssdk.codegen#paginatorOverride. It carries the paginators-1.json fields on the operation, so the generated paginator stays the same as on the C2J path. It sits alongside the existing Java-only codegen traits and is applied through smithy-build.json, so the service's model.json is not edited. With skip: true, the trait generates no paginator, for an operation that has @paginated but no paginator on the C2J path. We can modify this in the future.

Modifications

  1. paginatorOverride trait: the definition in aws-sdk-java-codegen-traits.smithy and the class PaginatorOverrideTrait, registered as a TraitService.
    • The trait is either skip: true alone, or non-empty inputToken and outputToken lists, plus optional resultKey, moreResults, and limitKey.
    • Any other shape fails when the trait is loaded.
  2. AddSmithyPaginators: builds the paginator map, keyed by operation name as in paginators-1.json.
    • An operation's paginatorOverride wins.
    • Otherwise @paginated is translated: inputToken and outputToken become single-element lists, items becomes resultKey, and pageSize becomes limitKey.
    • A service-level @paginated fills in members the operation leaves out, as Smithy's PaginatedIndex does.
  3. SmithyIntermediateModelBuilder:
    • Passes the paginator map into the intermediate model.
    • Marks an operation as paginated with the same rule the C2J path uses: a paginator exists and has both tokens. The client methods follow this flag and the paginator classes follow the map, so the two stay in agreement.
    • Drops paginators of deprecatedOperations, as the C2J path does.

Not in this PR:

  • Waiters: they follow in a separate PR.
  • Writing the overrides: generating paginatorOverride entries from a service's paginators-1.json into smithy-build.json belongs with the tool that generates smithy-build.json from customization.config. Until then, a smithy-build.json without the overrides falls back to translating @paginated.

Screenshots (if appropriate)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the CONTRIBUTING document
  • Local run of mvn install succeeds
  • My code follows the code style of this project
  • My change requires a change to the Javadoc documentation
  • I have updated the Javadoc documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed
  • I have added a changelog entry. Adding a new entry must be accomplished by running the scripts/new-change script and following the instructions. Commit the new file created by the script in .changes/next-release with your changes.
  • My change is to implement 1.11 parity feature and I have updated LaunchChangelog

License

  • I confirm that this pull request can be released under the Apache 2 license

The Smithy builder passed an empty paginator map and never set
isPaginated, so no paginator classes or xxxPaginator() client methods
were generated from a Smithy model.

AddSmithyPaginators builds the map from each operation's @paginated
trait, with the service's @paginated filling the members the operation
leaves out, as Smithy's PaginatedIndex does. A new codegen trait,
paginatorOverride, replaces that translation for paginators @paginated
cannot express (several tokens, moreResults, several result keys), or
with skip, drops the paginator. The builder sets isPaginated with the
rule C2J's AddOperations uses, so the client methods and paginator
classes agree, and removes paginators of deprecatedOperations as the
C2J builder does.
@Fred1155
Fred1155 requested a review from a team as a code owner October 19, 2026 21:33
if (!skip && (isNullOrEmpty(inputToken) || isNullOrEmpty(outputToken))) {
throw new ExpectationNotMetException(
ID + " needs inputToken and outputToken unless skip is true. Remove the trait to use @paginated.", node);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this validation also require inputToken and outputToken to have the same size? The paginator generator pairs them by index, so mismatched lists could cause generation failures or unused tokens ?

inputToken: PaginatorMemberPaths
outputToken: PaginatorMemberPaths
resultKey: PaginatorMemberPaths
moreResults: String

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should moreResults be validated to reference a Boolean member? Generated paginator code calls booleanValue() on its getter, while current validation only checks that the member exists

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! Though this and the above behavior are all c2j behavior today. And no model in our current repo violates that. if we are going to add it, we probably will add this for both smithy path and c2j path. I can take a note on that.

@Fred1155
Fred1155 merged commit 6c5d151 into feature/master/smithy-migration Oct 30, 2026
4 of 5 checks passed
@github-actions

Copy link
Copy Markdown

This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Oct 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants