Skip to content

Add GlassFish / Jakarta EE shopservice with CI#20

Merged
rrobetti merged 34 commits intomainfrom
copilot/evaluate-glassfish-jakarta-ee
Mar 16, 2026
Merged

Add GlassFish / Jakarta EE shopservice with CI#20
rrobetti merged 34 commits intomainfrom
copilot/evaluate-glassfish-jakarta-ee

Conversation

Copy link
Contributor

Copilot AI commented Mar 14, 2026

Adds a complete Jakarta EE 10 / GlassFish 7 implementation of the shopservice to this repo, covered by Arquillian integration tests running in CI. OJP integration is in place for both production and test datasources.

Production datasource (glassfish-resources.xml)

Uses org.openjproxy.jdbc.OjpDataSource — the javax.sql.DataSource implementation shipped with the OJP JDBC driver. This lets GlassFish register the JNDI resource as javax.sql.DataSource, which is what its JTA resource validator requires.

Client-side pooling is suppressed (steady-pool-size="0", max-connection-usage-count="1") so OJP handles all pooling server-side, consistent with every other module in this repo.

<jdbc-connection-pool
    name="ShopServicePool"
    res-type="javax.sql.DataSource"
    datasource-classname="org.openjproxy.jdbc.OjpDataSource"
    steady-pool-size="0"
    idle-timeout-in-seconds="0"
    max-connection-usage-count="1">
    <property name="url" value="jdbc:ojp[localhost:1059]_postgresql://localhost/shopservice_db"/>
    ...
</jdbc-connection-pool>

Test datasource (TestDataSourceProducer)

@DataSourceDefinition connects through OJP to H2 in-memory. Registered in the java:app/ namespace so it is visible to ResourceValidator before it runs — glassfish-resources.xml inside a WAR is never bound in JNDI early enough in GlassFish Embedded.

@DataSourceDefinition(
        name      = "java:app/jdbc/shopservice",
        className = "org.openjproxy.jdbc.OjpDataSource",
        url       = "jdbc:ojp[localhost:1059]_h2:mem:shopdb;MODE=LEGACY;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
        user      = "sa",
        password  = "")

MODE=LEGACY is included so H2 2.x accepts EclipseLink's BIGINT IDENTITY DDL syntax. Schema generation uses standard EclipseLink drop-and-create with no custom scripts.

How integration tests work

  1. @DataSourceDefinition on TestDataSourceProducer registers the datasource under java:app/jdbc/shopservice in the embedded GlassFish JNDI tree.
  2. DeploymentFactory.createDeployment() builds the ShrinkWrap WAR and includes TestDataSourceProducer.class, substituting persistence-test.xml as META-INF/persistence.xml.
  3. persistence-test.xml points EclipseLink at that JNDI name and uses drop-and-create + H2Platform so EclipseLink generates H2-compatible DDL.
  4. Each @RunWith(Arquillian) test class calls DeploymentFactory.createDeployment() from its @Deployment method, deploying to embedded GlassFish with that datasource.

TestDataSourceProducer is only included in the test archive — it is never bundled in the production WAR.

Notable GlassFish / Jakarta EE specifics addressed

  • WELD-001524 (Java 17+ module access): --add-opens flags added to Surefire argLine — GlassFish Embedded doesn't run its normal startup scripts that provide these.
  • EclipseLink platform: eclipselink.target-database=org.eclipse.persistence.platform.database.H2Platform (FQN required; the short alias H2 throws ClassNotFoundException in EclipseLink 4.x).
  • CDI discovery: beans.xml uses bean-discovery-mode="annotated" to prevent Weld from proxying server-side built-in beans it can't load from the WAR classloader.
  • OJP driver placement: For production, the JAR must be in $GLASSFISH_HOME/domains/domain1/lib/ so the server-level pool manager can load it.
  • ID generation: All entities use GenerationType.IDENTITY. EclipseLink omits the id column from INSERT statements and retrieves the generated key via Statement.getGeneratedKeys().

Integration-test-only notice

All app READMEs in this repo include a > [!WARNING] alert noting that these applications were built for integration testing purposes only and may require configuration changes to run outside the CI context.

CI

mvn clean verify for glassfish/shopservice added to .github/workflows/main.yml.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits March 14, 2026 20:20
Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copilot AI changed the title [WIP] Evaluate requirements for shopservice app on Glassfish and Jakarta EE Add GlassFish 7 / Jakarta EE 10 shopservice implementation Mar 14, 2026
Copilot AI requested a review from rrobetti March 14, 2026 20:24
-->
<resources>

<jdbc-connection-pool
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot is this really a connection pool? OJP does not work if there is a connection pool active in the client as per pooling is handled in the service, if you check all other pojects of shopservice in this repo they all have local pooling disable, and instead they create and close every connection.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right — fixed in 5483ccb. The pool now has steady-pool-size="0" (no idle connections) and max-connection-usage-count="1" (connection discarded after each use), which makes GlassFish open a fresh connection per request and never cache/recycle it. This matches the approach in the other modules: Spring Boot's SimpleDriverDataSource, Micronaut's bare DriverManager wrapper, and Quarkus's unpooled=true.

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copilot AI changed the title Add GlassFish 7 / Jakarta EE 10 shopservice implementation Disable client-side connection pooling in GlassFish JDBC config Mar 14, 2026
Copy link
Collaborator

@rrobetti rrobetti left a comment

Choose a reason for hiding this comment

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

@copilot you need to add the execution of the integration tests of Glassfish you just created to the main workflow that runs all other frameworks' tests already

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 14, 2026

@copilot you need to add the execution of the integration tests of Glassfish you just created to the main workflow that runs all other frameworks' tests already

Done in ff78555. Added a Run OJP GlassFish Integration tests (shopservice) step to .github/workflows/main.yml that runs mvn clean verify in glassfish/shopservice, placed after the Narayana step and before the log dump — exactly matching the pattern used for all other frameworks.

Copilot AI changed the title Disable client-side connection pooling in GlassFish JDBC config Disable client-side connection pooling in GlassFish JDBC config and add CI integration Mar 14, 2026
Copilot AI requested a review from rrobetti March 14, 2026 20:45
@rrobetti
Copy link
Collaborator

@copilot Glassfish integration tests are failing, one of the errors is

Error: xtActionReporterFAILUREApplication shopservice is not deployed on this target [server][ERROR] Tests run: 3, Failures: 0, Errors: 3, Skipped: 0, Time elapsed: 0.287 s <<< FAILURE! -- in com.example.shopservice.resource.OrderResourceTest
Error: com.example.shopservice.resource.OrderResourceTest.testCreateOrder -- Time elapsed: 0.026 s <<< ERROR!
io.restassured.path.json.exception.JsonPathException: Failed to parse the JSON document
at io.restassured.path.json.JsonPath$ExceptionCatcher.invoke(JsonPath.java:1002)
at io.restassured.path.json.JsonPath$4.doParseWith(JsonPath.java:967)
at io.restassured.path.json.JsonPath$JsonParser.parseWith(JsonPath.java:1047)
at io.restassured.path.json.JsonPath.get(JsonPath.java:202)
at io.restassured.path.json.JsonPath.getLong(JsonPath.java:332)
at com.example.shopservice.resource.OrderResourceTest.createUser(OrderResourceTest.java:40)
at com.example.shopservice.resource.OrderResourceTest.testCreateOrder(OrderResourceTest.java:46)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.junit5.ArquillianExtension$1.invoke(ArquillianExtension.java:169)
at org.jboss.arquillian.container.test.impl.execution.LocalTestExecuter.execute(LocalTestExecuter.java:58)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:86)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:103)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:90)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:134)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:106)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:62)
at org.jboss.arquillian.container.test.impl.execution.ClientTestExecuter.execute(ClientTestExecuter.java:50)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:86)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:103)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:90)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.createContext(ContainerEventController.java:128)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.createTestContext(ContainerEventController.java:118)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:86)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:95)
at org.jboss.arquillian.test.impl.TestContextHandler.createTestContext(TestContextHandler.java:116)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:86)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:95)
at org.jboss.arquillian.test.impl.TestContextHandler.createClassContext(TestContextHandler.java:83)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:86)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:95)
at org.jboss.arquillian.test.impl.TestContextHandler.createSuiteContext(TestContextHandler.java:69)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:86)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:95)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:134)
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.test(EventTestRunnerAdaptor.java:139)
at org.jboss.arquillian.junit5.ArquillianExtension.interceptInvocation(ArquillianExtension.java:149)
at org.jboss.arquillian.junit5.ArquillianExtension.interceptTestMethod(ArquillianExtension.java:89)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)
Caused by: groovy.json.JsonException: Lexing failed on line: 1, column: 1, while reading '<', no possible valid JSON value or punctuation could be recognized.
at groovy.json.JsonLexer.nextToken(JsonLexer.java:86)
at groovy.json.JsonLexer$nextToken.call(Unknown Source)
at io.restassured.internal.path.json.ConfigurableJsonSlurper.parse(ConfigurableJsonSlurper.groovy:97)
at io.restassured.internal.path.json.ConfigurableJsonSlurper$parse.callCurrent(Unknown Source)
at io.restassured.internal.path.json.ConfigurableJsonSlurper.parseText(ConfigurableJsonSlurper.groovy:83)
at io.restassured.path.json.JsonPath$4$1.method(JsonPath.java:965)
at io.restassured.path.json.JsonPath$ExceptionCatcher.invoke(JsonPath.java:1000)
... 44 more

…beans.xml

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 14, 2026

@copilot Glassfish integration tests are failing, one of the errors is

Error: xtActionReporterFAILUREApplication shopservice is not deployed on this target [server][ERROR] Tests r...

Fixed in cc7eb57. Two root causes identified:

  1. EclipseLink H2 dialect — without an explicit hint, EclipseLink auto-detects the database via JDBC metadata. With OJP as a proxy it doesn't recognise H2, falls back to a generic dialect that omits GENERATED BY DEFAULT AS IDENTITY on @Id columns, and every persist() fails with a NOT-NULL violation (→ HTTP 500 → HTML response → JsonPathException). Added <property name="eclipselink.target-database" value="H2"/> to persistence-test.xml, mirroring Spring Boot's hibernate.dialect=H2Dialect and Quarkus's db-kind=h2.

  2. CDI activation in ShrinkWrap archive — added EmptyAsset.INSTANCE as WEB-INF/beans.xml in DeploymentFactory for reliable annotated-mode CDI discovery, which is a common requirement when deploying programmatic ShrinkWrap archives to GlassFish/Weld embedded.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • glassfish.org
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/working/files-to-index10291086706110143638.list --sourceArchiveDir=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/src --outputDir=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/trap/java (dns block)
  • repository.jboss.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/ojp-framework-integration/ojp-framework-integration/META-INF/maven/dev.snowdrop/narayana-spring-boot-core org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • s01.oss.sonatype.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/ojp-framework-integration/ojp-framework-integration/quarkus/shopservice org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Contributor Author

Copilot AI commented Mar 15, 2026

@copilot I am fixing the Statement.RETURN_GENERATED_KEYS situation in OJP, meanwhile I want you to revert any changes done to work around it. I will let you know once fixed.

Done in 05068f0. Reverted in all 5 entities back to GenerationType.IDENTITY, updated create.sql to use BIGINT GENERATED BY DEFAULT AS IDENTITY, and removed the DROP SEQUENCE lines from drop.sql. The rest of the DDL scripting setup (custom create/drop scripts, FK-safe drop order, EclipseLink DDL redirect) is left in place as those fixes are independent of the getGeneratedKeys() issue.

@rrobetti
Copy link
Collaborator

@copilot
Internal Exception: java.sql.SQLException: Table "PRODUCTS" not found; SQL statement:
INSERT INTO products (NAME, PRICE) VALUES (?, ?) [42102-232]
Error Code: 42102
Call: INSERT INTO products (NAME, PRICE) VALUES (?, ?)
bind => [Widget, 19.99]
Query: InsertObjectQuery(com.example.shopservice.entity.Product@4a3faa67)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:783)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:280)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:175)
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:70)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:449)
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:865)
at com.sun.enterprise.transaction.TransactionManagerHelper.commit(TransactionManagerHelper.java:67)
at org.glassfish.cdi.transaction.TransactionalInterceptorRequired.transactional(TransactionalInterceptorRequired.java:95)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)

…e.sql runs for IDENTITY entities

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 15, 2026

@copilot
Internal Exception: java.sql.SQLException: Table "PRODUCTS" not found; SQL statement:
INSERT INTO products (NAME, PRICE) VALUES (?, ?) [42102-232]
...

Fixed in 90cc535.

Root cause: eclipselink.ddl-generation=create-or-extend-tables + output-mode=sql-script skips executing the JPA standard create-source=script for GenerationType.IDENTITY entities — EclipseLink considers DDL "handled" (written to file) and never runs create.sql against the database.

Switched back to eclipselink.ddl-generation=none. This prevents EclipseLink's proprietary DDL from racing with the JPA scripts while still letting drop.sql and create.sql execute, so tables are created with GENERATED BY DEFAULT AS IDENTITY. The test will still fail with the INSERT/getGeneratedKeys issue until the OJP fix lands.

@rrobetti
Copy link
Collaborator

@copilot the auto-generated key issue has been fixed in ojp
Open-J-Proxy/ojp@d56af7f

but still getting this error

Caused by: java.sql.SQLException: NULL not allowed for column "ID"; SQL statement:
INSERT INTO users (CREATEDAT, EMAIL, USERNAME) VALUES (?, ?, ?) [23502-232]
at org.openjproxy.grpc.client.GrpcExceptionHandler.handle(GrpcExceptionHandler.java:32)
at org.openjproxy.grpc.client.StatementServiceGrpcClient.executeUpdate(StatementServiceGrpcClient.java:118)
at org.openjproxy.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:127)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:112)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:909)
... 97 more

Remember how was the setup when we fixed it without OJP? the settings for DDL and how to configure everything should be the same as in that commit only adding OJP as a pass trough proxy. We should not be having to do all these fixing. Make sure that only required OJP changes are in place and everything else is exactly the same as when it worked without OJP. So I want you to keep ojp but revert everything else to be the same as in the commit that worked connecting directly to H2

… OJP getGeneratedKeys() is fixed

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 15, 2026

@copilot the auto-generated key issue has been fixed in ojp
Open-J-Proxy/ojp@d56af7f

...

Fixed in 597fda3.

The three changes that restore the working direct-H2 baseline with OJP as the only difference:

  1. TestDataSourceProducer: Added MODE=LEGACY to the OJP backend URL (jdbc:ojp[localhost:1059]_h2:mem:shopdb;...;MODE=LEGACY) — same as the direct H2 baseline, so H2 2.x accepts EclipseLink's BIGINT IDENTITY DDL.

  2. persistence-test.xml: Reverted to drop-and-create — removed all custom script properties (drop-source=script, create-source=script, drop-script-source, create-script-source) and eclipselink.ddl-generation=none. Identical to the working baseline.

  3. DeploymentFactory: Removed drop.sql and create.sql from the ShrinkWrap archive.

The only OJP-specific change remaining is OjpDataSource class + OJP URL prefix in TestDataSourceProducer, everything else is identical to the commit that worked directly against H2.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • glassfish.org
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/working/files-to-index12143856557880057014.list --sourceArchiveDir=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/src --outputDir=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/trap/java (dns block)
  • repository.jboss.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/ojp-framework-integration/ojp-framework-integration/META-INF/maven/dev.snowdrop/narayana-spring-boot-core org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • s01.oss.sonatype.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/ojp-framework-integration/ojp-framework-integration/quarkus/shopservice org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@rrobetti
Copy link
Collaborator

@copilot Still failing with the auto generated problem. Remove OJP again and leave in the working baseline version accessing H2 directly. I try this locally later.

…configuration

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 15, 2026

@copilot Still failing with the auto generated problem. Remove OJP again and leave in the working baseline version accessing H2 directly. I try this locally later.

Done in 58362b0. Reverted to the direct H2 baseline:

  • TestDataSourceProducer: uses org.h2.jdbcx.JdbcDataSource with jdbc:h2:mem:shopdb;MODE=LEGACY directly (no OJP)
  • persistence-test.xml: standard drop-and-create (no custom scripts)
  • DeploymentFactory: no custom SQL files
  • pom.xml: removed SLF4J deps (only needed for OjpDataSource)
  • Deleted create.sql and drop.sql
  • glassfish-resources.xml: reverted to driver-classname=org.openjproxy.jdbc.Driver for production

This is exactly the working state from before OJP was introduced into the tests.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • glassfish.org
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/working/files-to-index16397389353636903784.list --sourceArchiveDir=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/src --outputDir=/tmp/codeql-scratch-44c33df7668c9f98/dbs/java/trap/java -Dlicense.skip=true -Drat.skip=true -Dspotless.check.skip=true -s /tmp/codeql-scratch-44c33df7668c9f98/dbs/java/working/settings.xml com.github.ferstl:depgraph-maven-plugin:4.0.3-CodeQL:graph (dns block)
  • repository.jboss.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/ojp-framework-integration/ojp-framework-integration/META-INF/maven/dev.snowdrop/narayana-spring-boot-core org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • s01.oss.sonatype.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/ojp-framework-integration/ojp-framework-integration/quarkus/shopservice org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Add GlassFish / Jakarta EE shopservice with OJP integration and CI Add GlassFish / Jakarta EE shopservice with CI Mar 15, 2026
@rrobetti
Copy link
Collaborator

@copilot explain how exactly these integration tests are working. Where is the URL to H2 configured?

Copy link
Contributor Author

Copilot AI commented Mar 16, 2026

@copilot explain how exactly these integration tests are working. Where is the URL to H2 configured?

The H2 URL is configured in TestDataSourceProducer via @DataSourceDefinition:

@DataSourceDefinition(
        name      = "java:app/jdbc/shopservice",
        className = "org.h2.jdbcx.JdbcDataSource",
        url       = "jdbc:h2:mem:shopdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=LEGACY",
        user      = "sa",
        password  = "")

Here's how it flows end-to-end:

  1. @DataSourceDefinition on TestDataSourceProducer registers an H2 in-memory datasource under java:app/jdbc/shopservice in the embedded GlassFish JNDI tree.

  2. DeploymentFactory.createDeployment() builds the ShrinkWrap WAR and includes TestDataSourceProducer.class in the archive. It also substitutes the test persistence-test.xml as META-INF/persistence.xml.

  3. persistence-test.xml points EclipseLink at that JNDI name:

    <jta-data-source>java:app/jdbc/shopservice</jta-data-source>

    and uses drop-and-create + H2Platform so EclipseLink generates H2-compatible DDL.

  4. Each @RunWith(Arquillian) test class calls DeploymentFactory.createDeployment() from its @Deployment method, so every test class deploys to the embedded GlassFish with that same H2-backed datasource.

TestDataSourceProducer is only included in the test archive — it is never bundled in the production WAR.

@copilot explain how exactly these integration tests are working. Where is the URL to H2 configured?

The H2 URL is configured in TestDataSourceProducer via a @DataSourceDefinition annotation:

@DataSourceDefinition(
        name      = "java:app/jdbc/shopservice",
        className = "org.h2.jdbcx.JdbcDataSource",
        url       = "jdbc:h2:mem:shopdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=LEGACY",
        user      = "sa",
        password  = "")
@ApplicationScoped
public class TestDataSourceProducer {}

Here's how the whole chain works:

  1. DeploymentFactory.createDeployment() builds a ShrinkWrap WAR that includes TestDataSourceProducer, all entities/repositories/resources, and a test-specific persistence.xml (mapped from persistence-test.xml).

  2. persistence-test.xml references java:app/jdbc/shopservice as the JTA data source and sets schema-generation.database.action=drop-and-create so EclipseLink creates the schema fresh on each test deployment. eclipselink.target-database=org.eclipse.persistence.platform.database.H2Platform tells EclipseLink to generate H2-compatible DDL.

  3. @DataSourceDefinition on TestDataSourceProducer registers the H2 datasource in JNDI at java:app/jdbc/shopservice during CDI deployment, before GlassFish's ResourceValidator checks JNDI references. This is why it can't be in glassfish-resources.xml — that file's resources aren't bound to JNDI early enough in GlassFish Embedded.

  4. Arquillian deploys the WAR into the embedded GlassFish instance, EclipseLink drops and recreates the H2 schema, and the JAX-RS resource tests (ProductResourceTest, etc.) call the deployed REST endpoints over HTTP against the in-memory H2 database.

@rrobetti
Copy link
Collaborator

@copilot I have fixed the issues in relation to the auto generated indexes not working on glassfish, the trouble was that glassfish was running after many other tests in the workflow (spring boot, quarkus, micronout) which created the tables already, so when glassfish tried to recriate them they were already there and it would use the ones there, but the other tests do not configure autoincrement in the manner glassfish needed. Correct me if I am missing something here.

Now I want you to add these explanations you gave me about where things are configured for the test.

I also want you to fix the OJP port in the postgres connection url inside the glassfish-resources.xml
jdbc:ojp[localhost:5432]postgresql://localhost/shopservice
ojp port is 1059.

Also I want you to add an alert in every README of every test app in this repo stating that these apps were run only for integration tests, if someone wants to really run them (outside integration testing context) there might be changes required.

… setup

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 16, 2026

@copilot I have fixed the issues in relation to the auto generated indexes not working on glassfish, the trouble was that glassfish was running after many other tests in the workflow...

Done in b30a0de.

Your analysis is correct — the GlassFish test was sharing H2 with prior test jobs (Spring Boot, Quarkus, Micronaut) in the same workflow run. Those frameworks create the tables without GENERATED BY DEFAULT AS IDENTITY (or with a different schema), and since H2's DB_CLOSE_DELAY=-1 keeps the in-memory DB alive across the JVM, GlassFish's drop-and-create wasn't running cleanly against those stale tables. Running the GlassFish job in its own isolated step (as it now is) eliminates that interference.

Three changes in this commit:

  1. OJP port in glassfish-resources.xml: changed localhost:5432localhost:1059.

  2. "How Integration Tests Work" section added to glassfish/shopservice/README.md — explains the role of TestDataSourceProducer (@DataSourceDefinition with the H2 URL), DeploymentFactory (ShrinkWrap archive builder), persistence-test.xml (drop-and-create + H2Platform), and the end-to-end Arquillian flow.

  3. > [!WARNING] integration-test-only alert added to the top of all 6 app READMEs (glassfish/shopservice, spring-boot/shopservice, quarkus/shopservice, micronaut/shopservice, spring-boot-atomikos, spring-boot-narayana).

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.

2 participants