Skip to content

Iceberg REST Phase 1 [2/3]: Controller, serde, and exception handling#499

Open
cbb330 wants to merge 3 commits intolinkedin:mainfrom
cbb330:chbush/iceberg-rest-2-controller
Open

Iceberg REST Phase 1 [2/3]: Controller, serde, and exception handling#499
cbb330 wants to merge 3 commits intolinkedin:mainfrom
cbb330:chbush/iceberg-rest-2-controller

Conversation

@cbb330
Copy link
Collaborator

@cbb330 cbb330 commented Mar 11, 2026

Summary

Part 2 of 3 for Iceberg REST Catalog support. Implements the read-only Iceberg REST surface on top of the generated OpenAPI interfaces from #498.

Changes

  • Client-facing API Changes
  • Internal API Changes
  • Bug Fixes
  • New Features
  • Performance Improvements
  • Code Style
  • Refactoring
  • Documentation
  • Tests

Client-facing API Changes

Adds read-only Iceberg REST Catalog endpoints via IcebergRestCatalogController:

  • GET /v1/config — returns prefix override (iceberg) for route isolation
  • GET /v1/iceberg/namespaces/{namespace}/tables — list tables
  • GET /v1/iceberg/namespaces/{namespace}/tables/{table} — load table metadata
  • HEAD /v1/iceberg/namespaces/{namespace}/tables/{table} — check table existence

All unimplemented endpoints (write, namespace, views, etc.) return 501 via generated defaults.

Internal API Changes

Serialization:

  • IcebergRestHttpMessageConverter — custom AbstractHttpMessageConverter<RESTResponse> using Iceberg's RESTSerializers (kebab-case JSON) without interfering with existing Jackson converters
  • IcebergRestSerde — ObjectMapper configured with Iceberg serializers and kebab-case
  • IcebergRestSerdeConfig — registers converter via WebMvcConfigurer.extendMessageConverters

Error handling:

  • IcebergRestExceptionHandler — scoped @RestControllerAdvice returning Iceberg ErrorResponse format (no stack traces exposed)

New Features

  • TablesService.searchTables(databaseId, actingPrincipal) overload for auth-checked table listing

Review guidance

This PR's new files (316 lines across 7 files):

  • IcebergRestCatalogController.java (138 lines)
  • IcebergRestExceptionHandler.java (64 lines)
  • IcebergRestHttpMessageConverter.java (45 lines)
  • IcebergRestSerde.java (33 lines)
  • IcebergRestSerdeConfig.java (20 lines)
  • TablesService.java (+9 lines)
  • TablesServiceImpl.java (+7 lines)

The diff against main also includes #498's files — those are reviewed in that PR.

Testing Done

  • Manually Tested on local docker setup. Please include commands ran, and their output.
  • Added new tests for the changes made.
  • Updated existing tests to reflect the changes made.
  • No tests added or updated. Please explain why. If unsure, please feel free to ask for help.

Tests are in PR 3/3. This PR adds the implementation; 27 tests covering all endpoints are in the next PR.

Additional Information

  • Breaking Changes
  • Deprecations
  • Large PR broken into smaller PRs, and PR plan linked in the description.

PR Stack (merge in order)

  1. Iceberg REST Phase 1 [1/3]: OpenAPI spec and codegen infrastructure #498 — OpenAPI spec and codegen infrastructure
  2. Iceberg REST Phase 1 [2/3]: Controller, serde, and exception handling #499 — Controller, serde, and exception handling ← you are here
  3. Iceberg REST Phase 1 [3/3]: Tests and CI #500 — Tests and CI

Vendor the upstream Apache Iceberg REST OpenAPI spec (v1.10) and wire
Polaris-aligned codegen into the services/tables Gradle build:

- spec/iceberg-rest-catalog-open-api.yaml: upstream spec as source of truth
- Gradle tasks: setUpOpenApiCliForIcebergRest, validateIcebergRestOpenApiSpec,
  generateIcebergRestOpenApiServer with importMappings/typeMappings to map
  spec schemas to real Iceberg library types (no model generation)
- Post-processing for Iceberg 1.10-only types mapped to Object (compatibility
  with our 1.5.2 fork)
- compileJava depends on codegen; check depends on spec validation
- jackson-databind-nullable dependency for generated code
- Strip non-upstream comments (CODE_COPIED_TO_POLARIS, version marker) so
  the vendored spec is byte-for-byte identical to apache-iceberg-1.10.0
- Add verifyIcebergRestSpecSync Gradle task that downloads the upstream spec
  from the pinned tag and fails if it differs from the vendored copy
- Wire verifyIcebergRestSpecSync into the check task so CI catches drift
@cbb330 cbb330 force-pushed the chbush/iceberg-rest-2-controller branch from 38ce9b7 to 85b9ba0 Compare March 11, 2026 23:23
Implement the read-only Iceberg REST Catalog surface on top of the
generated OpenAPI interfaces from PR1:

Controller (IcebergRestCatalogController):
- Implements CatalogApiApi + ConfigurationApiApi generated interfaces
- GET /v1/config returns prefix override for route isolation
- GET /v1/{prefix}/namespaces/{ns}/tables lists tables via TablesService
- GET /v1/{prefix}/namespaces/{ns}/tables/{t} loads table via CatalogHandlers
- HEAD /v1/{prefix}/namespaces/{ns}/tables/{t} checks table existence
- All unimplemented endpoints return 501 via generated defaults

Serialization:
- IcebergRestHttpMessageConverter for Iceberg REST types (kebab-case JSON)
- IcebergRestSerde with Iceberg RESTSerializers + kebab-case ObjectMapper
- IcebergRestSerdeConfig registers converter without affecting existing Jackson

Error handling:
- IcebergRestExceptionHandler scoped to controller, returns Iceberg ErrorResponse

Service:
- TablesService.searchTables(databaseId, actingPrincipal) overload for auth
@cbb330 cbb330 force-pushed the chbush/iceberg-rest-2-controller branch from 85b9ba0 to c2161a8 Compare March 11, 2026 23:38
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.

1 participant