Skip to content

Migrate from arquillian-glassfish-server-managed to arquillian-glassfish-server-pool#368

Draft
BalusC wants to merge 4 commits into
jakartaee:masterfrom
BalusC:arquillian-glassfish-server-pool
Draft

Migrate from arquillian-glassfish-server-managed to arquillian-glassfish-server-pool#368
BalusC wants to merge 4 commits into
jakartaee:masterfrom
BalusC:arquillian-glassfish-server-pool

Conversation

@BalusC
Copy link
Copy Markdown
Member

@BalusC BalusC commented May 10, 2026

Replaces the per-module GlassFish unpack + JVM-scoped server lifecycle with a shared pre-warmed slot pool, mirroring the faces/tck migration in jakartaee/faces#2165. A single GlassFish dist is unpacked at validate, all slots clone from it, and the arquillian-glassfish-server-pool extension leases a slot per test JVM. Default invocation is unchanged (mvn verify); mvn clean install -T8 drops wall-clock from ~24 min to ~2 min.

  • glassfish-pool-maven-plugin in pluginManagement carries distribution + per-overlay (jakarta.security-api, soteria, soteria-weld) config; per- overlay tags wire to the existing security.api.update / soteria.update master switches via a build-helper bsh-property hop.
  • glassfish-ci-managed profile rewritten: arquillian-glassfish-server-pool
    in place of -managed, pool:up at initialize, parent-owned source-staging
    antrun at validate (mkdir-lock + marker, awk-portable) handles unpack, Mitre cert import into cacerts.p12, and trustStorePassword injection into domain.xml — see the in-line comment on gf.pool.unpack.skip for why these have to land before pool:up.
  • maven-install-plugin install-file (vendor-api jar for sigtest) is now inherited=false at initialize on the reactor root only — aggregator goal with a per-module execution wasn't safe under -T.
  • maven-surefire-report-plugin failsafe-report-only and cyclonedx makeAggregateBom: same root-only treatment, removes the parallel-build aggregator stalls.

Shared-pool collateral fixed alongside (each came up while making individual modules -T-safe; README's "Running tests in parallel" section documents the rules for new modules):

  • Cross-app java:global/ DataSource sharing exposed an upstream GlassFish bug — ComponentEnvManagerImpl.getResourceId returned "" for ScopeType.GLOBAL, so every app declaring the same java:global/X ended up sharing one un-prefixed physical pool, and connections opened against the first app's classloader lingered after that app undeployed (next app's lookups blew up with ClassLoader is not in expected state wrapped as SQLException: GeneralError). Fixed in Scope java:global/ resource pools per declaring app eclipse-ee4j/glassfish#26029
  • Per-module embedded LDAP ports: app-ldap2/3 split off the colliding 33389 onto 33390/33391; app-ldap stays on 33389.
  • app-openid: hardcoded http://localhost:8080/openid-server/... replaced with EL/UriInfo-derived URLs (OpenIdConfig.getProviderURI() backed by injected HttpServletRequest; OidcProvider uses @context UriInfo) so metadata, JWT issuer and providerURI all track the live request.
  • app-openid2/3: per-module Tomcat ports (8443+8005 / 8444+8006); clients.sql redirect URIs pre-registered for every slot the pool may grow to (= ${session.request.degreeOfConcurrency} = -TN, exposed as a regular property via bsh-property since Maven only resolves bean expressions for typed Plexus parameters); openid3 cert pair refreshed (the original expired 2023-03 and PKIX rejects it on a current JDK); Tomcat work/ wiped before startup so SESSIONS.ser doesn't resurrect Mitre's "client already authorized" state across re-runs without clean.
  • arquillian.xml: glassfish-pool container added (default), poolDir from the gf.pool.dir property forwarded by failsafe.

The Mitre cert handling needed two pre-startup fixes: the cert must be in cacerts.p12 before GF starts (Java caches the default SSLContext on first SSL use and never reloads from disk), and -Djavax.net.ssl.trustStorePassword must be set on the GF JVM — without it Java loads the PKCS12 truststore with zero trust anchors regardless of how many certs the file contains. The cert import runs from antrun (it's TCK-specific). The trust-store password goes through arquillian-glassfish-server-pool's native hook (added in OmniFish-EE/arquillian-container-glassfish#39 to mirror the existing glassfish-managed convention), which bakes it into each slot's domain.xml as a -D jvm-option at provisioning time.

NOTE: this is a Draft PR because arquillian-container-glassfish 2.1.4 is not yet released and 2.1.4-SNAPSHOT in current code needs to be swapped out for 2.1.4 or 2.2.0 once it's released.

Related PR: OmniFish-EE/arquillian-container-glassfish#38
Checkout both branches, make sure eclipse-ee4j/glassfish#26029 is fixed in your local GlassFish 9.0.0-SNAPSHOT, build the arquillian-container-glassfish 2.1.4-SNAPSHOT then run mvn clean install -Tn on tck folder of current branch.

Fastest result so far at my machine using mvn clean install -T8:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:49 min (Wall Clock)
[INFO] Finished at: 2026-05-11T09:32:31-04:00
[INFO] ------------------------------------------------------------------------

It was ~24 minutes.

arquillian-glassfish-server-pool

Replaces the per-module GlassFish unpack + JVM-scoped server lifecycle
with a shared pre-warmed slot pool, mirroring the faces/tck migration in
jakartaee/faces#2165. A single GlassFish dist is unpacked at validate,
all slots clone from it, and the arquillian-glassfish-server-pool
extension leases a slot per test JVM. Default invocation is unchanged
(mvn verify); mvn clean install -T8 drops wall-clock from ~24 min to ~2
min.

- glassfish-pool-maven-plugin in pluginManagement carries distribution +
  per-overlay (jakarta.security-api, soteria, soteria-weld) config; per-
  overlay <skip> tags wire to the existing security.api.update /
  soteria.update master switches via a build-helper bsh-property hop.
- glassfish-ci-managed profile rewritten:
arquillian-glassfish-server-pool
  in place of -managed, pool:up at initialize, parent-owned
source-staging
  antrun at validate (mkdir-lock + marker, awk-portable) handles unpack,
  Mitre cert import into cacerts.p12, and trustStorePassword injection
  into domain.xml — see the in-line comment on gf.pool.unpack.skip for
  why these have to land before pool:up.
- maven-install-plugin install-file (vendor-api jar for sigtest) is now
  inherited=false at initialize on the reactor root only — aggregator
  goal with a per-module execution wasn't safe under -T.
- maven-surefire-report-plugin failsafe-report-only and cyclonedx
  makeAggregateBom: same root-only treatment, removes the parallel-build
  aggregator stalls.

Shared-pool collateral fixed alongside (each came up while making
individual modules -T-safe; README's "Running tests in parallel" section
documents the rules for new modules):

- Per-module H2 JNDI: each app-db-* binds DataSource under a unique
  java:global/securityAPIDB-<suffix> instead of all sharing one global
  name (collisions with one GF JVM hosting many sequential deploys).
- Per-module embedded LDAP ports: app-ldap2/3 split off the colliding
  33389 onto 33390/33391; app-ldap stays on 33389.
- app-openid: hardcoded http://localhost:8080/openid-server/... replaced
  with EL/UriInfo-derived URLs (OpenIdConfig.getProviderURI() backed by
  injected HttpServletRequest; OidcProvider uses @context UriInfo) so
  metadata, JWT issuer and providerURI all track the live request.
- app-openid2/3: per-module Tomcat ports (8443+8005 / 8444+8006);
  clients.sql redirect URIs pre-registered for every slot the pool may
  grow to (= \${session.request.degreeOfConcurrency} = -TN, exposed as a
  regular property via bsh-property since Maven only resolves bean
  expressions for typed Plexus parameters); openid3 cert pair refreshed
  (the original expired 2023-03 and PKIX rejects it on a current JDK);
  Tomcat work/ wiped before startup so SESSIONS.ser doesn't resurrect
  Mitre's "client already authorized" state across re-runs without
  clean.
- arquillian.xml: glassfish-pool container added (default), poolDir from
  the gf.pool.dir property forwarded by failsafe.

The Mitre cert handling needed two pre-startup fixes: the cert must be
in cacerts.p12 *before* GF starts (Java caches the default SSLContext on
first SSL use and never reloads from disk), and -Djavax.net.ssl.trust-
StorePassword must be set on the GF JVM via domain.xml — without it Java
loads the PKCS12 truststore with zero trust anchors regardless of how
many certs the file contains. Pre-migration this came through
arquillian-glassfish-server-managed's glassfish.systemProperties hook;
the pool plugin doesn't have an equivalent so we bake it into source
domain.xml instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BalusC and others added 2 commits May 11, 2026 07:36
Drops the awk hack that injected
<jvm-options>-Djavax.net.ssl.trustStorePassword=changeit</jvm-options>
into the source domain.xml from antrun. The pool plugin now exposes
<systemProperties> natively (mirroring arquillian-glassfish-server-managed),
so we configure it via plugin <configuration> instead of post-processing
the staged dist by hand.

The antrun staging step still does the unzip + Mitre cert import — the
cert is TCK-specific and can't move into the pool plugin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reverts the @DataSourceDefinition(name = "java:global/securityAPIDB-<suffix>")
workaround in 14 app-db-* modules — restores the shared
"java:global/securityAPIDB" name and drops README rule jakartaee#1.

The workaround was added during the arquillian-glassfish-server-pool
migration to dodge cross-module GeneralError failures. The actual root
cause turned out to be an upstream GlassFish bug in
ComponentEnvManagerImpl.getResourceId returning "" for ScopeType.GLOBAL,
causing every app declaring the same java:global/X to share one physical
connection pool — see BalusC/glassfish branch
scope-global-resource-pools-per-app for the fix.

With patched GlassFish in place the suffix is no longer needed; both
sequential and -T8 parallel reactor runs pass with the shared name.
README rules 2-6 renumbered to 1-5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dmatej pushed a commit to BalusC/glassfish that referenced this pull request May 12, 2026
ComponentEnvManagerImpl.getResourceId returned "" for ScopeType.GLOBAL,
so deriveResourceName produced an un-prefixed pool name and every app
declaring the same java:global/X (e.g. @DataSourceDefinition) shared
one physical connection pool. Connections opened against the first
app's classloader stayed in the shared pool after that app undeployed,
blowing up the next app's lookups with "ClassLoader is not in expected
state" wrapped as SQLException: GeneralError.

Return the application name for GLOBAL too, matching the behaviour
already in place for APP scope. Each app now gets its own physical
pool keyed under __SYSTEM/.../<appName>/java:global/X — symmetric with
__SYSTEM/.../<appName>/java:app/X.

The empty fall-through has been there since the helper was introduced
in 1230a81 (2012-07-25, Java EE 7 Mail Resource Annotation); GLOBAL
was simply omitted from the COMPONENT/MODULE/APP cascade. No deliberate
semantics to preserve.

Discovered while debugging recurring "GeneralError" failures in
jakartaee/security#368 (Jakarta Security TCK
arquillian-glassfish-server-pool
migration), where multiple app-db-* modules each declare
@DataSourceDefinition(name = "java:global/securityAPIDB", ...).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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