From 1dcf7bea23ee3ff3f2c00122228ec8c80b1cb6da Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Tue, 15 Sep 2026 10:59:55 +0200 Subject: [PATCH] [OPENJPA-3005] Use jakarta.persistence.PersistenceUnitTransactionType internally PersistenceUnitInfoImpl keeps the transaction type as the non-deprecated jakarta.persistence.PersistenceUnitTransactionType and only converts to the SPI enum in getTransactionType(), which PersistenceUnitInfo still requires in Jakarta Persistence 3.2. A deprecated setter taking the SPI enum is kept. The jakarta.persistence.transactionType property now accepts both enums, a jakarta.persistence.PersistenceUnitTransactionType value was silently turned into a null transaction type before. --- .../PersistenceProductDerivation.java | 2 +- .../persistence/PersistenceUnitInfoImpl.java | 43 ++++++++-- ...estPersistenceUnitInfoTransactionType.java | 82 +++++++++++++++++++ 3 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 openjpa-persistence/src/test/java/org/apache/openjpa/persistence/TestPersistenceUnitInfoTransactionType.java diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java index ddfefafa51..875478afbe 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java @@ -35,10 +35,10 @@ import java.util.Set; import jakarta.persistence.PersistenceConfiguration; +import jakarta.persistence.PersistenceUnitTransactionType; import jakarta.persistence.SharedCacheMode; import jakarta.persistence.ValidationMode; import jakarta.persistence.spi.PersistenceUnitInfo; -import jakarta.persistence.spi.PersistenceUnitTransactionType; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.conf.OpenJPAConfiguration; diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java index 5e5e6fc64d..81c178dd63 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java @@ -35,11 +35,11 @@ import java.util.stream.Collectors; import jakarta.persistence.PersistenceConfiguration; +import jakarta.persistence.PersistenceUnitTransactionType; import jakarta.persistence.SharedCacheMode; import jakarta.persistence.ValidationMode; import jakarta.persistence.spi.ClassTransformer; import jakarta.persistence.spi.PersistenceUnitInfo; -import jakarta.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; import org.apache.openjpa.lib.conf.Configuration; @@ -129,15 +129,42 @@ public void setPersistenceProviderClassName(String providerClassName) { _providerClassName = providerClassName; } + /** + * The transaction type as the deprecated SPI enum, as still required by + * {@link PersistenceUnitInfo} in Jakarta Persistence 3.2. + */ @Override - public PersistenceUnitTransactionType getTransactionType() { - return _transType; + @SuppressWarnings("removal") + public jakarta.persistence.spi.PersistenceUnitTransactionType getTransactionType() { + return _transType == null ? null + : jakarta.persistence.spi.PersistenceUnitTransactionType.valueOf(_transType.name()); } public void setTransactionType(PersistenceUnitTransactionType transType) { _transType = transType; } + /** + * @deprecated use {@link #setTransactionType(PersistenceUnitTransactionType)} + */ + @Deprecated + @SuppressWarnings("removal") + public void setTransactionType(jakarta.persistence.spi.PersistenceUnitTransactionType transType) { + setTransactionType(toTransactionType(transType)); + } + + /** + * Returns the transaction type of the given unit, which may be provided by a container. + */ + @SuppressWarnings("removal") + static PersistenceUnitTransactionType transactionTypeOf(PersistenceUnitInfo info) { + return toTransactionType(info.getTransactionType()); + } + + private static PersistenceUnitTransactionType toTransactionType(Enum transType) { + return transType == null ? null : PersistenceUnitTransactionType.valueOf(transType.name()); + } + public String getJtaDataSourceName() { return _jtaDataSourceName; } @@ -356,7 +383,10 @@ public void fromUserProperties(Map map) { if (JPAProperties.PROVIDER.equals(key)) setPersistenceProviderClassName((String) val); else if (JPAProperties.TRANSACTION_TYPE.equals(key)) { - setTransactionType(JPAProperties.getEnumValue(PersistenceUnitTransactionType.class, val)); + // accept the deprecated SPI enum as well + setTransactionType(val instanceof Enum + ? toTransactionType((Enum) val) + : JPAProperties.getEnumValue(PersistenceUnitTransactionType.class, val)); } else if (JPAProperties.DATASOURCE_JTA.equals(key)) { if (val instanceof String) { setJtaDataSourceName((String) val); @@ -402,7 +432,7 @@ public Map toOpenJPAProperties() { public static Map toOpenJPAProperties(PersistenceUnitInfo info) { Map map = new HashMap(); Set added = new HashSet<>(); - if (info.getTransactionType() == PersistenceUnitTransactionType.JTA) + if (transactionTypeOf(info) == PersistenceUnitTransactionType.JTA) replaceAsOpenJPAProperty(map, added, "TransactionMode", "managed"); boolean hasJta = false; @@ -647,8 +677,7 @@ public static PersistenceUnitInfoImpl convert(PersistenceConfiguration config) { pinfo.setPersistenceProviderClassName(config.provider()); pinfo.setPersistenceUnitName(config.name()); pinfo.setSharedCacheMode(config.sharedCacheMode()); - pinfo.setTransactionType(config.transactionType() == jakarta.persistence.PersistenceUnitTransactionType.JTA ? - PersistenceUnitTransactionType.JTA : PersistenceUnitTransactionType.RESOURCE_LOCAL); + pinfo.setTransactionType(config.transactionType()); pinfo.setValidationMode(config.validationMode()); List> managedClasses = config.managedClasses(); if (managedClasses != null && !managedClasses.isEmpty()) { diff --git a/openjpa-persistence/src/test/java/org/apache/openjpa/persistence/TestPersistenceUnitInfoTransactionType.java b/openjpa-persistence/src/test/java/org/apache/openjpa/persistence/TestPersistenceUnitInfoTransactionType.java new file mode 100644 index 0000000000..7621790c7e --- /dev/null +++ b/openjpa-persistence/src/test/java/org/apache/openjpa/persistence/TestPersistenceUnitInfoTransactionType.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Map; + +import jakarta.persistence.PersistenceConfiguration; +import jakarta.persistence.PersistenceUnitTransactionType; + +import org.junit.Test; + +/** + * The transaction type is kept as {@link PersistenceUnitTransactionType} and only + * exposed as the deprecated SPI enum through {@link PersistenceUnitInfoImpl#getTransactionType()}. + */ +@SuppressWarnings("removal") +public class TestPersistenceUnitInfoTransactionType { + + @Test + public void testDefaultIsResourceLocal() { + PersistenceUnitInfoImpl pinfo = new PersistenceUnitInfoImpl(); + assertEquals(jakarta.persistence.spi.PersistenceUnitTransactionType.RESOURCE_LOCAL, + pinfo.getTransactionType()); + assertNull(PersistenceUnitInfoImpl.toOpenJPAProperties(pinfo).get("openjpa.TransactionMode")); + } + + @Test + public void testFromPersistenceConfiguration() { + PersistenceConfiguration config = new PersistenceConfiguration("tx") + .transactionType(PersistenceUnitTransactionType.JTA); + PersistenceUnitInfoImpl pinfo = PersistenceUnitInfoImpl.convert(config); + assertEquals(jakarta.persistence.spi.PersistenceUnitTransactionType.JTA, pinfo.getTransactionType()); + assertEquals("managed", PersistenceUnitInfoImpl.toOpenJPAProperties(pinfo).get("openjpa.TransactionMode")); + } + + @Test + public void testFromUserPropertiesAsString() { + assertJta("JTA"); + } + + @Test + public void testFromUserPropertiesAsEnum() { + assertJta(PersistenceUnitTransactionType.JTA); + } + + @Test + public void testFromUserPropertiesAsDeprecatedSpiEnum() { + assertJta(jakarta.persistence.spi.PersistenceUnitTransactionType.JTA); + } + + @Test + public void testDeprecatedSetter() { + PersistenceUnitInfoImpl pinfo = new PersistenceUnitInfoImpl(); + pinfo.setTransactionType(jakarta.persistence.spi.PersistenceUnitTransactionType.JTA); + assertEquals(jakarta.persistence.spi.PersistenceUnitTransactionType.JTA, pinfo.getTransactionType()); + } + + private static void assertJta(Object value) { + PersistenceUnitInfoImpl pinfo = new PersistenceUnitInfoImpl(); + pinfo.fromUserProperties(Map.of(JPAProperties.TRANSACTION_TYPE, value)); + assertEquals(jakarta.persistence.spi.PersistenceUnitTransactionType.JTA, pinfo.getTransactionType()); + } +}