Fixes #31214: fluent API for glossary relation types, removal, and graph - #31215
Fixes #31214: fluent API for glossary relation types, removal, and graph#31215harshach wants to merge 1 commit into
Conversation
…l/graph
The Java fluent layer could set a relation type but not discover one:
GlossaryTerms.find(id).relateTo(x).as("prescribes") existed, while listing
the configured types, removing a relation, and reading the relation graph
were reachable only by dropping to the service layer. That asymmetry is
sharper now that #31070 makes the relation-type read available to non-admins
— the one call they gained is the one the fluent layer skipped.
Adds GlossaryRelationTypes (list/names/inCategory, find/exists, settings,
usage, and an admin-only define) plus unrelateFrom(...) and relations() on
the GlossaryTerms finder. Identifier resolution shared by all three builders
moves to one place instead of being copied per builder.
Python needs no equivalent: metadata.sdk already exposes relation reads and
writes at the same level as the rest of its API.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
| public static Optional<GlossaryTermRelationType> find(String name) { | ||
| return list().fetch().stream().filter(type -> matchesName(type, name)).findFirst(); | ||
| } | ||
|
|
||
| public static boolean exists(String name) { | ||
| return find(name).isPresent(); | ||
| } |
There was a problem hiding this comment.
💡 Performance: find()/exists() each trigger a fresh HTTP fetch of all relation types
GlossaryRelationTypes.find(name) and exists(name) both call list().fetch(), which issues a full settings().glossaryRelationTypes() HTTP round trip every invocation. The documented pattern (e.g. if (exists(x)) { ... find(x) ... }, or calling find twice) causes several redundant network calls for what is a single lookup. Consider fetching once and reusing the list, or having exists() reuse a cached fetch, since the endpoint returns the whole vocabulary in one document.
Was this helpful? React with 👍 / 👎
Code Review 👍 Approved with suggestions 0 resolved / 1 findingsAdds a Java fluent API for glossary relation types, removal, and graphs with comprehensive test coverage. Consider avoiding fresh HTTP fetches for each find() or exists() call in GlossaryRelationTypes. 💡 Performance: find()/exists() each trigger a fresh HTTP fetch of all relation types📄 openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/GlossaryRelationTypes.java:89-95 GlossaryRelationTypes.find(name) and exists(name) both call list().fetch(), which issues a full settings().glossaryRelationTypes() HTTP round trip every invocation. The documented pattern (e.g. 🤖 Prompt for agentsOptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |
There was a problem hiding this comment.
Pull request overview
This PR extends the Java SDK fluent layer (org.openmetadata.sdk.fluent) to cover the full glossary term relation surface: discovering configured relation types, removing relations, and fetching a term’s relations graph—without dropping down to the service-layer clients.
Changes:
- Added
GlossaryRelationTypesfluent resource to list/filter/find/define glossary relation types, fetch full settings, and retrieve per-type usage. - Extended
GlossaryTermsfluent finder withunrelateFrom(...)andrelations()builders, and centralized UUID/FQN identifier resolution helpers. - Added unit tests validating the new fluent calls delegate correctly to
SystemSettingsService/GlossaryTermService, including defaults and “remove all types” behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/GlossaryRelationTypes.java | New fluent resource for glossary relation type vocabulary (list/filter/find/settings/usage/define). |
| openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/GlossaryTerms.java | Adds fluent builders for removing relations and fetching relation graphs; shares identifier resolution. |
| openmetadata-sdk/src/main/java/org/openmetadata/sdk/OM.java | Registers GlossaryRelationTypes in OM.init(client) for standard fluent initialization. |
| openmetadata-sdk/src/test/java/org/openmetadata/sdk/fluent/GlossaryRelationsFluentAPITest.java | Unit coverage for new fluent surfaces and delegation/default semantics. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
✅ Playwright Results — workflow succeededValidated commit ✅ 550 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 50m 38s ⏱️ Max setup 3m 41s · max shard execution 17m 23s · max shard-job elapsed before upload 22m 1s · reporting 4s 🌐 200.06 requests/attempt · 2.83 app boots/UI scenario · 2.01% common-shard skew Optimization targets still in progress:
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
Describe your changes:
Fixes #31214
The Java fluent layer could set a glossary relation type but not discover one —
GlossaryTerms.find(id).relateTo(x).as("prescribes")existed, while listing the configured types, removing a relation, and reading the relation graph were reachable only by dropping to the service layer (client.settings()/client.glossaryTerms()). I added the missing half because #31070 makes the relation-type read available to non-admins, so the one call those users just gained is the one the fluent layer skipped.Python needs no equivalent —
metadata.sdkalready exposes relation reads and writes at the same level as the rest of its API (Settings.glossary_relation_types(),GlossaryTerms.add_relation / remove_relation / relations_graph / relation_type_usage).Type of change:
High-level design:
N/A — small change (4 files, no new HTTP surface).
Every addition delegates to service-layer methods that already exist; no new endpoints, request shapes, or error handling.
GlossaryRelationTypesis a new fluent class because relation types are a distinct resource fromGlossaryTermsand the fluent package is one class per resource (SearchAPI,LineageAPIare the precedent for non-entity fluent classes). Category filtering is client-side, since the settings endpoint returns the whole vocabulary in one document. The identifier-resolution helpers (UUID-or-FQN) thatGlossaryTermRelatorheld privately are now shared statics, so the three builders don't carry three copies.New surface
Tests:
Use cases covered
relateTo(...).as(...)Unit tests
openmetadata-sdk/src/test/java/org/openmetadata/sdk/fluent/GlossaryRelationsFluentAPITest.java(11 tests).SystemSettingsServiceandGlossaryTermServiceare mocked at the service boundary, so each test asserts the call the fluent builder actually makes — including that an unset.as(...)passesnull(remove all types) and thatrelations()defaults to depth 1 with no type filter.mvn test -pl openmetadata-sdk -Dtest=GlossaryRelationsFluentAPITest→Tests run: 11, Failures: 0, Errors: 0mvn test -pl openmetadata-sdk→Tests run: 244, Failures: 0, Errors: 0(no regression from theGlossaryTerms/OMedits)Backend integration tests
GlossaryTermRelationsIT/GlossaryTermRelationSettingsIT.Ingestion integration tests
Playwright (UI) tests
Manual testing performed
None against a live server — this is a client-side wrapper over endpoints that already have server-side IT coverage, and the mock tests pin the exact URL, method, and arguments each builder produces. To verify by hand against a running instance:
OM.init(client)(registers the new fluent class).GlossaryRelationTypes.list().names()→ the configured relation types; works as a non-admin once Non-admin users cannot fetch full glossary term relation list when adding related terms #31070 is in.GlossaryTerms.find(a).relateTo(b).as(names.get(0)).apply(), thenGlossaryTerms.find(a).relations().fetch()→ the new edge appears.GlossaryTerms.find(a).unrelateFrom(b).apply()→ edge gone.UI screen recording / screenshots:
Not applicable — no UI changes.
Checklist:
Fixes <issue-number>: <short explanation>Fixes #<issue-number>above.🤖 Generated with Claude Code