This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 658ce645059 Add optional module for Jakarta Transactions impl of
Jakarta EE 9 Spec (#39881)
658ce645059 is described below
commit 658ce6450590bbb7b0c19fe331457c88d6356832
Author: Hengqian Ling <[email protected]>
AuthorDate: Tue Sep 22 22:31:03 2026 +0800
Add optional module for Jakarta Transactions impl of Jakarta EE 9 Spec
(#39881)
* Add optional module for Jakarta Transactions impl of Jakarta EE 9 Spec
* Restore transformer plugin version and fix review findings for Jakarta
Transactions
* Update documents and BOM
---
RELEASE-NOTES.md | 1 +
bom/pom.xml | 20 ++
.../jakarta-transactions/_index.cn.md | 358 ++++++++++++++++++++
.../jakarta-transactions/_index.en.md | 366 +++++++++++++++++++++
.../jdbc-driver/spring-boot/_index.cn.md | 3 +
.../jdbc-driver/spring-boot/_index.en.md | 3 +
kernel/transaction/type/pom.xml | 1 +
kernel/transaction/type/xa-jakarta/core/pom.xml | 115 +++++++
.../core/JakartaNamespaceTransformationIT.java | 113 +++++++
kernel/transaction/type/{ => xa-jakarta}/pom.xml | 21 +-
.../type/xa-jakarta/provider/atomikos/pom.xml | 123 +++++++
.../atomikos/JakartaNamespaceTransformationIT.java | 113 +++++++
.../type/xa-jakarta/provider/narayana/pom.xml | 129 ++++++++
.../narayana/JakartaNamespaceTransformationIT.java | 113 +++++++
.../type/{ => xa-jakarta/provider}/pom.xml | 9 +-
kernel/transaction/type/xa-jakarta/spi/pom.xml | 115 +++++++
.../spi/JakartaNamespaceTransformationIT.java | 113 +++++++
pom.xml | 1 +
18 files changed, 1708 insertions(+), 9 deletions(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index affba762c46..c675298a3b2 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -9,6 +9,7 @@
### New Features
1. MCP: Add standalone ShardingSphere-MCP Server -
[#38541](https://github.com/apache/shardingsphere/pull/38541)
+1. Transaction: Add optional module for Jakarta Transactions impl of Jakarta
EE 9 Spec - [#26041](https://github.com/apache/shardingsphere/issues/26041)
### CVE
diff --git a/bom/pom.xml b/bom/pom.xml
index 5f5cc79172c..965b8812dde 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -810,6 +810,26 @@
<artifactId>shardingsphere-transaction-xa-narayana</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-jakarta-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-jakarta-atomikos</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-jakarta-narayana</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-global-clock-api</artifactId>
diff --git
a/docs/document/content/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions/_index.cn.md
b/docs/document/content/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions/_index.cn.md
new file mode 100644
index 00000000000..78900689372
--- /dev/null
+++
b/docs/document/content/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions/_index.cn.md
@@ -0,0 +1,358 @@
++++
+title = "Jakarta EE 9 Spec 的 Jakarta Transactions"
+weight = 6
++++
+
+## 背景信息
+
+本页文档所涉及的可选模块均采用 Jakarta EE 9 Spec 的 Jakarta Transactions,兼容 Jakarta EE
9,Jakarta EE 9.1 或 Jakarta EE 10。
+本页文档所涉及的可选模块,旨在解决可选模块 `shardingsphere-transaction-xa` 无法在 Spring Boot
3,Quarkus 3,
+Micronaut Framework 4 或 Helidon 3 等其他基于 Jakarta EE 9+ 的 Web Framework 下使用的问题。
+
+本页文档所涉及的可选模块与 `shardingsphere-transaction-xa` 的约定配置基本一致。
+但相关可选模块无法与 `shardingsphere-transaction-xa` 在同一 classpath,或在同一 Maven 模块使用。
+Java EE 8 或 Jakarta EE 8 不属于本页文档所涉及的可选模块的支持范围,对于类似的情况应考虑使用
`shardingsphere-transaction-xa`。
+
+## JDBC
+
+### Atomikos
+
+#### 前提条件
+
+要在 ShardingSphere 的配置文件中配置 Atomikos 作为 Jakarta EE 9 Spec 的 Jakarta
Transactions 实现,
+可能的 Maven 依赖关系如下,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-jdbc</artifactId>
+ <version>${shardingsphere.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${shardingsphere.version}</version>
+ </dependency>
+</dependencies>
+```
+
+#### 配置
+
+与 `org.apache.shardingsphere:shardingsphere-transaction-xa-core` 一致,可以通过在项目的
classpath 中添加 `jta.properties` 来定制化 Atomikos 配置项。
+
+在 ShardingSphere 的配置文件中,可能的配置项如下,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Atomikos
+```
+
+### Narayana
+
+要在 ShardingSphere 的配置文件中配置 Narayana 作为 Jakarta EE 9 Spec 的 Jakarta
Transactions 实现,
+可能的 Maven 依赖关系如下,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-jdbc</artifactId>
+ <version>${shardingsphere.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${shardingsphere.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-narayana</artifactId>
+ <version>${shardingsphere.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jta</groupId>
+ <artifactId>narayana-jta-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jts</groupId>
+ <artifactId>narayana-jts-integration-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>3.4.3.Final</version>
+ </dependency>
+</dependencies>
+```
+
+#### 配置
+
+与 `org.apache.shardingsphere:shardingsphere-transaction-xa-narayana`
一致,可以通过在项目的 classpath 中添加 `jbossts-properties.xml` 来定制化 Narayana 配置项。
+
+对于 `jbossts-properties.xml` 的最小配置,ShardingSphere 要求定义 Narayana 的
`CoreEnvironmentBean.nodeIdentifier` 属性。
+如果 Narayana 的 object store 并非在不同的 Narayana 实例之间共享,你可以将此值设置为 `1`。一个可能的
`jbossts-properties.xml` 配置如下,
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <entry key="CoreEnvironmentBean.nodeIdentifier">1</entry>
+</properties>
+```
+
+在特定情况下,开发者可能不会希望使用 XML 文件,那开发者需要在自有 Java 项目的启动类手动设置
`CoreEnvironmentBean.nodeIdentifier`。 可参考如下方法调用 Narayana Java API。
+
+```java
+import com.arjuna.ats.arjuna.common.CoreEnvironmentBeanException;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+
+public class ExampleUtils {
+ public void initNarayanaInstance() {
+ try {
+ arjPropertyManager.getCoreEnvironmentBean().setNodeIdentifier("1");
+ } catch (CoreEnvironmentBeanException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
+```
+
+在 ShardingSphere 的配置文件中,可能的配置项如下,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Narayana
+```
+
+## Proxy
+
+以下内容仅作为 ShardingSphere 默认 Maven Profile 的构建配置的参考。
+
+引入前提,ShardingSphere Proxy 默认情况下使用 Jakarta EE 8 Spec 的 Jakarta Transactions 实现。
+
+### Atomikos
+
+如果需要使用 Jakarta EE 9 Spec 的 Jakarta Transactions 的 Atomikos 实现,
+需要更改源代码,并手动编译 binary 或 Linux Container。
+
+对于 `distribution/proxy/pom.xml` 文件的如下部分,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+</dependencies>
+```
+
+需更改为,
+
+```xml
+<dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+</dependencyManagement>
+
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+</dependencies>
+```
+
+仅将 `jakarta.transaction-api` 固定为 `2.0.0`,不要把整个 `jakarta.jakartaee-bom` 覆盖为
`9.0.0`,因为已验证整 BOM 覆盖会把 `jakarta.validation-api` 升级到 `3.0.0`,而 `bval-jsr` 仍使用
`javax.validation` 命名空间,Proxy 启动随即以 `NoClassDefFoundError:
javax/validation/ValidationException` 失败。
+必须替换旧的 XA 依赖,而不是在保留旧依赖的同时追加 Jakarta 依赖。
+使用显式停用 `default-dep` 且不激活 `all`、`transaction-atomikos`、`transaction-narayana`
的命令构建 binary,因为 `default-dep` 为 `activeByDefault`,而 `default-dep` 与 `all` 都会带入旧
Provider,重新制造混合 `javax.transaction`/`jakarta.transaction` 类路径。
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep'
+```
+
+使用相同的 Profile 选择再加上 `docker` Profile 构建容器镜像。
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep,docker'
+```
+
+不要追加 `-T1C` 之类的并行 Reactor 参数,因为 `shardingsphere-proxy-distribution`
与产出其装配所需目录的 `shardingsphere-agent-distribution` 之间没有 Maven Reactor
依赖边,并行构建会在该目录上竞态。
+
+保持 `shardingsphere-proxy-bootstrap` 的 `dev` Profile 处于激活状态,因为它携带方言、权限、模式仓储与
DistSQL 处理器依赖,且不包含旧事务依赖。
+确认构建产物的 `lib` 目录包含
`shardingsphere-transaction-xa-jakarta-core`、`shardingsphere-transaction-xa-jakarta-spi`、`shardingsphere-transaction-xa-jakarta-atomikos`
与 `jakarta.transaction-api-2.0.0.jar`,且不包含
`shardingsphere-transaction-xa-core`、`shardingsphere-transaction-xa-spi`、`shardingsphere-transaction-xa-atomikos`、`shardingsphere-transaction-xa-narayana`。
+正式使用前需验证 Proxy 能够使用所配置的 Provider 正常启动。
+
+对于 Proxy 的 `global.yaml`, 可能的配置项如下,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Atomikos
+```
+
+### Narayana
+
+如果需要使用 Jakarta EE 9 Spec 的 Jakarta Transactions 的 Narayana 实现,需要更改源代码,并手动编译
binary 或 Linux Container。
+
+对于 `distribution/proxy/pom.xml` 文件的如下部分,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+</dependencies>
+```
+
+需更改为,
+
+```xml
+<dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+</dependencyManagement>
+
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-narayana</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jta</groupId>
+ <artifactId>narayana-jta-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jts</groupId>
+ <artifactId>narayana-jts-integration-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>3.4.3.Final</version>
+ </dependency>
+</dependencies>
+```
+
+仅将 `jakarta.transaction-api` 固定为 `2.0.0`,不要把整个 `jakarta.jakartaee-bom` 覆盖为
`9.0.0`,因为已验证整 BOM 覆盖会把 `jakarta.validation-api` 升级到 `3.0.0`,而 `bval-jsr` 仍使用
`javax.validation` 命名空间,Proxy 启动随即以 `NoClassDefFoundError:
javax/validation/ValidationException` 失败。
+Narayana Jakarta 产物必须声明显式版本,因为它们在
`shardingsphere-transaction-xa-jakarta-narayana` 中为 `provided`
范围,不会传递引入,且本模块没有管理其版本的 BOM。
+必须替换旧的 XA 依赖,而不是在保留旧依赖的同时追加 Jakarta 依赖。
+使用显式停用 `default-dep` 且不激活 `all`、`transaction-atomikos`、`transaction-narayana`
的命令构建 binary,因为 `default-dep` 为 `activeByDefault`,而 `default-dep` 与 `all` 都会带入旧
Provider,重新制造混合 `javax.transaction`/`jakarta.transaction` 类路径。
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep'
+```
+
+使用相同的 Profile 选择再加上 `docker` Profile 构建容器镜像。
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep,docker'
+```
+
+不要追加 `-T1C` 之类的并行 Reactor 参数,因为 `shardingsphere-proxy-distribution`
与产出其装配所需目录的 `shardingsphere-agent-distribution` 之间没有 Maven Reactor
依赖边,并行构建会在该目录上竞态。
+
+保持 `shardingsphere-proxy-bootstrap` 的 `dev` Profile 处于激活状态,因为它携带方言、权限、模式仓储与
DistSQL 处理器依赖,且不包含旧事务依赖。
+确认构建产物的 `lib` 目录在 Jakarta core、SPI 与事务 API 之外还包含
`shardingsphere-transaction-xa-jakarta-narayana` 与
`narayana-jta-jakarta-5.12.7.Final.jar`,且不包含
`shardingsphere-transaction-xa-core`、`shardingsphere-transaction-xa-spi`、`shardingsphere-transaction-xa-atomikos`、`shardingsphere-transaction-xa-narayana`。
+正式使用前需验证 Proxy 能够使用所配置的 Provider 正常启动。
+
+对于 Proxy 的 `global.yaml`, 可能的配置项如下,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Narayana
+```
+
+对于最小配置,仍需通过与 `global.yaml` 处于同一目录的 `jbossts-properties.xml` 配置 Narayana 的
`CoreEnvironmentBean.nodeIdentifier` 属性。
+
+## Proxy Native
+
+处理方式与 ShardingSphere Proxy 一致。
diff --git
a/docs/document/content/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions/_index.en.md
b/docs/document/content/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions/_index.en.md
new file mode 100644
index 00000000000..8a8f34748f3
--- /dev/null
+++
b/docs/document/content/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions/_index.en.md
@@ -0,0 +1,366 @@
++++
+title = "Jakarta Transactions of Jakarta EE 9 Spec"
+weight = 6
++++
+
+## Background Information
+
+The optional modules mentioned in this document all use Jakarta Transactions
of Jakarta EE 9 Spec and are compatible with Jakarta EE 9,
+Jakarta EE 9.1 or Jakarta EE 10.
+The optional modules mentioned in this document are designed to solve the
problem that the optional module `shardingsphere-transaction-xa` cannot be used
in other Web Frameworks based on Jakarta EE 9+,
+such as Spring Boot 3, Quarkus 3, Micronaut Framework 4 or Helidon 3.
+
+The optional modules mentioned in this document are basically consistent with
the agreed configuration of `shardingsphere-transaction-xa`.
+However, the relevant optional modules cannot be used in the same classpath or
in the same Maven module as `shardingsphere-transaction-xa`.
+Java EE 8 or Jakarta EE 8 are not supported by the optional modules mentioned
in this document. For similar situations, you should consider using
`shardingsphere-transaction-xa`.
+
+## JDBC
+
+### Atomikos
+
+#### Prerequisites
+
+To configure Atomikos as the Jakarta Transactions implementation of the
Jakarta EE 9 Spec in the ShardingSphere configuration file,
+the possible Maven dependencies are as follows,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-jdbc</artifactId>
+ <version>${shardingsphere.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${shardingsphere.version}</version>
+ </dependency>
+</dependencies>
+```
+
+#### Configuration
+
+As with `org.apache.shardingsphere:shardingsphere-transaction-xa-core`,
+you can customize Atomikos configuration items by adding `jta.properties` to
the project's classpath.
+
+In the ShardingSphere configuration file, possible configuration items are as
follows,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Atomikos
+```
+
+### Narayana
+
+To configure Narayana as the Jakarta Transactions implementation of the
Jakarta EE 9 Spec in ShardingSphere's configuration file,
+the possible Maven dependencies are as follows,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-jdbc</artifactId>
+ <version>${shardingsphere.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${shardingsphere.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-narayana</artifactId>
+ <version>${shardingsphere.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jta</groupId>
+ <artifactId>narayana-jta-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jts</groupId>
+ <artifactId>narayana-jts-integration-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>3.4.3.Final</version>
+ </dependency>
+</dependencies>
+```
+
+#### Configuration
+
+In line with
`org.apache.shardingsphere:shardingsphere-transaction-xa-narayana`,
+Narayana configuration items can be customized by adding
`jbossts-properties.xml` to the project's classpath.
+
+For the minimal configuration of `jbossts-properties.xml`, ShardingSphere
requires the definition of Narayana's `CoreEnvironmentBean.nodeIdentifier`
property.
+If Narayana's object store is not shared between different Narayana instances,
you can set this value to `1`.
+A possible `jbossts-properties.xml` configuration is as follows,
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <entry key="CoreEnvironmentBean.nodeIdentifier">1</entry>
+</properties>
+```
+
+In certain cases, developers may not want to use XML files,
+then developers need to manually set `CoreEnvironmentBean.nodeIdentifier` in
the startup class of their own Java project.
+You can refer to the following method to call the Narayana Java API.
+
+```java
+import com.arjuna.ats.arjuna.common.CoreEnvironmentBeanException;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+
+public class ExampleUtils {
+ public void initNarayanaInstance() {
+ try {
+ arjPropertyManager.getCoreEnvironmentBean().setNodeIdentifier("1");
+ } catch (CoreEnvironmentBeanException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
+```
+
+In the ShardingSphere configuration file, possible configuration items are as
follows:
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Narayana
+```
+
+## Proxy
+
+The following content is only a reference for the build configuration of
ShardingSphere's default Maven Profile.
+
+Introduction premise, ShardingSphere Proxy uses the Jakarta Transactions
implementation of the Jakarta EE 8 Spec by default.
+
+### Atomikos
+
+If you need to use the Atomikos implementation of Jakarta Transactions of the
Jakarta EE 9 Spec,
+you need to change the source code and manually compile the binary or Linux
Container.
+
+For the following part of the `distribution/proxy/pom.xml` file,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+</dependencies>
+```
+
+Need to be changed to,
+
+```xml
+<dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+</dependencyManagement>
+
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+</dependencies>
+```
+
+Pin only `jakarta.transaction-api` to `2.0.0` instead of overriding the whole
`jakarta.jakartaee-bom` to `9.0.0`, because the whole-BOM override was verified
to upgrade `jakarta.validation-api` to `3.0.0` while `bval-jsr` still uses the
`javax.validation` namespace, and Proxy then fails at startup with
`NoClassDefFoundError: javax/validation/ValidationException`.
+Replace the legacy XA dependencies instead of adding the Jakarta dependencies
alongside them.
+Build the binary with an invocation that explicitly deactivates `default-dep`
and does not activate `all`, `transaction-atomikos`, or `transaction-narayana`,
because `default-dep` is `activeByDefault` and both `default-dep` and `all` add
a legacy provider that recreates the mixed
`javax.transaction`/`jakarta.transaction` classpath.
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep'
+```
+
+Build the container image with the same profile selection plus the `docker`
profile.
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep,docker'
+```
+
+Do not add a parallel reactor flag such as `-T1C`, because no Maven reactor
dependency edge connects `shardingsphere-proxy-distribution` to
`shardingsphere-agent-distribution` whose output directory the Proxy assembly
consumes, and parallel builds race on that directory.
+
+Keep the `dev` profile of `shardingsphere-proxy-bootstrap` active, because it
carries the dialect, authority, mode repository, and DistSQL handler
dependencies and contains no legacy transaction dependency.
+Verify that the built `lib` directory contains
`shardingsphere-transaction-xa-jakarta-core`,
`shardingsphere-transaction-xa-jakarta-spi`,
`shardingsphere-transaction-xa-jakarta-atomikos`, and
`jakarta.transaction-api-2.0.0.jar`, and that it contains neither
`shardingsphere-transaction-xa-core`, `shardingsphere-transaction-xa-spi`,
`shardingsphere-transaction-xa-atomikos`, nor
`shardingsphere-transaction-xa-narayana`.
+Verify that Proxy starts successfully with the configured provider before
using it.
+
+For Proxy's `global.yaml`, possible configuration items are as follows,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Atomikos
+```
+
+### Narayana
+
+If you need to use the Narayana implementation of Jakarta Transactions with
the Jakarta EE 9 Spec,
+you need to modify the source code and manually compile the binary or Linux
Container.
+
+For the following part of the `distribution/proxy/pom.xml` file,
+
+```xml
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+</dependencies>
+```
+
+Need to be changed to,
+
+```xml
+<dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+</dependencyManagement>
+
+<dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-proxy-bootstrap</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-narayana</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jta</groupId>
+ <artifactId>narayana-jta-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jts</groupId>
+ <artifactId>narayana-jts-integration-jakarta</artifactId>
+ <version>5.12.7.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>3.4.3.Final</version>
+ </dependency>
+</dependencies>
+```
+
+Pin only `jakarta.transaction-api` to `2.0.0` instead of overriding the whole
`jakarta.jakartaee-bom` to `9.0.0`, because the whole-BOM override was verified
to upgrade `jakarta.validation-api` to `3.0.0` while `bval-jsr` still uses the
`javax.validation` namespace, and Proxy then fails at startup with
`NoClassDefFoundError: javax/validation/ValidationException`.
+Declare explicit versions for the Narayana Jakarta artifacts, because they are
`provided` scope in `shardingsphere-transaction-xa-jakarta-narayana` and
therefore do not arrive transitively, and no repository BOM manages them for
this module.
+Replace the legacy XA dependencies instead of adding the Jakarta dependencies
alongside them.
+Build the binary with an invocation that explicitly deactivates `default-dep`
and does not activate `all`, `transaction-atomikos`, or `transaction-narayana`,
because `default-dep` is `activeByDefault` and both `default-dep` and `all` add
a legacy provider that recreates the mixed
`javax.transaction`/`jakarta.transaction` classpath.
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep'
+```
+
+Build the container image with the same profile selection plus the `docker`
profile.
+
+```shell
+./mvnw clean package -pl distribution/proxy,distribution/agent -am -DskipTests
-P 'release,!default-dep,docker'
+```
+
+Do not add a parallel reactor flag such as `-T1C`, because no Maven reactor
dependency edge connects `shardingsphere-proxy-distribution` to
`shardingsphere-agent-distribution` whose output directory the Proxy assembly
consumes, and parallel builds race on that directory.
+
+Keep the `dev` profile of `shardingsphere-proxy-bootstrap` active, because it
carries the dialect, authority, mode repository, and DistSQL handler
dependencies and contains no legacy transaction dependency.
+Verify that the built `lib` directory contains
`shardingsphere-transaction-xa-jakarta-narayana` and
`narayana-jta-jakarta-5.12.7.Final.jar` in addition to the Jakarta core, SPI,
and transaction API jars, and that it contains neither
`shardingsphere-transaction-xa-core`, `shardingsphere-transaction-xa-spi`,
`shardingsphere-transaction-xa-atomikos`, nor
`shardingsphere-transaction-xa-narayana`.
+Verify that Proxy starts successfully with the configured provider before
using it.
+
+For Proxy's `global.yaml`, possible configuration items are as follows,
+
+```yaml
+transaction:
+ defaultType: XA
+ providerType: Narayana
+```
+
+For a minimal configuration,
+you still need to configure Narayana's `CoreEnvironmentBean.nodeIdentifier`
property via `jbossts-properties.xml` in the same directory as `global.yaml`.
+
+## Proxy Native
+
+The processing method is the same as ShardingSphere Proxy.
diff --git
a/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.cn.md
b/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.cn.md
index 1e42de9daf4..ae9e6901bcb 100644
---
a/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.cn.md
+++
b/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.cn.md
@@ -40,6 +40,9 @@ spring.datasource.url=jdbc:shardingsphere:classpath:xxx.yaml
ShardingSphere 的 XA 分布式事务尚未在 Spring Boot 3+ 上就绪,此限制同样适用于其他基于 Jakarta EE 9+ 的
Web Framework,如
Quarkus 3,Micronaut Framework 4 和 Helidon 3+。
+若需在 Spring Boot 3+ 下使用 ShardingSphere 的 XA 分布式事务,请参考
+[Jakarta EE 9 Spec 的 Jakarta
Transactions](/cn/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions)。
+
用户仅需要配置如下。
```xml
diff --git
a/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.en.md
b/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.en.md
index c4640fc48bd..f18bebae759 100644
---
a/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.en.md
+++
b/docs/document/content/user-manual/shardingsphere-jdbc/yaml-config/jdbc-driver/spring-boot/_index.en.md
@@ -41,6 +41,9 @@ ShardingSphere's XA distributed transactions are not yet
ready for Spring Boot 3
This limitation also applies to other Jakarta EE 9+ based web frameworks,
such as Quarkus 3, Micronaut Framework 4, and Helidon 3+.
+If you need to use ShardingSphere's XA distributed transactions under Spring
Boot 3+,
+please refer to [Jakarta Transactions of Jakarta EE 9
Spec](/en/user-manual/shardingsphere-jdbc/optional-plugins/jakarta-transactions).
+
Users only need to configure the following.
```xml
diff --git a/kernel/transaction/type/pom.xml b/kernel/transaction/type/pom.xml
index c8a8e4a5e69..1fdbb491c36 100644
--- a/kernel/transaction/type/pom.xml
+++ b/kernel/transaction/type/pom.xml
@@ -29,6 +29,7 @@
<modules>
<module>xa</module>
+ <module>xa-jakarta</module>
<module>base</module>
</modules>
</project>
diff --git a/kernel/transaction/type/xa-jakarta/core/pom.xml
b/kernel/transaction/type/xa-jakarta/core/pom.xml
new file mode 100644
index 00000000000..26683011562
--- /dev/null
+++ b/kernel/transaction/type/xa-jakarta/core/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta</artifactId>
+ <version>5.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>shardingsphere-transaction-xa-jakarta-core</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-jakarta-atomikos</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-core</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.transformer</groupId>
+ <artifactId>transformer-maven-plugin</artifactId>
+ <version>${transformer-maven-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <rules>
+ <jakartaDefaults>true</jakartaDefaults>
+ </rules>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-core</artifactId>
+ <version>${project.version}</version>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>javadoc-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <skip>${maven.javadoc.skip}</skip>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-core</artifactId>
+ <version>${project.version}</version>
+ <classifier>javadoc</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>source-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-core</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/kernel/transaction/type/xa-jakarta/core/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/core/JakartaNamespaceTransformationIT.java
b/kernel/transaction/type/xa-jakarta/core/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/core/JakartaNamespaceTransformationIT.java
new file mode 100644
index 00000000000..c0431223bc2
--- /dev/null
+++
b/kernel/transaction/type/xa-jakarta/core/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/core/JakartaNamespaceTransformationIT.java
@@ -0,0 +1,113 @@
+/*
+ * 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.shardingsphere.transaction.xa.jakarta.core;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the Eclipse Transformer has rewritten the Jakarta EE 8 {@code
javax.transaction} namespace to
+ * {@code jakarta.transaction} in the classes produced for this module. The
JDK-provided {@code javax.transaction.xa}
+ * subpackage ({@code XAResource}, {@code Xid}, {@code XAException}) must
remain unchanged, as it is part of the
+ * {@code java.transaction.xa} module and is not renamed by the Jakarta EE 9
transition.
+ */
+class JakartaNamespaceTransformationIT {
+
+ private static final byte[] JAVAX_TRANSACTION =
"javax/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ private static final byte[] JAKARTA_TRANSACTION =
"jakarta/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ @Test
+ void assertNoJakartaEE8NamespaceRemains() throws IOException {
+ Path artifact = findMainArtifact();
+ try (JarFile jarFile = new JarFile(artifact.toFile())) {
+ Collection<byte[]> actualClassBytes =
jarFile.stream().filter(entry -> entry.getName().endsWith(".class")).map(entry
-> readEntry(jarFile, entry)).collect(Collectors.toList());
+ assertFalse(actualClassBytes.isEmpty());
+ assertTrue(actualClassBytes.stream().anyMatch(bytes ->
indexOf(bytes, JAKARTA_TRANSACTION, 0) >= 0));
+
assertTrue(actualClassBytes.stream().noneMatch(JakartaNamespaceTransformationIT::hasJakartaEE8Reference));
+ }
+ }
+
+ private Path findMainArtifact() throws IOException {
+ try (Stream<Path> stream = Files.list(Paths.get("target"))) {
+ return stream.filter(path -> path.toString().endsWith(".jar"))
+ .filter(path -> !path.toString().contains("-sources"))
+ .filter(path -> !path.toString().contains("-javadoc"))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No main
artifact jar was found in target"));
+ }
+ }
+
+ private static byte[] readEntry(final JarFile jarFile, final JarEntry
jarEntry) {
+ try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ byte[] block = new byte[8192];
+ int read;
+ while ((read = inputStream.read(block)) != -1) {
+ buffer.write(block, 0, read);
+ }
+ return buffer.toByteArray();
+ } catch (final IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private static boolean hasJakartaEE8Reference(final byte[] bytes) {
+ int idx = indexOf(bytes, JAVAX_TRANSACTION, 0);
+ while (idx >= 0) {
+ int after = idx + JAVAX_TRANSACTION.length;
+ if (after < bytes.length && bytes[after] >= 'A' && bytes[after] <=
'Z') {
+ return true;
+ }
+ idx = indexOf(bytes, JAVAX_TRANSACTION, after);
+ }
+ return false;
+ }
+
+ private static int indexOf(final byte[] haystack, final byte[] needle,
final int from) {
+ for (int i = from; i <= haystack.length - needle.length; i++) {
+ boolean match = true;
+ for (int j = 0; j < needle.length; j++) {
+ if (haystack[i + j] != needle[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/kernel/transaction/type/pom.xml
b/kernel/transaction/type/xa-jakarta/pom.xml
similarity index 62%
copy from kernel/transaction/type/pom.xml
copy to kernel/transaction/type/xa-jakarta/pom.xml
index c8a8e4a5e69..83847a8435e 100644
--- a/kernel/transaction/type/pom.xml
+++ b/kernel/transaction/type/xa-jakarta/pom.xml
@@ -20,15 +20,28 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.shardingsphere</groupId>
- <artifactId>shardingsphere-transaction</artifactId>
+ <artifactId>shardingsphere-transaction-type</artifactId>
<version>5.5.4-SNAPSHOT</version>
</parent>
- <artifactId>shardingsphere-transaction-type</artifactId>
+ <artifactId>shardingsphere-transaction-xa-jakarta</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<modules>
- <module>xa</module>
- <module>base</module>
+ <module>spi</module>
+ <module>provider</module>
+ <module>core</module>
</modules>
+
+ <properties>
+ <!--
+ As a workaround for
https://github.com/apache/shardingsphere/issues/26041 ,
+ versions of Jakarta EE Spec dependencies are maintained separately in
this module and its submodules.
+ -->
+ <jakarta.jakartaee-bom.version>9.0.0</jakarta.jakartaee-bom.version>
+ <glassfish-jaxb.version>3.0.2</glassfish-jaxb.version>
+ <atomikos.version>6.0.0</atomikos.version>
+ <narayana.version>5.12.7.Final</narayana.version>
+ <jboss-logging.version>3.4.3.Final</jboss-logging.version>
+ </properties>
</project>
diff --git a/kernel/transaction/type/xa-jakarta/provider/atomikos/pom.xml
b/kernel/transaction/type/xa-jakarta/provider/atomikos/pom.xml
new file mode 100644
index 00000000000..b92f7c6f666
--- /dev/null
+++ b/kernel/transaction/type/xa-jakarta/provider/atomikos/pom.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-provider</artifactId>
+ <version>5.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>shardingsphere-transaction-xa-jakarta-atomikos</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.atomikos</groupId>
+ <artifactId>transactions-jta</artifactId>
+ <version>${atomikos.version}</version>
+ <classifier>jakarta</classifier>
+ </dependency>
+ <dependency>
+ <groupId>com.atomikos</groupId>
+ <artifactId>transactions-jdbc</artifactId>
+ <version>${atomikos.version}</version>
+ <classifier>jakarta</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.transformer</groupId>
+ <artifactId>transformer-maven-plugin</artifactId>
+ <version>${transformer-maven-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <rules>
+ <jakartaDefaults>true</jakartaDefaults>
+ </rules>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ <version>${project.version}</version>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>javadoc-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <skip>${maven.javadoc.skip}</skip>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ <version>${project.version}</version>
+ <classifier>javadoc</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>source-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-atomikos</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/kernel/transaction/type/xa-jakarta/provider/atomikos/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/atomikos/JakartaNamespaceTransformationIT.java
b/kernel/transaction/type/xa-jakarta/provider/atomikos/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/atomikos/JakartaNamespaceTransformationIT.java
new file mode 100644
index 00000000000..629a1ed65ed
--- /dev/null
+++
b/kernel/transaction/type/xa-jakarta/provider/atomikos/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/atomikos/JakartaNamespaceTransformationIT.java
@@ -0,0 +1,113 @@
+/*
+ * 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.shardingsphere.transaction.xa.jakarta.atomikos;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the Eclipse Transformer has rewritten the Jakarta EE 8 {@code
javax.transaction} namespace to
+ * {@code jakarta.transaction} in the classes produced for this module. The
JDK-provided {@code javax.transaction.xa}
+ * subpackage ({@code XAResource}, {@code Xid}, {@code XAException}) must
remain unchanged, as it is part of the
+ * {@code java.transaction.xa} module and is not renamed by the Jakarta EE 9
transition.
+ */
+class JakartaNamespaceTransformationIT {
+
+ private static final byte[] JAVAX_TRANSACTION =
"javax/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ private static final byte[] JAKARTA_TRANSACTION =
"jakarta/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ @Test
+ void assertNoJakartaEE8NamespaceRemains() throws IOException {
+ Path artifact = findMainArtifact();
+ try (JarFile jarFile = new JarFile(artifact.toFile())) {
+ Collection<byte[]> actualClassBytes =
jarFile.stream().filter(entry -> entry.getName().endsWith(".class")).map(entry
-> readEntry(jarFile, entry)).collect(Collectors.toList());
+ assertFalse(actualClassBytes.isEmpty());
+ assertTrue(actualClassBytes.stream().anyMatch(bytes ->
indexOf(bytes, JAKARTA_TRANSACTION, 0) >= 0));
+
assertTrue(actualClassBytes.stream().noneMatch(JakartaNamespaceTransformationIT::hasJakartaEE8Reference));
+ }
+ }
+
+ private Path findMainArtifact() throws IOException {
+ try (Stream<Path> stream = Files.list(Paths.get("target"))) {
+ return stream.filter(path -> path.toString().endsWith(".jar"))
+ .filter(path -> !path.toString().contains("-sources"))
+ .filter(path -> !path.toString().contains("-javadoc"))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No main
artifact jar was found in target"));
+ }
+ }
+
+ private static byte[] readEntry(final JarFile jarFile, final JarEntry
jarEntry) {
+ try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ byte[] block = new byte[8192];
+ int read;
+ while ((read = inputStream.read(block)) != -1) {
+ buffer.write(block, 0, read);
+ }
+ return buffer.toByteArray();
+ } catch (final IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private static boolean hasJakartaEE8Reference(final byte[] bytes) {
+ int idx = indexOf(bytes, JAVAX_TRANSACTION, 0);
+ while (idx >= 0) {
+ int after = idx + JAVAX_TRANSACTION.length;
+ if (after < bytes.length && bytes[after] >= 'A' && bytes[after] <=
'Z') {
+ return true;
+ }
+ idx = indexOf(bytes, JAVAX_TRANSACTION, after);
+ }
+ return false;
+ }
+
+ private static int indexOf(final byte[] haystack, final byte[] needle,
final int from) {
+ for (int i = from; i <= haystack.length - needle.length; i++) {
+ boolean match = true;
+ for (int j = 0; j < needle.length; j++) {
+ if (haystack[i + j] != needle[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/kernel/transaction/type/xa-jakarta/provider/narayana/pom.xml
b/kernel/transaction/type/xa-jakarta/provider/narayana/pom.xml
new file mode 100644
index 00000000000..56e19eaca8b
--- /dev/null
+++ b/kernel/transaction/type/xa-jakarta/provider/narayana/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-provider</artifactId>
+ <version>5.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>shardingsphere-transaction-xa-jakarta-narayana</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.narayana.jta</groupId>
+ <artifactId>narayana-jta-jakarta</artifactId>
+ <version>${narayana.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.narayana.jts</groupId>
+ <artifactId>narayana-jts-integration-jakarta</artifactId>
+ <version>${narayana.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>${jboss-logging.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.transformer</groupId>
+ <artifactId>transformer-maven-plugin</artifactId>
+ <version>${transformer-maven-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <rules>
+ <jakartaDefaults>true</jakartaDefaults>
+ </rules>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ <version>${project.version}</version>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>javadoc-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <skip>${maven.javadoc.skip}</skip>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ <version>${project.version}</version>
+ <classifier>javadoc</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>source-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-narayana</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/kernel/transaction/type/xa-jakarta/provider/narayana/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/narayana/JakartaNamespaceTransformationIT.java
b/kernel/transaction/type/xa-jakarta/provider/narayana/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/narayana/JakartaNamespaceTransformationIT.java
new file mode 100644
index 00000000000..5336fa7fde9
--- /dev/null
+++
b/kernel/transaction/type/xa-jakarta/provider/narayana/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/narayana/JakartaNamespaceTransformationIT.java
@@ -0,0 +1,113 @@
+/*
+ * 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.shardingsphere.transaction.xa.jakarta.narayana;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the Eclipse Transformer has rewritten the Jakarta EE 8 {@code
javax.transaction} namespace to
+ * {@code jakarta.transaction} in the classes produced for this module. The
JDK-provided {@code javax.transaction.xa}
+ * subpackage ({@code XAResource}, {@code Xid}, {@code XAException}) must
remain unchanged, as it is part of the
+ * {@code java.transaction.xa} module and is not renamed by the Jakarta EE 9
transition.
+ */
+class JakartaNamespaceTransformationIT {
+
+ private static final byte[] JAVAX_TRANSACTION =
"javax/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ private static final byte[] JAKARTA_TRANSACTION =
"jakarta/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ @Test
+ void assertNoJakartaEE8NamespaceRemains() throws IOException {
+ Path artifact = findMainArtifact();
+ try (JarFile jarFile = new JarFile(artifact.toFile())) {
+ Collection<byte[]> actualClassBytes =
jarFile.stream().filter(entry -> entry.getName().endsWith(".class")).map(entry
-> readEntry(jarFile, entry)).collect(Collectors.toList());
+ assertFalse(actualClassBytes.isEmpty());
+ assertTrue(actualClassBytes.stream().anyMatch(bytes ->
indexOf(bytes, JAKARTA_TRANSACTION, 0) >= 0));
+
assertTrue(actualClassBytes.stream().noneMatch(JakartaNamespaceTransformationIT::hasJakartaEE8Reference));
+ }
+ }
+
+ private Path findMainArtifact() throws IOException {
+ try (Stream<Path> stream = Files.list(Paths.get("target"))) {
+ return stream.filter(path -> path.toString().endsWith(".jar"))
+ .filter(path -> !path.toString().contains("-sources"))
+ .filter(path -> !path.toString().contains("-javadoc"))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No main
artifact jar was found in target"));
+ }
+ }
+
+ private static byte[] readEntry(final JarFile jarFile, final JarEntry
jarEntry) {
+ try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ byte[] block = new byte[8192];
+ int read;
+ while ((read = inputStream.read(block)) != -1) {
+ buffer.write(block, 0, read);
+ }
+ return buffer.toByteArray();
+ } catch (final IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private static boolean hasJakartaEE8Reference(final byte[] bytes) {
+ int idx = indexOf(bytes, JAVAX_TRANSACTION, 0);
+ while (idx >= 0) {
+ int after = idx + JAVAX_TRANSACTION.length;
+ if (after < bytes.length && bytes[after] >= 'A' && bytes[after] <=
'Z') {
+ return true;
+ }
+ idx = indexOf(bytes, JAVAX_TRANSACTION, after);
+ }
+ return false;
+ }
+
+ private static int indexOf(final byte[] haystack, final byte[] needle,
final int from) {
+ for (int i = from; i <= haystack.length - needle.length; i++) {
+ boolean match = true;
+ for (int j = 0; j < needle.length; j++) {
+ if (haystack[i + j] != needle[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/kernel/transaction/type/pom.xml
b/kernel/transaction/type/xa-jakarta/provider/pom.xml
similarity index 86%
copy from kernel/transaction/type/pom.xml
copy to kernel/transaction/type/xa-jakarta/provider/pom.xml
index c8a8e4a5e69..ce680f04f28 100644
--- a/kernel/transaction/type/pom.xml
+++ b/kernel/transaction/type/xa-jakarta/provider/pom.xml
@@ -20,15 +20,14 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.shardingsphere</groupId>
- <artifactId>shardingsphere-transaction</artifactId>
+ <artifactId>shardingsphere-transaction-xa-jakarta</artifactId>
<version>5.5.4-SNAPSHOT</version>
</parent>
- <artifactId>shardingsphere-transaction-type</artifactId>
+ <artifactId>shardingsphere-transaction-xa-jakarta-provider</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
-
<modules>
- <module>xa</module>
- <module>base</module>
+ <module>atomikos</module>
+ <module>narayana</module>
</modules>
</project>
diff --git a/kernel/transaction/type/xa-jakarta/spi/pom.xml
b/kernel/transaction/type/xa-jakarta/spi/pom.xml
new file mode 100644
index 00000000000..99973bb1e0c
--- /dev/null
+++ b/kernel/transaction/type/xa-jakarta/spi/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-jakarta</artifactId>
+ <version>5.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>shardingsphere-transaction-xa-jakarta-spi</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>jakarta.transaction</groupId>
+ <artifactId>jakarta.transaction-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.transformer</groupId>
+ <artifactId>transformer-maven-plugin</artifactId>
+ <version>${transformer-maven-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <rules>
+ <jakartaDefaults>true</jakartaDefaults>
+ </rules>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ <version>${project.version}</version>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>javadoc-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <skip>${maven.javadoc.skip}</skip>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ <version>${project.version}</version>
+ <classifier>javadoc</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ <execution>
+ <id>source-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <phase>verify</phase>
+ <configuration>
+ <artifact>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-transaction-xa-spi</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </artifact>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/kernel/transaction/type/xa-jakarta/spi/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/spi/JakartaNamespaceTransformationIT.java
b/kernel/transaction/type/xa-jakarta/spi/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/spi/JakartaNamespaceTransformationIT.java
new file mode 100644
index 00000000000..a5889a775cd
--- /dev/null
+++
b/kernel/transaction/type/xa-jakarta/spi/src/test/java/org/apache/shardingsphere/transaction/xa/jakarta/spi/JakartaNamespaceTransformationIT.java
@@ -0,0 +1,113 @@
+/*
+ * 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.shardingsphere.transaction.xa.jakarta.spi;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the Eclipse Transformer has rewritten the Jakarta EE 8 {@code
javax.transaction} namespace to
+ * {@code jakarta.transaction} in the classes produced for this module. The
JDK-provided {@code javax.transaction.xa}
+ * subpackage ({@code XAResource}, {@code Xid}, {@code XAException}) must
remain unchanged, as it is part of the
+ * {@code java.transaction.xa} module and is not renamed by the Jakarta EE 9
transition.
+ */
+class JakartaNamespaceTransformationIT {
+
+ private static final byte[] JAVAX_TRANSACTION =
"javax/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ private static final byte[] JAKARTA_TRANSACTION =
"jakarta/transaction/".getBytes(StandardCharsets.UTF_8);
+
+ @Test
+ void assertNoJakartaEE8NamespaceRemains() throws IOException {
+ Path artifact = findMainArtifact();
+ try (JarFile jarFile = new JarFile(artifact.toFile())) {
+ Collection<byte[]> actualClassBytes =
jarFile.stream().filter(entry -> entry.getName().endsWith(".class")).map(entry
-> readEntry(jarFile, entry)).collect(Collectors.toList());
+ assertFalse(actualClassBytes.isEmpty());
+ assertTrue(actualClassBytes.stream().anyMatch(bytes ->
indexOf(bytes, JAKARTA_TRANSACTION, 0) >= 0));
+
assertTrue(actualClassBytes.stream().noneMatch(JakartaNamespaceTransformationIT::hasJakartaEE8Reference));
+ }
+ }
+
+ private Path findMainArtifact() throws IOException {
+ try (Stream<Path> stream = Files.list(Paths.get("target"))) {
+ return stream.filter(path -> path.toString().endsWith(".jar"))
+ .filter(path -> !path.toString().contains("-sources"))
+ .filter(path -> !path.toString().contains("-javadoc"))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No main
artifact jar was found in target"));
+ }
+ }
+
+ private static byte[] readEntry(final JarFile jarFile, final JarEntry
jarEntry) {
+ try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ byte[] block = new byte[8192];
+ int read;
+ while ((read = inputStream.read(block)) != -1) {
+ buffer.write(block, 0, read);
+ }
+ return buffer.toByteArray();
+ } catch (final IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private static boolean hasJakartaEE8Reference(final byte[] bytes) {
+ int idx = indexOf(bytes, JAVAX_TRANSACTION, 0);
+ while (idx >= 0) {
+ int after = idx + JAVAX_TRANSACTION.length;
+ if (after < bytes.length && bytes[after] >= 'A' && bytes[after] <=
'Z') {
+ return true;
+ }
+ idx = indexOf(bytes, JAVAX_TRANSACTION, after);
+ }
+ return false;
+ }
+
+ private static int indexOf(final byte[] haystack, final byte[] needle,
final int from) {
+ for (int i = from; i <= haystack.length - needle.length; i++) {
+ boolean match = true;
+ for (int j = 0; j < needle.length; j++) {
+ if (haystack[i + j] != needle[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/pom.xml b/pom.xml
index bc9db9433fc..55589f82bda 100644
--- a/pom.xml
+++ b/pom.xml
@@ -156,6 +156,7 @@
<dockerfile-maven.version>1.4.13</dockerfile-maven.version>
<os-detector-maven-plugin.version>0.3.1</os-detector-maven-plugin.version>
<native-maven-plugin.version>1.1.12</native-maven-plugin.version>
+
<transformer-maven-plugin.version>1.0.0</transformer-maven-plugin.version>
<!-- Compile plugin versions -->
<maven-antrun-plugin.version>3.1.0</maven-antrun-plugin.version>