Skip to content

feat(QTDI-3497): jakarta only public api - #1285

Open
undx wants to merge 17 commits into
masterfrom
ouf/QTDI-3497-jakarta-only-public-api
Open

undx wants to merge 17 commits into
masterfrom
ouf/QTDI-3497-jakarta-only-public-api

Conversation

@undx

@undx undx commented Sep 29, 2026

Copy link
Copy Markdown
Member

Requirements

  • Any code change adding any logic MUST be tested through a unit test executed with the default build
  • Any API addition MUST be done with a documentation update if relevant

Why this PR is needed?

What does this PR adds (design/code thoughts)?

AI generated code

https://internal.qlik.dev/general/ways-of-working/code-reviews/#guidelines-for-ai-generated-code

  • [] this PR has been written with the help of GitHub Copilot or another generative AI tool

undx and others added 17 commits September 22, 2026 16:10
Align component-runtime's cxf.version with Studio/connectors (4.1.8).
CXF 4.0+ dropped javax.* support entirely, so this is not a plain
property bump: every module compiled/run against CXF's JAX-RS/CDI
runtime (component-server, vault-client, component-starter-server,
component-tools-webapp, documentation) is migrated from javax.ws.rs /
javax.xml.ws / javax.enterprise / javax.inject / javax.annotation to
the jakarta.* equivalents, and the embedded server stack (Meecrowave,
OpenWebBeans, Johnzon) is bumped to jakarta-compatible releases so it
can boot alongside CXF 4.x.

Key changes:
- Root pom cxf.version 3.6.12 -> 4.1.8; meecrowave/owb/johnzon bumped
  to jakarta-compatible lines; jakarta re-pins added to images/*.
- javax.* -> jakarta.* import migration across component-server,
  vault-client, component-starter-server, component-tools-webapp and
  documentation's REST-doc generator.
- New self-contained jakarta CDI extension in component-server
  (service/jcache/cdi) replacing geronimo-jcache-simple's javax-only
  JSR-107 caching integration, which was a silent no-op under jakarta
  CDI.
- Dual javax/jakarta @JsonbTransient annotations on component-api's
  Schema/Entry and component-runtime-impl's concrete Record/Schema
  implementations, since jakarta johnzon-jsonb 2.1.0 introspects the
  declared interface type rather than concrete overrides.
- SmallRye Config scanning-exclude added to meecrowave.properties
  (component-server, component-starter-server, images/*) to avoid a
  double-registered ConfigProducer CDI bean under CDI 4.x.

The CVE fixed in QTDI-3340 (cxf 3.6.12) remains resolved at 4.1.8; no
new CVE introduced (spot-checked via CI's Trivy scan).

Connectors-se/ee, cloud-components and studio are unaffected: their
cxf 4.1.8 usages are already independently declared and isolated by
per-plugin classloaders, or (Studio TCK-SDK prep-repo) intentionally
still pinned to 3.6.12 to match component-runtime.

Verified: full reactor build (mvn clean install) is BUILD SUCCESS,
2932 tests run / 0 failures / 0 errors. component-server (177 tests),
component-starter-server (47 tests), component-runtime-manager (316
tests) and vault-client (19 tests) suites independently green.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…edge

Repo-specific memory from this ticket's delivery: RAT false-positive on
local ai-commons tooling, documentation module's generated-doc
regeneration side effect, and a -T 1C parallel-build test hang in
component-runtime-manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Builder reflection

createPojoJsonbBuilder reflectively grabbed a private Johnzon-only
MapperBuilder 'builder' field to force setDoCloseOnStreams(true). Since
round0 re-pinned johnzon-core/johnzon-mapper to the jakarta line in
component-server's dependencyManagement, JsonbBuilder.newBuilder() can
now resolve to Yasson's builder impl instead, which has no such field,
turning a harmless optimization into a fatal NoSuchFieldException /
IllegalStateException.

Guard the reflection behind an instanceof check against Johnzon's
JohnzonBuilder and skip the optimization (with a debug log) when a
different JSON-B provider is active instead of rethrowing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The beam-sample-test surefire execution (BeamActionSerializationTest +
BeamComponentResourceImplTest) had no reuseForks override, defaulting
to reuseForks=true, so both test classes shared one JVM fork/one
ComponentManager singleton — causing an intermittent
'Container the-test-component already exists' collision on CI.

Add reuseForks=false to the beam-sample-test execution, matching the
sibling default-test execution which already carries the same fix for
the identical class of collision.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two module-knowledge.md files created (component-runtime-manager,
component-server) documenting this round's root-caused findings:
- JSON-B provider resolution assumption in
  DefaultServiceProvider.createPojoJsonbBuilder (Johnzon-only reflection).
- reuseForks=false fixes for ComponentManager/Meecrowave container-id
  collisions must be applied per surefire execution, not just once per pom.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
component-tools-webapp, documentation, images/component-server-image
and images/component-starter-server-image each re-pin the jakarta
container libraries (Meecrowave/Tomcat/OpenWebBeans) for their own
dependencyManagement, but left the runtime Johnzon graph on the shared
root javax ${johnzon.version}. Add the jakarta johnzon-core,
johnzon-mapper and johnzon-jsonb pins to each module's
dependencyManagement, mirroring component-server/pom.xml, so the
jakarta.json.spi.JsonProvider lookup used by jakarta.json.bind.Jsonb
resolves consistently across all four modules.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ueParameter

getValueParameter never advanced idx past the first outer-loop
iteration, so for a JSR-107 method whose @CacheValue annotation sits on
any parameter other than the first, MethodMeta.valueIndex incorrectly
stayed at 0. Increment idx once per outer-loop iteration so the
returned index matches the actual annotated parameter's position.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…fterInvocation flag

CacheRemoveAllInterceptor read the co-located @cACHEpUT's
afterInvocation flag instead of @CacheRemoveAll's own, so a method
combining both annotations would evict at the wrong time relative to
invocation, and a standalone @CacheRemoveAll with afterInvocation=true
would evict before invocation instead of after — leaving the cache
uncleared when the method fails. Read
methodMeta.getCacheRemoveAll().afterInvocation() instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add JakartaJAXRSClientTest, covering #action's request path/query
params, payload conversion, response mapping, and #close()'s
delegate-ownership behavior, using a local embedded
com.sun.net.httpserver.HttpServer per java-testing-conventions.md
(no live external services in unit tests).

Writing this test surfaced that #action itself was broken: CXF's
JAX-RS client does not auto-discover a JSON-B MessageBodyReader/Writer
for a plain Map<String, Object> payload, so every call failed at
runtime with 'No message body writer has been found for class
java.util.HashMap'. Register johnzon-jsonb's bundled
org.apache.johnzon.jaxrs.jsonb.jaxrs.JsonbJaxrsProvider on the client
in the shared 3-arg constructor (used by both JakartaJAXRSClient's own
newClient() factory and LazyClient's injected client), and make the
johnzon-jsonb dependency explicit rather than relying on it arriving
transitively via component-server, since this class now imports one of
its classes directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… JAX-RS JSON-B provider gotcha

Module-specific memory finding from Round 2 PR-review-fix pass: CXF's JAX-RS
client does not auto-discover a JSON-B provider for arbitrary payloads and
must have org.apache.johnzon.jaxrs.jsonb.jaxrs.JsonbJaxrsProvider registered
explicitly. Documented per manage-memory skill (ungated, module-specific
scope) so future work in this module doesn't rediscover the same runtime
bug pattern.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…s for item #8

Dev supplied real SonarQube credentials to un-block item #8 (previously a
manual-audit fallback due to 401/missing SONAR_TOKEN). Queried the Sonar Web
API directly against PR #1283's already-current CI analysis (authoritative,
newer than the local sandbox's own network-restricted mvn sonar:sonar
attempt) and reviewed all 53 new-code issues, all confined to the brand-new
jcache/cdi package (self-contained CDI extension replacing
geronimo-jcache-simple, ported/adapted from upstream, see file-level NOTE
comments).

Fixed the genuine, surgical issues:
- S2293 (10x): diamond operator on generic constructor calls.
- S6202 (8x): replace X.class.isInstance(o)/X.class.cast(o) with instanceof/
  cast expressions in the 4 interceptors' completion-stage/exception
  handling.
- S1066 (6x): merge nested "if (afterInvocation) { if (isIncluded) ... }"
  into a single condition (3 interceptors x 2 sites).
- S3824 + partial S3776: CDIJCacheHelper#findMeta's manual double-checked
  locking replaced with ConcurrentHashMap#computeIfAbsent (also simpler and
  still correct/thread-safe).
- S3776 (5x, cognitive complexity 19-30 -> under 15): extracted the
  completion-stage failure handling and catch-block cache-eviction/caching
  logic into small private helper methods in all 4 interceptors; extracted
  CDIJCacheHelper#keyParameterIndexes's two nested-loop scans into their own
  methods.
- S1117 (3x): renamed local variables/parameters that were shadowing a
  field, in CDIJCacheHelper and CacheInvocationContextImpl.
- S2093 (1x): converted a JakartaJAXRSClientTest test method's manual
  try/finally Client cleanup to try-with-resources (pure resource-management
  equivalence; no assertion touched — reviewed against the test-modification
  guardrail, not gated as it doesn't loosen/remove coverage).

Documented (not changed) the issues that are genuine design decisions or
Sonar false positives rather than defects, inline where it adds context and
in the round summary:
- S1181/S112 (Throwable catch/declare, 4x each): deliberate, already
  commented in each interceptor — a generic JSR-107 interceptor must
  observe and rethrow whatever the intercepted method throws, of any type.
- S3077 (volatile non-primitive field): textbook double-checked-locking lazy
  singleton, `volatile` is sufficient here; now documented inline.
- S107 (23-parameter constructor): already carries an in-code rationale
  (ported field-per-annotation carrier, CHECKSTYLE:OFF) predating this
  round.
- S125 (line 467): Sonar false-positive heuristic match on a plain
  rationale comment, not actual commented-out code.
- S1135 (3x, TODO comments): verbatim open design questions inherited from
  upstream geronimo-jcache-simple; resolving them is feature work outside
  this migration's scope.

Verified: component-server 177/0/0/1 (same pass rate as prior rounds),
component-tools-webapp 2/0/0/0, spotless:check/checkstyle:check clean on
both modules.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…che/cdi test coverage

Round 3 follow-up on the CXF 4.x/jakarta migration, addressing the 19 Sonar
"new code" issues reported on PR #1283 (all confined to
service/jcache/cdi) and the new-code coverage gap flagged by the quality
gate.

Sonar fixes (19 issues):
- S6201 (x4, genuine fix): replaced instanceof+cast with Java pattern
  matching in the onFailure/onAsyncFailure helpers of
  CacheResultInterceptor, CachePutInterceptor, CacheRemoveInterceptor and
  CacheRemoveAllInterceptor.
- S112/S1181 (x4 each), S3077, S6813, S107, S125, S1135 (x3): documented,
  accepted deviations from a prior round - now actually suppressed via
  @SuppressWarnings("java:Sxxxx") (the convention already used elsewhere
  in this module, e.g. AsyncContextImpl/BulkReadResourceImpl) with the
  existing rationale comments kept in place, so Sonar's issue count
  reflects the accepted state instead of re-flagging them every scan.

Test coverage (service/jcache/cdi, previously ~48.70% new-code coverage):
- Added CDIJCacheHelperTest, CacheResultInterceptorTest,
  CachePutInterceptorTest, CacheRemoveInterceptorTest and
  CacheRemoveAllInterceptorTest, exercising MethodMeta resolution and
  memoization, annotation parsing (@CacheResult/@CachePut/@CacheRemove/
  @CacheRemoveAll), key/value parameter indexing (including a regression
  lock for the round-2 getValueParameter off-by-one fix), CDI-bean-backed
  CacheKeyGenerator/CacheResolverFactory resolution and release(), and
  each interceptor's before/after-invocation timing, exception
  inclusion/exclusion filtering and sync/async failure handling,
  including a regression lock for the round-2 fix making
  CacheRemoveAllInterceptor read its own @CacheRemoveAll.afterInvocation()
  flag.
- Tests run against the real in-memory JSR-107 provider bundled by
  geronimo-jcache-simple (already a compile dependency, no live external
  system involved) instead of mocking JCache itself, for closer-to-
  production coverage of the surrounding CacheInvocationContextImpl,
  CacheKeyInvocationContextImpl and CacheMethodDetailsImpl classes.
- Added mockito-junit-jupiter as an explicit test dependency in
  component-server/pom.xml, excluding its transitive junit-jupiter-api to
  avoid downgrading the reactor-managed version.
- Local JaCoCo measurement after these tests: service/jcache/cdi package
  now at approximately 93.5% line, 91.1% instruction and 80.4% branch
  coverage (aggregate approximately 89% by Sonar's line+condition
  coverage formula), comfortably above the 80% quality gate threshold.
  The authoritative Sonar number will be confirmed on the next CI
  analysis of this PR.

Full component-server test suite: 217 + 3 tests, 0 failures (1 unrelated
pre-existing skip).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- S1130 CDIJCacheHelperTest#mockBean: removed unneeded 'throws Exception'
  (nothing checked-throwing in the body).
- S6068 CDIJCacheHelperTest#mockBean: dropped useless eq(...) wrapping on an
  all-eq getReference() verification, passing arguments directly (also
  removed the now-unused ArgumentMatchers.eq static import).
- S1751 CacheRemoveAllInterceptorTest#isEmpty: replaced the for-each with an
  unconditional first-iteration return by a plain iterator().hasNext() check
  — same semantics, no unconditional-return-in-loop code smell.
- S112 CacheResultInterceptor#lookupCachedResult: accepted deviation
  (rethrows an arbitrary cached Throwable from a prior #cache invocation,
  same generic-JSR-107-interceptor rationale as the other suppressions in
  this package) — suppressed with @SuppressWarnings("java:S112") and an
  inline rationale comment, consistent with the package convention.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
…ntation samples

Round 2's jakarta migration changed 8 connector sample/example files
under documentation/ from javax.* to jakarta.* imports (annotation +
json packages). These samples are compiled and executed through the
still-javax-based component-runtime
(component-runtime-impl LifecycleImpl only recognizes
javax.annotation.PostConstruct/PreDestroy; RecordConverters decodes
javax.json.* types), so the jakarta imports silently broke:
- @PostConstruct/@PreDestroy lifecycle hooks (open()/close()) — never
  invoked due to annotation type mismatch
- JSON values (JsonObject/JsonArray/JsonValue) returned/consumed at
  connector boundaries — incompatible with the javax-based JSON-B
  decoding path

Reverts imports (annotation + json packages only) in:
PersonReader, UserWriter, MockOutput, TableApiClient, MockTableSource,
MockTableMapper, Reject, MockTableService.

The first 5 were flagged by 5 unresolved GitHub review-thread comments
on PR #1283; MockTableMapper/Reject/MockTableService share the exact
same defect and were found by inspection while addressing the flagged
comments. Unrelated to the broader javax->jakarta migration of
component-api tracked separately in QTDI-3497.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…mples vs doc-generator jakarta split

Round 5's fix reverted 8 connector sample files' imports from jakarta.*
back to javax.* because component-runtime is still javax-based. Records
the distinguishing rule (sample code vs. this module's own REST-doc
generator tooling, which correctly uses jakarta) for future jakarta
migration work in this module.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…on line

Collapses the dual javax/jakarta version split for tomcat, meecrowave and
openwebbeans into a single, up-to-date version line shared by the whole
reactor:
- meecrowave.version: 1.2.15/2.0.0 -> 2.1.1 (latest release; 1.2.x is EOL
  upstream, no future javax releases planned)
- tomcat.version: 9.0.121/10.1.45 -> 11.0.26 (latest release)
- owb.version: 2.0.27/4.0.3 -> 4.1.1 (latest release; matches meecrowave
  2.1.1's own bundled/shaded CDI 4.1 API)
- jakarta.enterprise.cdi-api.version: 4.0.1 -> 4.1.0 (must match owb 4.1.x)
- johnzon-jakarta.version: 2.1.0 -> 2.2.0 (latest release; johnzon.version
  1.2.21 left untouched - required to coexist with the jakarta line on
  component-server's own classpath, see PR discussion)

Root cause fixed: component-tools's WebServer (backing the
'mvn talend-component:web' local UI tester goal) was still compiled
against meecrowave-core 1.2.15 (javax), while talend-component-maven-plugin
also pulls in component-tools-webapp/component-server, whose REST/CDI
resources are now jakarta-annotated (this PR's CXF 4.x migration). The
root pom's dependencyManagement silently downgraded meecrowave-core back
to 1.2.15 for any consumer without an explicit jakarta re-pin, so the
'web' goal's embedded server could not recognize any jakarta-annotated
REST/CDI resource (javax.* and jakarta.* annotations are distinct Java
types, no scanning compatibility) - the local web tester was effectively
broken by the migration.

Changes:
- pom.xml: unified version properties (see above), removed the now
  obsolete meecrowave-jakarta/owb-jakarta/tomcat-jakarta twin properties,
  added a missing openwebbeans-impl dependencyManagement pin.
- Removed the now-dead per-module dependencyManagement re-pin blocks that
  existed solely to counteract the old two-line split in:
  component-server, component-starter-server, vault-client,
  component-tools-webapp, documentation, images/component-server-image,
  images/component-starter-server-image.
- talend-component-maven-plugin/pom.xml + ComponentMetadataMojo.java:
  pinned johnzon-jsonb/core/mapper to the jakarta line and swapped javax
  json-bind imports to jakarta (this module needed both javax and jakarta
  json-bind before, only the latter is required now).
- component-tools/WebServer.java: excluded smallrye-config from CDI
  scanning (mirrors component-server's own
  @MeecrowaveConfig(scanningExcludes = "smallrye-config") - without it,
  SmallRye's ConfigProducer gets double-registered under CDI 4.1/OWB 4.1.1,
  causing AmbiguousResolutionException).
- InMemoryResponse.java: implemented the new Servlet 6.1 abstract method
  sendRedirect(String, int, boolean) introduced by Tomcat 11.

Validated via full reactor build, targeted module tests, and an
end-to-end 'mvn talend-component:web' smoke test against a sample
connector confirming REST endpoints (including AdminResource) now
register correctly (HTTP 200 on /api/v1/environment).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Removes javax/jakarta dual support across the whole component-runtime
reactor, retaining jakarta.* annotations/APIs only, since the project
now targets JDK >= 17 exclusively.

Highlights:
- Unify johnzon (JSON-B/JSON-P/core/mapper) to a single jakarta-only
  version line across the root pom and all modules that previously
  re-pinned the javax line.
- Port the vendored jsonschema validator in component-form-core to a
  dedicated org.talend...validation.jsonschema package built on
  jakarta.json, replacing the javax.json-based implementation.
- Migrate component-form-*, component-runtime-testing/*,
  component-runtime-design-extension, sample-parent samples/features,
  component-studio/component-runtime-di, singer-parent,
  component-tools(-webapp) and documentation modules to jakarta
  annotations/APIs.
- Unify Tomcat/Meecrowave/OpenWebBeans to a single jakarta-compatible
  version line (CXF 4.x) reactor-wide.
- Fix talend-component-maven-plugin: re-declare openwebbeans-se
  (previously only "provided" via component-tools-webapp, hence never
  on the plugin own runtime classpath) so the uispec/web goals boot
  a valid CDI-SE container.
- Add a documented clirr ignored difference entry for
  BaseComponentsHandler$State constructor javax->jakarta parameter
  change (differenceType 7005), instead of skipping clirr checks.
- Fix checkstyle FinalParameters violations introduced by the
  migration in component-form-core vendored jsonschema port.

Verified via full reactor mvn clean install -DskipTests -Dinvoker.skip=true
(compile, checkstyle, RAT, clirr all green) and targeted mvn install
(no skips) on the 3 clirr-bound modules.

This is an exploratory spike (QTDI-3497): downstream connector
repositories (e.g. Talend/connectors) still reference javax.annotation
and javax.json directly in their own sources and would need their own
jakarta migration before they can build against this branch end-to-end.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@undx undx self-assigned this Sep 29, 2026
@sonar-rnd

sonar-rnd Bot commented Sep 30, 2026

Copy link
Copy Markdown

Failed Quality Gate failed

  • 62.80% Coverage on New Code (is less than 80.00%)
  • 5.00% Duplicated Lines (%) on New Code (is greater than 3.00%)
  • 55 New Issues (is greater than 0)

Project ID: org.talend.sdk.component:component-runtime

View in SonarQube

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant