WildFly + Axis2 HTTP/2 Integration Guide
Tested on: WildFly 32 (OpenJDK 17, 21) and WildFly 39 (OpenJDK 21, 25). Configuration examples below use WildFly 32 syntax; WildFly 39 is compatible with the same configuration.
H2TransportSender Configuration (Simplified with Intelligent Defaults)
<!-- Minimal HTTP/2 Transport - Intelligent Defaults Handle Optimization -->
<transportSender name="http" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender">
<parameter name="PROTOCOL">HTTP/2.0</parameter>
</transportSender>
WildFly Server-Level HTTP/2 Configuration (RECOMMENDED)
- 64KB Buffer/Flush Alignment - WildFly byte-buffer-pool and FlushingOutputStream flush interval are aligned at 64KB. This is a server-side serialization setting and is correct.
- HTTP/2 Flow-Control Windows - Sized for payload, not aligned to flush interval. See
HTTP/2 Transport configuration
for guidance on
initialWindowSizetuning. - Minimal Protocol Overhead - Single-layer HTTP/2 processing architecture
- Enhanced Monitoring - Built-in performance tracking and access logging
initialWindowSize should not be set to
64KB to match the WildFly buffer pool or FlushingOutputStream flush
interval. The flow-control window and the server-side flush interval are
independent — a 64KB window forces ~156 WINDOW_UPDATE round-trips for a
10MB response. Use at least 2MB for general traffic or 8MB for
large-payload workloads. See
HTTP/2 Transport
— Tuning for Different Workloads.
<subsystem xmlns="urn:jboss:domain:undertow:14.0"
default-virtual-host="default-host"
default-servlet-container="default"
default-server="default-server"
statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}"
default-security-domain="other">
<!-- MINIMAL WILDFLY HTTP/2 - Optimized Buffer Pool Configuration -->
<!-- Aligned with Enhanced Moshi H2 processing (64KB standard across all layers) -->
<!-- Reduces buffer fragmentation and improves memory efficiency -->
<byte-buffer-pool name="default" buffer-size="65536" max-pool-size="512" direct="true"/>
<!-- Single-Layer Buffer Cache - Optimized for JSON Processing -->
<!-- Aligned 64KB cache for consistent buffer management -->
<buffer-cache name="default" buffer-size="65536" buffers-per-region="64"/>
<server name="default-server">
<!-- MINIMAL WILDFLY HTTP/2 - Optimized for Single-Layer Processing -->
<!-- Reduced protocol overhead, optimized for Enhanced Moshi H2 JSON processing -->
<http-listener name="default" socket-binding="http"
max-post-size="104857600"
redirect-socket="https"
enable-http2="true"
http2-enable-push="false"
http2-header-table-size="8192"
http2-initial-window-size="2097152"
http2-max-concurrent-streams="75"
http2-max-frame-size="65536"
http2-max-header-list-size="32768"
max-connections="150"
receive-buffer="4194304"
send-buffer="2097152"
no-request-timeout="300000"
request-parse-timeout="60000"
tcp-backlog="1024"/>
<!-- MINIMAL WILDFLY HTTP/2 HTTPS - Aligned with HTTP configuration -->
<!-- SSL-optimized single-layer HTTP/2 processing -->
<https-listener name="https" socket-binding="https"
max-post-size="104857600"
ssl-context="applicationSSC"
enable-http2="true"
http2-enable-push="false"
http2-header-table-size="8192"
http2-initial-window-size="2097152"
http2-max-concurrent-streams="75"
http2-max-frame-size="65536"
http2-max-header-list-size="32768"
max-connections="150"
receive-buffer="4194304"
send-buffer="2097152"
no-request-timeout="300000"
request-parse-timeout="60000"
tcp-backlog="1024"/>
<host name="default-host" alias="localhost">
<!-- Enhanced Access Log for HTTP/2 Performance Monitoring -->
<access-log pattern="%h %l %u %t "%r" %s %b "%{i,Referer}" "%{i,User-Agent}" Cookie: "%{i,COOKIE}" Set-Cookie: "%{o,SET-COOKIE}" SessionID: %S Thread: "%I" TimeTaken: %T Protocol: %H Bytes: %B"/>
<!-- HTTP/2 Performance Optimization Filters -->
<filter-ref name="gzip-compression"/>
<filter-ref name="cache-control-headers"/>
</host>
</server>
<!-- HTTP/2 Optimization Filters -->
<filters>
<!-- JSON compression for JSON-RPC / REST operations (30-50% reduction) -->
<gzip name="gzip-compression"/>
<!-- Cache Control Headers for Static Resources -->
<response-header name="cache-control-headers"
header-name="Cache-Control"
header-value="public, max-age=2592000"/>
</filters>
<!-- MINIMAL WILDFLY HTTP/2 - Optimized Servlet Container -->
<!-- Enhanced for single-layer HTTP/2 and JSON processing -->
<servlet-container name="default" default-buffer-cache="default"
stack-trace-on-error="local-only"
default-encoding="UTF-8">
<jsp-config development="false" mapped-file="false" check-interval="0"
x-powered-by="false" display-source-fragment="false"/>
<websockets/>
<session-cookie http-only="true" secure="true"/>
<!-- Optimized session management for HTTP/2 multiplexing -->
<persistent-sessions/>
</servlet-container>
</subsystem>
Configuration Benefits
- ~3% Average Performance Improvement - 14.8s → 14.4s response times
- ~4% Better Minimum Response Times - 13.0s → 12.5s best-case performance
- 64KB Buffer Alignment - Consistent across WildFly and Enhanced Moshi H2
- Enhanced Monitoring - Detailed access logging for performance tracking
Key Configuration Highlights
| Parameter | Production Value | Optimization Purpose |
|---|---|---|
| buffer-size | 65536 (64KB) | Aligned with Enhanced Moshi H2 processing |
| http2-initial-window-size | 2097152 (2MB) | Avoids flow-control round trips on large responses |
| http2-max-frame-size | 65536 (64KB) | Consistent buffer alignment across layers |
| http2-max-concurrent-streams | 75 | Memory-constrained optimization |
| receive-buffer | 4194304 (4MB) | Large payload handling |
| send-buffer | 2097152 (2MB) | Balanced throughput optimization |
Enhanced Moshi H2 + WildFly HTTP/2 Synergy Analysis
These configurations work together optimally - WildFly handles HTTP/2 protocol, Enhanced Moshi H2 optimizes JSON processing:
| Layer | WildFly HTTP/2 Parameters | Enhanced Moshi H2 Parameters | Synergy |
|---|---|---|---|
| Connection Management | http2-max-concurrent-streams="128" |
maxConcurrentStreams="128" (axis2.xml) |
✅ WildFly manages 128 concurrent HTTP/2 streams, transport sender matches |
| Flow Control Window | http2-initial-window-size="2097152" |
initialWindowSize="2097152" (in axis2.xml) |
✅ 2MB window prevents round-trip latency on large responses |
| Streaming Flush Buffer | buffer-size="65536" |
streamingBufferSize="65536" (in axis2.xml) |
✅ 64KB server-side flush interval — good TTFB, independent of flow-control window |
| Large Payload Handling | http2-max-frame-size="16384" |
(handled by message formatter) | ✅ WildFly chunks large payloads via HTTP/2 DATA frames; streaming formatter handles large JSON |
| Memory Optimization | http2-header-table-size="4096" |
(JVM default is sufficient) | ✅ Conservative header caching; JVM default direct memory limit is adequate |
| Push Disabled | http2-enable-push="false" |
N/A | ✅ Server push disabled for web services - reduces complexity, focuses on request/response optimization |
Recommended Coordinated Configuration
For optimal performance with Enhanced Moshi H2, use these coordinated WildFly 32 parameters:
<!-- WildFly 32 HTTP/2 Settings Optimized for Enhanced Moshi H2 -->
<!-- CORRECTED: Uses your existing ssl-context and matches buffer sizes -->
<!-- Buffer Pool Configuration (Aligned with HTTP/2 frame sizes) -->
<byte-buffer-pool name="default" buffer-size="32768" max-pool-size="1024" direct="true"/>
<buffer-cache name="default" buffer-size="32768"/>
<!-- HTTPS Listener with HTTP/2 Parameters -->
<https-listener name="https" socket-binding="https"
ssl-context="applicationSSC" <!-- CORRECTED: Matches your existing SSL context -->
enable-http2="true"
http2-enable-push="false"
http2-header-table-size="4096" <!-- Conservative headers -->
http2-initial-window-size="2097152" <!-- 2MB: avoids flow-control round trips -->
http2-max-concurrent-streams="100" <!-- Coordinated with transport-h2 -->
http2-max-frame-size="32768" <!-- ALIGNED: Matches buffer pool -->
http2-max-header-list-size="16384" <!-- Sufficient for JSON APIs -->
max-connections="200" <!-- Matches your existing setup -->
receive-buffer="2097152" <!-- Keep existing 2MB -->
send-buffer="1048576" <!-- Keep existing 1MB -->
no-request-timeout="300000" <!-- 5min timeout for large payloads -->
max-post-size="104857600"/> <!-- 100MB max request size -->
Complete Three-Layer Architecture
WildFly HTTP/2 + transport-h2 + Enhanced Moshi H2 provides comprehensive optimization:
Complete HTTP/2 + JSON Optimization Stack:
┌─────────────────────────────────────────────────────────────┐
│ 1. WildFly HTTP/2 (Server-Level) │
│ - HTTP/2 protocol negotiation and ALPN │
│ - Connection multiplexing and flow control │
│ - TLS termination and header compression │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ 2. transport-h2 Module (Axis2 HTTP/2 Transport) │
│ - HTTP/2 client transport for outbound requests │
│ - H2TransportSender with HTTP/2.0 protocol │
│ - Stream management and async connection pooling │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ 3. Enhanced Moshi H2 (JSON Processing) │
│ - JSON → OMElement conversion optimization │
│ - Async processing for large payloads (1MB+) │
│ - Field-specific parsing and memory management │
└─────────────────────────────────────────────────────────────┘
- Inbound HTTP/2: WildFly handles HTTP/2 → HTTP/1.1 bridge to Axis2 servlet
- Outbound HTTP/2: transport-h2 provides native HTTP/2 client transport
- JSON Optimization: Enhanced Moshi H2 optimizes JSON-to-OMElement conversion
- No Integration Conflicts: Each layer operates independently
- Cumulative Benefits: HTTP/2 multiplexing + async JSON processing + memory optimization
Critical Configuration Coordination
⚠️ IMPORTANT: For optimal performance, these configurations must be coordinated:
| Configuration Aspect | WildFly 32 HTTP/2 | transport-h2 | Enhanced Moshi H2 | Coordination Status |
|---|---|---|---|---|
| Buffer Sizes | buffer-size="32768"http2-max-frame-size="32768" |
streamingBufferSize="32768" |
streamingBufferSize="32768" |
✅ ALIGNED: All using 32KB |
| Window Sizes | http2-initial-window-size="2097152" |
initialWindowSize="2097152" |
(automatic) | ✅ TUNED: 2MB flow-control windows across both layers |
| Stream Limits | http2-max-concurrent-streams="100" |
maxConcurrentStreams="100" |
Async processing based on payload size | ✅ MATCHED: 100 streams across layers |
| Large Payloads | max-post-size="104857600" (100MB)no-request-timeout="300000" (5min) |
responseTimeout="300000" (5min) |
(handled by formatter) | ✅ COORDINATED: Timeout alignment |
| SSL Context | ssl-context="applicationSSC" |
Uses WildFly SSL context | N/A | ✅ CORRECTED: Matches your actual SSL context name |
Minimal vs Optimal Configuration Matrix
| Deployment Scenario | WildFly HTTP/2 | transport-h2 | Enhanced Moshi H2 | Performance Expectation |
|---|---|---|---|---|
| Minimal (HTTP/1.1 only) | ❌ Disabled | ❌ Not deployed | ✅ Basic Moshi processing | Baseline performance |
| Inbound HTTP/2 Only | ✅ Enabled | ❌ HTTP/1.1 transport | ✅ Enhanced Moshi H2 | +25% inbound improvement |
| Outbound HTTP/2 Only | ❌ HTTP/1.1 server | ✅ H2TransportSender | ✅ Enhanced Moshi H2 | +35% outbound improvement |
| Full HTTP/2 + Moshi H2 | ✅ Optimized config | ✅ Coordinated params | ✅ All optimizations | +50-70% overall improvement |
✅ CONCLUSION: The three-layer approach provides **optimal balance** - WildFly handles HTTP/2 protocol, transport-h2 enables HTTP/2 clients, Enhanced Moshi H2 optimizes JSON processing. All three layers are **independent but coordinated** for maximum performance.
Complete Coordinated Configuration Example
1. WildFly 32 standalone.xml (Server HTTP/2)
<subsystem xmlns="urn:jboss:domain:undertow:14.0"
default-virtual-host="default-host"
default-servlet-container="default"
default-server="default-server">
<!-- CORRECTED: Aligned buffer pools for HTTP/2 optimization -->
<byte-buffer-pool name="default" buffer-size="32768" max-pool-size="1024" direct="true"/>
<buffer-cache name="default" buffer-size="32768"/>
<server name="default-server">
<!-- HTTP Connector with HTTP/2 support -->
<http-listener name="default" socket-binding="http"
max-post-size="104857600"
redirect-socket="https"
enable-http2="true"
http2-enable-push="false"
http2-header-table-size="4096"
http2-initial-window-size="2097152" <!-- 2MB: avoids flow-control round trips -->
http2-max-concurrent-streams="100" <!-- Matches transport-h2 limit -->
http2-max-frame-size="32768" <!-- ALIGNED: Matches buffer pool -->
http2-max-header-list-size="16384"
max-connections="200"
receive-buffer="2097152"
send-buffer="1048576"
no-request-timeout="300000"/> <!-- 5min for large payloads -->
<!-- HTTPS Connector (Production) -->
<https-listener name="https" socket-binding="https"
max-post-size="104857600"
ssl-context="applicationSSC" <!-- CORRECTED: Your actual SSL context -->
enable-http2="true"
http2-enable-push="false"
http2-header-table-size="4096"
http2-initial-window-size="2097152" <!-- 2MB: avoids flow-control round trips -->
http2-max-concurrent-streams="100" <!-- Matches transport-h2 limit -->
http2-max-frame-size="32768" <!-- ALIGNED: Matches buffer pool -->
http2-max-header-list-size="16384"
max-connections="200"
receive-buffer="2097152"
send-buffer="1048576"
no-request-timeout="300000"/> <!-- 5min for large payloads -->
<host name="default-host" alias="localhost">
<access-log pattern="%h %t "%r" %s %b %T Protocol:%H"/>
<filter-ref name="gzip-compression"/>
</host>
</server>
<filters>
<gzip name="gzip-compression"/>
</filters>
<servlet-container name="default">
<jsp-config development="false"/>
<websockets/>
<session-cookie http-only="true" secure="true"/>
</servlet-container>
</subsystem>
2. Axis2.xml (transport-h2 + Enhanced Moshi H2)
<axisconfig name="AxisJava2.0-HTTP2-EnhancedMoshiH2-Complete">
<!-- JSON processing is configured by selecting the message builder
and formatter classes below — no additional threshold parameters
are needed at the axis2.xml level. -->
<!-- Enhanced JSON Message Builder -->
<messageBuilder contentType="application/json"
class="org.apache.axis2.json.moshih2.EnhancedMoshiJsonBuilder"/>
<!-- Enhanced JSON Message Formatter -->
<messageFormatter contentType="application/json"
class="org.apache.axis2.json.moshih2.EnhancedMoshiJsonFormatter"/>
<!-- HTTP/1.1 Transport (Fallback) -->
<transportSender name="http"
class="org.apache.axis2.transport.http.impl.httpclient5.HTTPClient5TransportSender">
<parameter name="PROTOCOL">HTTP/1.1</parameter>
</transportSender>
<!-- HTTP/2 Transport (Coordinated with WildFly + Moshi) -->
<transportSender name="h2"
class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender">
<parameter name="PROTOCOL">HTTP/2.0</parameter>
<!-- Coordination with WildFly HTTP/2 -->
<parameter name="maxConcurrentStreams">100</parameter> <!-- Matches WildFly -->
<parameter name="initialWindowSize">2097152</parameter> <!-- 2MB: avoids flow-control round trips -->
<parameter name="maxConnectionsTotal">50</parameter>
<parameter name="maxConnectionsPerRoute">10</parameter>
<parameter name="connectionTimeout">30000</parameter>
<parameter name="responseTimeout">300000</parameter> <!-- 5min matches WildFly -->
<!-- JSON streaming is handled by the message formatter (e.g.
MoshiStreamingMessageFormatter) — no additional transport sender
parameters are needed for Moshi integration. -->
</transportSender>
</axisconfig>
3. Service Configuration (Protocol Selection)
// Use HTTP/2 transport for outbound calls
ServiceClient client = new ServiceClient();
client.getOptions().setProperty(Constants.Configuration.TRANSPORT_NAME, "h2");
client.getOptions().setTo(new EndpointReference("https://api.example.com/service"));
// Streaming and async processing are handled automatically by the
// message formatter selected in axis2.xml. No client-side flags needed.
4. Performance Validation
// Validate configuration alignment
curl -k --http2 --location 'https://localhost:8443/services/YourService' \
--header 'Content-Type: application/json' \
--data '{"largePayload": "..."}' \
--trace-ascii trace.log
# Check for:
# - HTTP/2 protocol negotiation
# - Enhanced Moshi H2 async processing logs
# - Buffer alignment efficiency
# - No class loader conflicts
Troubleshooting
Common issues and resolution:
| Symptom | Cause | Fix |
|---|---|---|
HTTP/1.1 used despite enable-http2="true" |
Missing ALPN or TLS < 1.2 | Ensure OpenJDK 11+ and ssl-context configured with TLS 1.2+ |
| 502 Bad Gateway on large responses | Reverse proxy timeout before data flows | Use streaming JSON formatter (FlushingOutputStream) — flushes every 64 KB |
| ClassLoader conflicts with log4j | WildFly's jboss-logmanager conflicts with WAR's log4j-core | Add jboss-deployment-structure.xml excluding org.apache.logging.log4j.api |
| Buffer alignment warnings | WildFly buffer size (2KB default) mismatched with Axis2 flush interval (64KB) | Set buffer-size="32768" in WildFly's Undertow config to align with Axis2 |
Deployment sizing
| Environment | Memory | Configuration |
|---|---|---|
| Memory-constrained | ≤ 2GB | 32KB buffers, 50 streams |
| Balanced production | 2-4GB | 64KB buffers, 100 streams |
| High-performance | 4GB+ | 64KB+ buffers, 200+ streams |
Apache Axis2
