This is an automated email from the ASF dual-hosted git repository.
robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git
The following commit(s) were added to refs/heads/master by this push:
new 161d0b1317 AXIS2-6099 add some unit tests and better Wildfly dep
verification
161d0b1317 is described below
commit 161d0b131783717d5e35e66b51287c1002d9c6cc
Author: Robert Lazarski <[email protected]>
AuthorDate: Tue Dec 9 17:21:21 2025 -1000
AXIS2-6099 add some unit tests and better Wildfly dep verification
---
.../moshi/UndertowAxis2BufferIntegration.java | 191 +++++++++++++++++----
.../moshi/MemoryConstraintValidationTest.java | 28 +--
.../WildFlyAxis2CooperativeIntegrationTest.java | 34 ++--
3 files changed, 182 insertions(+), 71 deletions(-)
diff --git
a/modules/transport-h2/src/main/java/org/apache/axis2/transport/h2/integration/moshi/UndertowAxis2BufferIntegration.java
b/modules/transport-h2/src/main/java/org/apache/axis2/transport/h2/integration/moshi/UndertowAxis2BufferIntegration.java
index 94b1fef796..36b3d58cdd 100644
---
a/modules/transport-h2/src/main/java/org/apache/axis2/transport/h2/integration/moshi/UndertowAxis2BufferIntegration.java
+++
b/modules/transport-h2/src/main/java/org/apache/axis2/transport/h2/integration/moshi/UndertowAxis2BufferIntegration.java
@@ -40,6 +40,7 @@ import
org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import
org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
+import org.xnio.Pool;
import org.xnio.XnioWorker;
import com.squareup.moshi.JsonReader;
@@ -47,14 +48,6 @@ import com.squareup.moshi.JsonReader;
import okio.BufferedSource;
import okio.Okio;
-/**
- * Simple Pool interface for buffer management compatibility.
- */
-interface Pool<T> {
- T allocate();
- void free(T item);
- int getAllocatedObjectCount();
-}
/**
* Moshi-specific Axis2 integration with Undertow shared buffer pools using
Axis2 architecture patterns.
@@ -75,24 +68,161 @@ public class UndertowAxis2BufferIntegration {
private static final Log log =
LogFactory.getLog(UndertowAxis2BufferIntegration.class);
/**
- * Initialize Moshi-specific integration with Undertow servlet context.
- *
- * @param servletContext The servlet context providing access to
Undertow's XNIO worker and buffer pool
+ * Cached WildFly integration singleton - initialized once, reused across
all HTTP requests.
+ * This ensures zero performance overhead in high-volume enterprise
applications.
+ */
+ private static volatile WildFlyResourceCache wildflyCache = null;
+ private static final Object initLock = new Object();
+
+ /**
+ * Cached WildFly resources discovered once during first servlet context
access.
+ */
+ private static class WildFlyResourceCache {
+ final XnioWorker xnioWorker;
+ final Pool<ByteBuffer> sharedBufferPool;
+ final boolean integrationAvailable;
+ final String discoveryLog;
+
+ WildFlyResourceCache(ServletContext servletContext) {
+ StringBuilder discovery = new StringBuilder("WildFly resource
discovery: ");
+ XnioWorker worker = null;
+ Pool<ByteBuffer> pool = null;
+
+ // Try multiple possible WildFly attribute names (test-compatible
first)
+ String[] workerNames = {
+ "io.undertow.servlet.XnioWorker", // Test compatibility -
current expected name
+ "io.undertow.xnio.worker", // Alternative WildFly name
+ "org.wildfly.undertow.worker", // WildFly-specific name
+ "undertow.xnio.worker" // Generic name
+ };
+
+ String[] poolNames = {
+ "io.undertow.servlet.BufferPool", // Test compatibility -
current expected name
+ "io.undertow.buffer-pool", // Alternative WildFly name
+ "org.wildfly.undertow.buffer.pool", // WildFly-specific name
+ "undertow.buffer.pool" // Generic name
+ };
+
+ // Search for XNIO Worker
+ for (String name : workerNames) {
+ Object attr = servletContext.getAttribute(name);
+ if (attr instanceof XnioWorker) {
+ worker = (XnioWorker) attr;
+ discovery.append("Found XnioWorker at
'").append(name).append("', ");
+ break;
+ }
+ }
+
+ // Search for Buffer Pool
+ for (String name : poolNames) {
+ Object attr = servletContext.getAttribute(name);
+ if (attr instanceof Pool) {
+ try {
+ @SuppressWarnings("unchecked")
+ Pool<ByteBuffer> bufferPool = (Pool<ByteBuffer>) attr;
+ pool = bufferPool;
+ discovery.append("Found BufferPool at
'").append(name).append("', ");
+ break;
+ } catch (ClassCastException e) {
+ // Not a ByteBuffer pool, continue searching
+ }
+ }
+ }
+
+ this.xnioWorker = worker;
+ this.sharedBufferPool = pool;
+ this.integrationAvailable = (worker != null && pool != null);
+ this.discoveryLog = discovery.toString();
+
+ // Log discovery results once
+ if (integrationAvailable) {
+ log.info("WildFly integration available: " + discoveryLog);
+ } else {
+ log.debug("WildFly integration not available: " + discoveryLog
+
+ "Worker=" + (worker != null) + ", Pool=" + (pool !=
null));
+
+ // Debug: enumerate all servlet context attributes to help
discover correct names
+ if (log.isDebugEnabled()) {
+ enumerateServletContextAttributes(servletContext);
+ }
+ }
+ }
+
+ /**
+ * Debug helper: enumerate all servlet context attributes to discover
WildFly's actual attribute names.
+ * Only called when debug logging is enabled and integration fails.
+ */
+ private void enumerateServletContextAttributes(ServletContext
servletContext) {
+ try {
+ java.util.Enumeration<String> attributeNames =
servletContext.getAttributeNames();
+ StringBuilder allAttrs = new StringBuilder("All servlet
context attributes: ");
+
+ while (attributeNames.hasMoreElements()) {
+ String name = attributeNames.nextElement();
+ Object value = servletContext.getAttribute(name);
+ String className = (value != null) ?
value.getClass().getSimpleName() : "null";
+
allAttrs.append(name).append("=").append(className).append(", ");
+ }
+
+ log.debug(allAttrs.toString());
+ } catch (Exception e) {
+ log.debug("Failed to enumerate servlet context attributes: " +
e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Check if WildFly integration is available for this instance.
+ * @return true if both XNIO worker and buffer pool are available for this
instance
+ */
+ public boolean isIntegrationAvailable() {
+ return xnioWorker != null && sharedBufferPool != null;
+ }
+
+ /**
+ * Get integration discovery information for monitoring/debugging.
+ * @return discovery log string, or null if not yet discovered
+ */
+ public static String getDiscoveryInfo() {
+ WildFlyResourceCache cache = wildflyCache;
+ return cache != null ? cache.discoveryLog : "Not yet initialized";
+ }
+
+ /**
+ * Clear the static cache - useful for testing environments.
+ * Package-private for use in test classes.
+ */
+ static void clearCache() {
+ wildflyCache = null;
+ }
+
+ /**
+ * Initialize Moshi-specific integration with cached WildFly resources.
+ * First call discovers and caches resources, subsequent calls reuse
cached values.
+ * @param servletContext The servlet context (used only for first-time
discovery)
*/
public UndertowAxis2BufferIntegration(ServletContext servletContext) {
- // Access Undertow's XNIO worker and buffer pool
- this.xnioWorker = (XnioWorker) servletContext
- .getAttribute("io.undertow.servlet.XnioWorker");
- this.sharedBufferPool = (Pool<ByteBuffer>) servletContext
- .getAttribute("io.undertow.servlet.BufferPool");
-
- if (xnioWorker == null) {
- log.warn("XNIO Worker not found in servlet context - Undertow
integration may be limited");
+ // Lazy initialization with double-checked locking for thread safety
+ if (wildflyCache == null) {
+ synchronized (initLock) {
+ if (wildflyCache == null) {
+ wildflyCache = new WildFlyResourceCache(servletContext);
+ }
+ }
}
- if (sharedBufferPool == null) {
- log.warn("Shared buffer pool not found in servlet context - using
default buffer management");
- } else {
- log.info("Successfully integrated Moshi-based Axis2 with Undertow
shared buffer pool");
+
+ // Use cached resources (zero lookup overhead after first
initialization)
+ this.xnioWorker = wildflyCache.xnioWorker;
+ this.sharedBufferPool = wildflyCache.sharedBufferPool;
+
+ // Emit warnings only if this is a fresh discovery attempt
+ if (!wildflyCache.integrationAvailable) {
+ if (xnioWorker == null) {
+ log.warn("XNIO Worker not found in servlet context - Undertow
integration may be limited");
+ }
+ if (sharedBufferPool == null) {
+ log.warn("Shared buffer pool not found in servlet context -
using default buffer management");
+ }
}
}
@@ -148,7 +278,7 @@ public class UndertowAxis2BufferIntegration {
private int getSharedBufferSize() {
if (sharedBufferPool != null) {
// Align with Undertow's buffer configuration and Axis2's
needs
- return sharedBufferPool.getAllocatedObjectCount() > 0 ?
4096 : 2048;
+ return 4096; // Use 4KB buffers when shared pool is
available
} else {
// Fallback to default Axis2 buffer size optimized for
Moshi
return 65536; // 64KB default for large JSON payloads
@@ -215,8 +345,7 @@ public class UndertowAxis2BufferIntegration {
// Create BufferedSource with shared buffer pool awareness for
Moshi optimization
// Note: Okio uses its own buffer management, but we coordinate
with shared pool metrics
if (sharedBufferPool != null && log.isDebugEnabled()) {
- log.debug("Creating Moshi-optimized BufferedSource with shared
buffer pool awareness - " +
- "allocated buffers: " +
sharedBufferPool.getAllocatedObjectCount());
+ log.debug("Creating Moshi-optimized BufferedSource with shared
buffer pool awareness");
}
return Okio.buffer(Okio.source(inputStream));
}
@@ -240,14 +369,6 @@ public class UndertowAxis2BufferIntegration {
return sharedBufferPool;
}
- /**
- * Check if Undertow integration is fully available.
- *
- * @return true if both XNIO worker and buffer pool are available
- */
- public boolean isIntegrationAvailable() {
- return xnioWorker != null && sharedBufferPool != null;
- }
/**
* Get integration status for monitoring and debugging.
@@ -261,7 +382,7 @@ public class UndertowAxis2BufferIntegration {
if (isIntegrationAvailable()) {
status.append("FULL - XNIO Worker and Buffer Pool available");
if (sharedBufferPool != null) {
- status.append(", Allocated Buffers:
").append(sharedBufferPool.getAllocatedObjectCount());
+ status.append(", Buffer Pool: available");
}
} else if (xnioWorker != null) {
status.append("PARTIAL - XNIO Worker available, Buffer Pool
missing");
diff --git
a/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/MemoryConstraintValidationTest.java
b/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/MemoryConstraintValidationTest.java
index 7772d7f794..93fbd8440a 100644
---
a/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/MemoryConstraintValidationTest.java
+++
b/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/MemoryConstraintValidationTest.java
@@ -45,6 +45,7 @@ import org.mockito.MockitoAnnotations;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
+import org.xnio.Pool;
/**
* Memory Constraint Validation Test Suite for WildFly 32 + Axis2 HTTP/2
Integration.
@@ -84,6 +85,9 @@ public class MemoryConstraintValidationTest {
public void setUp() throws Exception {
MockitoAnnotations.openMocks(this);
+ // Clear static cache to ensure test isolation
+ UndertowAxis2BufferIntegration.clearCache();
+
// Initialize memory coordination
memoryCoordinator = new HTTP2MemoryCoordinator();
@@ -488,27 +492,11 @@ public class MemoryConstraintValidationTest {
// Helper methods and classes
+ @SuppressWarnings("unchecked")
private Pool<ByteBuffer> createMockBufferPoolWithTracking() {
- return new Pool<ByteBuffer>() {
- private int allocatedCount = 0;
- private int maxAllocated = 10;
-
- @Override
- public ByteBuffer allocate() {
- allocatedCount++;
- return ByteBuffer.allocate(8192); // 8KB buffers
- }
-
- @Override
- public void free(ByteBuffer item) {
- allocatedCount = Math.max(0, allocatedCount - 1);
- }
-
- @Override
- public int getAllocatedObjectCount() {
- return Math.min(allocatedCount, maxAllocated);
- }
- };
+ Pool<ByteBuffer> pool = mock(Pool.class);
+ // Mock the pool - using Mockito to avoid XNIO interface complexity in
tests
+ return pool;
}
private String generateMemoryTestPayload(long targetSizeBytes) {
diff --git
a/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/WildFlyAxis2CooperativeIntegrationTest.java
b/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/WildFlyAxis2CooperativeIntegrationTest.java
index 92c458ec3d..0d5ace7342 100644
---
a/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/WildFlyAxis2CooperativeIntegrationTest.java
+++
b/modules/transport-h2/src/test/java/org/apache/axis2/transport/h2/integration/moshi/WildFlyAxis2CooperativeIntegrationTest.java
@@ -40,6 +40,7 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.xnio.Pool;
import org.xnio.XnioWorker;
import io.undertow.server.HttpServerExchange;
@@ -80,6 +81,9 @@ public class WildFlyAxis2CooperativeIntegrationTest {
public void setUp() throws Exception {
MockitoAnnotations.openMocks(this);
+ // Clear static cache to ensure test isolation
+ UndertowAxis2BufferIntegration.clearCache();
+
// Mock WildFly buffer pool (key integration point)
mockBufferPool = createMockBufferPool();
@@ -310,10 +314,20 @@ public class WildFlyAxis2CooperativeIntegrationTest {
*/
@Test
public void testWildFlyIntegrationFallback() {
+ // Clear cache to ensure this test has clean state
+ UndertowAxis2BufferIntegration.clearCache();
+
// Test integration without WildFly components
ServletContext limitedContext = mock(ServletContext.class);
+ // Mock all possible attribute names to return null
when(limitedContext.getAttribute("io.undertow.servlet.XnioWorker")).thenReturn(null);
when(limitedContext.getAttribute("io.undertow.servlet.BufferPool")).thenReturn(null);
+
when(limitedContext.getAttribute("io.undertow.xnio.worker")).thenReturn(null);
+
when(limitedContext.getAttribute("io.undertow.buffer-pool")).thenReturn(null);
+
when(limitedContext.getAttribute("org.wildfly.undertow.worker")).thenReturn(null);
+
when(limitedContext.getAttribute("org.wildfly.undertow.buffer.pool")).thenReturn(null);
+
when(limitedContext.getAttribute("undertow.xnio.worker")).thenReturn(null);
+
when(limitedContext.getAttribute("undertow.buffer.pool")).thenReturn(null);
UndertowAxis2BufferIntegration limitedIntegration = new
UndertowAxis2BufferIntegration(limitedContext);
@@ -331,23 +345,11 @@ public class WildFlyAxis2CooperativeIntegrationTest {
// Helper methods
+ @SuppressWarnings("unchecked")
private Pool<ByteBuffer> createMockBufferPool() {
- return new Pool<ByteBuffer>() {
- @Override
- public ByteBuffer allocate() {
- return ByteBuffer.allocate(8192); // 8KB buffer
- }
-
- @Override
- public void free(ByteBuffer item) {
- // Mock implementation
- }
-
- @Override
- public int getAllocatedObjectCount() {
- return 10; // Mock active buffers
- }
- };
+ Pool<ByteBuffer> pool = mock(Pool.class);
+ // Mock the pool - using Mockito to avoid XNIO interface complexity in
tests
+ return pool;
}
private String generateLargeJsonPayload(int sizeBytes) {