diff --git a/docs/src/main/asciidoc/transaction.adoc b/docs/src/main/asciidoc/transaction.adoc
index efed7ffa0cff6d..067636af544f54 100644
--- a/docs/src/main/asciidoc/transaction.adoc
+++ b/docs/src/main/asciidoc/transaction.adoc
@@ -307,6 +307,9 @@ The node name identifier needs to be unique per transaction manager deployment.
And the node identifier needs to be stable over the transaction manager restarts.
The node name identifier may be configured via the property `quarkus.transaction-manager.node-name`.
+The node-name property has a length limitation, it cannot be longer than 28 bytes.
+The length limitation can possibly be solved by enabling the property 'quarkus.transaction-manager.shortenNodeNameIfNecessary' which, when enabled, will shorten name longer than 28 bytes.
+The shortening process is done by applying the 'SHA-224' algorithm, encoding to Base64 and then truncating the result.
[[transaction-scope]]
== Using `@TransactionScoped` to bind CDI beans to the transaction lifecycle
diff --git a/extensions/narayana-jta/runtime/pom.xml b/extensions/narayana-jta/runtime/pom.xml
index fdd82659db7e49..a6b76942406b03 100644
--- a/extensions/narayana-jta/runtime/pom.xml
+++ b/extensions/narayana-jta/runtime/pom.xml
@@ -83,6 +83,17 @@
org.jboss.narayana.jts
narayana-jts-integration
+
+
+ io.quarkus
+ quarkus-junit5-internal
+ test
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
diff --git a/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorder.java b/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorder.java
index 156dbd6d1c8654..3363fb1276547f 100644
--- a/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorder.java
+++ b/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorder.java
@@ -5,6 +5,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -60,7 +61,15 @@ private static void shortenNodeName(TransactionManagerConfiguration transactions
HASH_ALGORITHM_FOR_SHORTENING);
final byte[] nodeNameAsBytes = originalNodeName.getBytes();
MessageDigest messageDigest224 = MessageDigest.getInstance(HASH_ALGORITHM_FOR_SHORTENING);
- transactions.nodeName = new String(messageDigest224.digest(nodeNameAsBytes), StandardCharsets.UTF_8);
+ byte[] hashedByteArray = messageDigest224.digest(nodeNameAsBytes);
+
+ //Encode the byte array in Base64
+ //encoding the array might result in a longer array
+ byte[] base64Result = Base64.getEncoder().encode(hashedByteArray);
+ //truncate the array
+ byte[] slice = Arrays.copyOfRange(base64Result, 0, 28);
+
+ transactions.nodeName = new String(slice, StandardCharsets.UTF_8);
log.warnf("New node name is \"%s\"", transactions.nodeName);
}
diff --git a/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java b/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java
index 6719ea8e1d128d..cad532cc6d9a4f 100644
--- a/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java
+++ b/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java
@@ -27,7 +27,7 @@ public final class TransactionManagerConfiguration {
* Whether the node name should be shortened if necessary.
* The node name must not exceed a length of 28 bytes. If this property is set to {@code true}, and the node name exceeds 28
* bytes, the node name is shortened by calculating the SHA-224 hash,
- * which has a length of 28 bytes.
+ * which has a length of 28 bytes, encoded to Base64 format and then shorten to 28 bytes.
*
* @see #nodeName
*/
diff --git a/extensions/narayana-jta/runtime/src/test/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorderTest.java b/extensions/narayana-jta/runtime/src/test/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorderTest.java
new file mode 100644
index 00000000000000..208b1595957520
--- /dev/null
+++ b/extensions/narayana-jta/runtime/src/test/java/io/quarkus/narayana/jta/runtime/NarayanaJtaRecorderTest.java
@@ -0,0 +1,39 @@
+package io.quarkus.narayana.jta.runtime;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.nio.charset.StandardCharsets;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.junit.jupiter.api.Test;
+
+public class NarayanaJtaRecorderTest {
+
+ @Test
+ void testByteLength() {
+ TransactionManagerConfiguration transactions = new TransactionManagerConfiguration();
+ transactions.shortenNodeNameIfNecessary = true;
+ // create nodeNames larger than 28 bytes
+ for (int i = 1; i < 100; i++) {
+ String originalNodeName = UUID.randomUUID().toString();
+ NarayanaJtaRecorder r = new NarayanaJtaRecorder();
+ transactions.nodeName = originalNodeName;
+ r.setNodeName(transactions);
+ int numberOfBytes = transactions.nodeName.getBytes(StandardCharsets.UTF_8).length;
+ assertFalse(numberOfBytes > 28,
+ "node name bytes still exceeded 28 bytes limit, number of bytes is " + numberOfBytes);
+ }
+ for (int i = 1; i < 1000; i++) {
+ byte[] data = new byte[i];
+ NarayanaJtaRecorder r = new NarayanaJtaRecorder();
+ transactions.nodeName = new String(data);
+ r.setNodeName(transactions);
+ int numberOfBytes = transactions.nodeName.getBytes(StandardCharsets.UTF_8).length;
+ assertFalse(numberOfBytes > 28,
+ "node name bytes still exceeded 28 bytes limit, number of bytes is " + numberOfBytes);
+ }
+ }
+
+}