Skip to content

Accept storage type names case-insensitively in the management API#5036

Open
Zhuoxi2000 wants to merge 1 commit into
apache:mainfrom
Zhuoxi2000:storage-type-case-insensitive
Open

Accept storage type names case-insensitively in the management API#5036
Zhuoxi2000 wants to merge 1 commit into
apache:mainfrom
Zhuoxi2000:storage-type-case-insensitive

Conversation

@Zhuoxi2000

Copy link
Copy Markdown

Fixes #996

Problem

"storageType": "s3" is rejected while "S3" works: both the Jackson
subtype discriminator on StorageConfigInfo and the generated enum match
case-sensitively.

Changes

  • spec/polaris-management-service.yml: the discriminator mapping now lists
    lowercase aliases (s3, gcs, azure, file), so subtype resolution
    accepts them and the published spec documents both spellings.
  • server-templates/enumClass.mustache (new override, based on
    openapi-generator's JavaJaxRS/resteasy template): generated enums gain a
    case-insensitive @JsonCreator fromValue, covering the visible
    discriminator property and all other request enums consistently.

Responses always emit the canonical uppercase value; unknown values are
still rejected.

Testing

Extended CatalogSerializationTest: all four storage types in both
spellings resolve to the correct subclass; lowercase input round-trips to
the canonical enum and serializes back as "S3"; unknown values still
throw.

Note for reviewers

@JsonSubTypes.Type(names = {...}) via the generator's lambda.lowercase
was considered first, but that lambda escapes reserved words
(FILE_file), so the explicit spec mapping is safer and
self-documenting. The Python client picks up the aliases on its next
regeneration; existing clients are unaffected.

Checklist

  • 🛡️ Don't disclose security issues! (contact security@apache.org)
  • 🔗 Clearly explained why the changes are needed, or linked related issues: Fixes Using case insensitive storage type names #996
  • 🧪 Added/updated tests with good coverage, or manually tested (and explained how)
  • 💡 Added comments for complex logic
  • 🧾 Updated CHANGELOG.md (if needed)
  • 📚 Updated documentation in site/content/in-dev/unreleased (if needed)

@dimas-b dimas-b left a comment

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.

Thanks for your contribution, @Zhuoxi2000 !

Comment thread spec/polaris-management-service.yml Outdated
FILE: "#/components/schemas/FileStorageConfigInfo"
# Lowercase aliases: the server accepts storage type names
# case-insensitively (https://github.com/apache/polaris/issues/996)
s3: "#/components/schemas/AwsStorageConfigInfo"

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.

I'm not sure duplicating discriminator values in the spec is a sustainable impl. approach 🤔

Creating a catalog with "storageType": "s3" failed while "S3"
succeeded. The storage config discriminator is both a Jackson
polymorphic type id and a visible enum property, and both matched
case-sensitively.

Rather than enumerate lowercase aliases per type (which would have to
be repeated in the spec for every discriminator and every enum), this
enables two standard Jackson features on the shared ObjectMapper:

- ACCEPT_CASE_INSENSITIVE_VALUES — case-insensitive polymorphic type
  id (subtype discriminator) matching, and
- ACCEPT_CASE_INSENSITIVE_ENUMS — case-insensitive enum value matching
  (needed as well because the discriminator is declared visible=true
  and is deserialized into the enum after subtype dispatch).

Both are required for the storage config case; together they make the
whole API lenient about input case without any per-type wiring, so new
enums and discriminators are covered automatically. Only input is
relaxed: serialization still emits the canonical value and unknown
values are still rejected.

Fixes apache#996
@Zhuoxi2000
Zhuoxi2000 force-pushed the storage-type-case-insensitive branch from 72c5174 to 63bc479 Compare July 14, 2026 03:52
@Zhuoxi2000

Copy link
Copy Markdown
Author

Thanks for your contribution, @Zhuoxi2000 !

Good point thanks for calling this out. @dimas-b

I reworked the change so we don’t need to duplicate aliases in the spec anymore. the shared ObjectMapper now enables case-insensitive handling for both the subtype discriminator and the enum value. We need both because the storage discriminator is visible = true, so after it’s used for subtype dispatch, it also gets deserialized into StorageTypeEnum which removes the need for any per type wiring in the spec or templates, and new enum / discriminator values should be handled automatically. Input is relaxed, but serialization still emits the canonical value and unknown values are still rejected. I added a test to cover these cases.

One thing to note: because this uses the shared Quarkus ObjectMapper, the behavior applies across the API, including Iceberg REST, rather than only the management API. That seemed like the cleaner tradeoff, but I’m happy to scope it down if you’d prefer.

The PR is now just a small ObjectMapperCustomizer plus a unit test.

@Zhuoxi2000
Zhuoxi2000 requested a review from dimas-b July 14, 2026 03:56
@snazy

snazy commented Jul 14, 2026

Copy link
Copy Markdown
Member

Thanks for your contribution.

I'd recommend to take a look at this discussion about case-sensitivity.

* leniency is uniform across the API rather than special-cased per type — which is what keeps it
* maintainable as new enums and discriminators are added.
*/
@Singleton

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

IIUC, this annotation would make Quarkus finds it on its own and slaps it on the ONE shared ObjectMapper the whole app uses. That means it not only just turn on lowercase for management API, but also turns on for Iceberg REST too, quietly.

IMO, we should it lock it to management API scope.

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.

Yes, we should be careful with the impact of default JSON serializer config changes. We certainly should not automatically apply this to the Iceberg REST API.

Comment thread CHANGELOG.md
- Names containing any of these characters: <code>/\:*?"<>|#+`</code>

### New Features
- Request enums and polymorphic type ids are now accepted case-insensitively — e.g. `"storageType": "s3"` is accepted alongside the canonical `"S3"`, as are all other request enums (catalog `type`, `connectionType`, `authenticationType`, …). Responses always emit the canonical value and unknown values are still rejected.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: do we have connectionType and authenticationType exercised as well?

@Override
public void customize(ObjectMapper objectMapper) {
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES, true);
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);

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.

Could you also reply to the related dev thread mentioning this PR for the sake of community awareness?

https://lists.apache.org/thread/jx2dn3fztn3t7tnnz8q7tg9l3v0orksy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using case insensitive storage type names

4 participants