Skip to content

Implements Jakarta Persistence 3.2 - #144

Open
cristof wants to merge 267 commits into
masterfrom
OPENJPA-2940
Open

Implements Jakarta Persistence 3.2#144
cristof wants to merge 267 commits into
masterfrom
OPENJPA-2940

Conversation

@cristof

@cristof cristof commented May 16, 2026

Copy link
Copy Markdown
Contributor

Hi! This work is an effort to implement JPA 3.2. I've started it a long time ago. Richard Zowalla picked it up and, with AI help (Claude), implemented the missing features, including some JPA <3.0 that weren't implemented.
I've tested it against default database, h2, mariadb(lts) e postgresql (18).
Please, check it against your favorite DB so we may fix some edge cases. It would be great if you can run TCK to be sure of the implementations.

cristof added 30 commits July 11, 2025 17:01
* Reverting unnecessary changes
* Fixing broken map synchronization
* Changing signature of BrokerFactory API on schema dealing validate method
* Adding test to check if validate operation throws exception when it fails
* Changing GH CI workflow to allow usage of both self-hosted and GH hosted runners
* Tested on derby, h2-2, postgresql:latest, mysql:lts, mariadb:lts
* Implementing emf creation passing PersistenceConfiguration
* Removing unused import in BrokerImpl
* Implemented new PersistenceUnitUtil load methods
* Moved PUU loading tests to test unit already present
* Updated test unit to junit 4.x format
* Original impl was wrongfully dependent of persistence.xml file
* Fixed this issue, but still lacking actual conversion of PersistenceConfiguration
properties to openjpa corresponding properties
* added update OracleDictionary to use unqualified table name from main
* added temporary file information disclosure vul-fix from main
…tence.xml

* Added tests of specifications supported
* Added support for scope and qualifiers in PersistenceUnitInfo and persistence.xml
Added function and corresponding tests, but MySQL still fails in tests.
Passed on h2-2, pg, mariadb.
* fixed behavior on MySQL
* tested on derbdb, h2-2, mysql lts, mariadb lts, postgresql
@rzo1

rzo1 commented Jul 17, 2026

Copy link
Copy Markdown

How do you run the tests exactly? They require quite a lot of properties 🙃

@solomax

solomax commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

I'm using: reset && ./run-tck32.sh :)
It starts Postgres:16 and runs everything

As I understand for some reason jpa.provider.implementation.specific.properties is not working
I'll try to debug :)

@rzo1

rzo1 commented Jul 17, 2026

Copy link
Copy Markdown

@solomax I looked into the Client2#createEntityManagerFactoryNoBeanValidatorTest issue and could reproduce both states on PostgreSQL 16. The test actually passes without the bval change: it verifies JPA spec 3.6.1 — ValidationMode.CALLBACK with no Bean Validation provider on the classpath must end in a PersistenceException, and OpenJPA already throws it (ValidationUnavailableException → wrapped in PersistenceProviderImpl). The ERROR ... A default ValidatorFactory could not be created stack trace in the log is expected output on the passing path.

That's also why the TCK runs this single test in the separate persistence-tests-2 execution: persistence-tests-1 gets hibernate-validator via ${validator.classes}, while persistence-tests-2 deliberately has no validator. Adding org.apache.bval.bundle to our profile puts a validator on both classpaths, so the EMF now gets created, em.persist() runs, and it fails on the unenhanced Order/Member classes instead — could you revert 4588093?

Re jpa.provider.implementation.specific.properties "not working": for this one test that's by TCK design — Client2 passes the raw myProps to createEntityManagerFactory and never calls PMClientBase.getPersistenceUnitProperties(), which is the only place that string gets parsed into openjpa.* properties. For all other tests it works fine.

Verified A/B/A on postgres:16 with a fresh branch-tip build, running only the persistence-tests-2 execution: without bval → Tests run: 1, Failures: 0, Errors: 0; with bval → the ArgumentException: This configuration disallows runtime optimization failure you saw; reverted → green again.

@solomax

solomax commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

You are right @rzo1, for whatever reason the test was red for me

Reverted and GREEN :)

I'll try to add parametrization and perform more tests

@rzo1

rzo1 commented Jul 17, 2026

Copy link
Copy Markdown

I am currently looking into my suggestion regarding Romains comment.

rzo1 and others added 2 commits July 17, 2026 08:41
…thout a version, so optimistic lock failures still surface

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@solomax

solomax commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Just commited updated run-tck32.sh
It is now able to run TCK against MySql with DB_TYPE=mysql ./run-tck32.sh (version can also be specified

My results are:
[ERROR] Tests run: 2134, Failures: 0, Errors: 145, Skipped: 4

I'll try to take a look at all this later :)

@cristof

cristof commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Kubernetes flukes aside, Oracle build is now green, skipping only tests where there is no database support (TIME data type, CURRENT_TIME and EXTRACT(QUARTER from)). Ran the tests on oracle-xe-18 and oracle-xe-21.
Provided the TCK tests are ok, I think we could update the docs and (pre?) release?

@solomax

solomax commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

It seems some errors in MySQL TCK tests are caused by:

Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: Data truncation: Data too long for column 'CHARDATA' at row 1 {prepstmnt 2112012700 INSERT INTO DATATYPES (id, BOOLEANDATA, BYTEARRAYDATA, BYTEDATA, CHARARRAYDATA, CHARDATA, DBLDATA, ENUMSDATA, FLOATDATA, INTDATA, INTDATA2, LONGDATA, SHORTDATA) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)} [code=1406, state=22001]
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:219)
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:195)
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.executeUpdate(LoggingConnectionDecorator.java:1188)
	at org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:308)
	at org.apache.openjpa.jdbc.kernel.JDBCStoreManager$CancelPreparedStatement.executeUpdate(JDBCStoreManager.java:1867)

While trying to persist entity with:

	@Column(name = "CHARDATA")
	protected char characterData;

Table is create with:

CREATE TABLE DATATYPES (ID INTEGER NOT NULL, BOOLEANDATA SMALLINT NULL, CHARDATA CHAR NULL, SHORTDATA SMALLINT NULL, INTDATA INTEGER NULL, INTDATA2 INTEGER NULL, LONGDATA NUMERIC NULL, DBLDATA DOUBLE PRECISION NULL, FLOATDATA REAL NULL, ENUMODATA INTEGER NULL, ENUMSDATA VARCHAR(25), BYTEDATA SMALLINT NULL, TRANS SMALLINT NULL, BYTEARRAYDATA BLOB, CHARARRAYDATA VARCHAR(448), CONSTRAINT PK_DATATYPES PRIMARY KEY (ID) ) ENGINE=innoDB DEFAULT CHARSET=latin1 !

java oblect is created with:

			char[] cArray = { 'a' };
			byte[] bArray = { (byte) 100 };
			d1 = new DataTypes(1, false, (byte) 100, 'a', (short) 100, 300, 600L, 50D, 1.0F, cArray, bArray);

Something weird :(((

@rzo1

rzo1 commented Jul 21, 2026

Copy link
Copy Markdown

Kubernetes flukes aside, Oracle build is now green, skipping only tests where there is no database support (TIME data type, CURRENT_TIME and EXTRACT(QUARTER from)). Ran the tests on oracle-xe-18 and oracle-xe-21. Provided the TCK tests are ok, I think we could update the docs and (pre?) release?

OpenJPA historically never passed the full TCK - so we can either try to get it green (again) for certain rdbms or we make a (pre?) release with updated docs and do the TCK work in another follow up PR? wdyt?

@solomax solomax left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 to merge this PR as is (with squash and merge, I guess)
And to continue polishing in next PRs :))

@rmannibucau I would appreciate your approve as well

BTW I will be on vacation for a week or so, so might be silent :)

@cristof

cristof commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

+1 to merge and create a release candidate, but I guess it would be better to keep the commit history instead of squashing it to allow future fixes.

@cristof

cristof commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@solomax, did openjpa pass the TCK in others DBs?

@rmannibucau rmannibucau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The 90 comments tagged (high)/(medium)/(low) below were prepared with the help of Claude; the untagged ones are mine. Points already discussed in existing threads were deliberately skipped.

Comment thread .github/workflows/ci.yml Outdated
<goals>
<goal>unpack</goal>
</goals>
<?m2e ignore?>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

really needed? it is out of maven schema anyway, no comment flavor?

Comment thread openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypecastAsNumber.java Outdated
Comment thread openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypecastAsString.java Outdated
exit 1
fi

stopAll() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(medium) stopAll runs unconditionally at startup and issues docker:stop with name patterns like postgres*/mysql* for all four DB profiles, even when DB_HOST points at an external database - that can kill unrelated containers on a developer machine and adds four mvn invocations per run. Suggest guarding with START_DOCKER and limiting to the selected DB_TYPE.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@rmannibucau (this one is mine :))))

this call was added to stop all stalled dockers from previous runs (better to use trap and perform clean-up, but this dirty solution much easier :)))

I would leave it as-is but also can change if you insist :)

fi

echo ""
echo "=== Preparing ${DB_TYPE} database ==="

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(low) "=== Preparing ${DB_TYPE} database ===" is an empty leftover (Step 5 is missing between Step 4 and Step 6), yet the README claims this step drops stale tables and creates stored procedures. Either implement it or drop the heading and fix the README.

@solomax solomax Aug 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'll perform clean-up (missing DB tables are being created by maven and dropped by docker:remove ...)

Comment thread .gitignore
@@ -1163,7 +1164,7 @@ data structure.
lifecycle callbacks
</seealso>
</indexterm>
<ulink url="http://download.oracle.com/javaee/6/api/javax/persistence/PreUpdate.html">
<ulink url="https://jakarta.ee/specifications/persistence/3.2/apidocs/jakarta.persistence/jakarta/persistence/postupdate">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(low) Copy/paste nit: the PreUpdate entry links to .../jakarta/persistence/postupdate - should be preupdate (line 1191 is the correct PostUpdate one).

<id>openjpa</id>
<properties>
<glassfish-artifact-id>glassfish</glassfish-artifact-id>
<openjpa.version>4.2.0-SNAPSHOT</openjpa.version>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(low) The injected profile hardcodes <openjpa.version>4.2.0-SNAPSHOT</openjpa.version>; the script always overrides it via -Dopenjpa.version, but the default silently goes stale after release - maybe add a comment that it must be kept in sync (same for the defaults baked into the README examples).

@rmannibucau rmannibucau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

overall good even if a few things surprised me, made claude running on it and he superseeded my review so just let him push his comment, several are worth checking, some are just "nice" but can be ignored IMHO

cristof and others added 9 commits July 30, 2026 18:34
* In-memory JPA environment would incur in infinite loop when using
REPLACE if the replacement string contains the replaced one
* Fixes casts in TypecastAsNumber when running in-memory JPA env
* Adds support for java.util.Date and fixes java.sql.Date treatment in
TypecastAsString when running in-memory JPA env
LEFT and RIGHT now mimic behavior of PostgreSQL equivalent functions
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.

5 participants