H2TransportSender (HTTP/2 Transport)
🚀 TL;DR - Quick Start for Large Payloads (50MB+)
Most Common Use Case: Processing 50MB+ JSON payloads with optimal performance
Production Configuration (axis2.xml) - AWS/Cloudflare Ready:
<transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> <!-- ALPN Support (Required for AWS ALB, Cloudflare) --> <parameter name="alpnProtocols">h2,http/1.1</parameter> <parameter name="tlsRequired">true</parameter> <!-- Large Payload Optimization --> <parameter name="maxConcurrentStreams">20</parameter> <parameter name="initialWindowSize">2097152</parameter> <!-- 2MB window --> <!-- Timeouts --> <parameter name="connectionTimeout">30000</parameter> <!-- 30s connect --> <parameter name="responseTimeout">300000</parameter> <!-- 5min response --> <!-- HTTP/2 fallback to HTTP/1.1 is automatic via TLS ALPN --> </transportSender>
Client Access for 50MB JSON Payloads:
Most JSON clients will use curl or Apache HTTP Components directly:
# curl with HTTP/2 for large JSON payloads (AWS/Cloudflare compatible)
curl --http2-prior-knowledge -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "User-Agent: MyApp/1.0" \
--max-time 300 --connect-timeout 30 \
--compressed \
--data @large-payload.json \
https://server:8443/services/BigDataService
# Apache HTTP Components 5.x (Java clients)
CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
.setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2)
.build();
httpClient.start();
HttpPost request = new HttpPost("https://server:8443/services/BigDataService");
request.setEntity(new StringEntity(jsonPayload, ContentType.APPLICATION_JSON));
Expected Performance: 40-70% faster than HTTP/1.1 for 50MB+ JSON payloads with 20% less memory usage
Note: Server push is disabled by default as it's not beneficial for JSON APIs (see "Server Push Capabilities" section below for detailed explanation).
H2TransportSender provides enterprise-grade HTTP/2 transport capabilities using HttpClient 5.x with advanced features for large payload processing, connection multiplexing, and performance optimization. This transport is specifically designed for big data applications requiring 50MB+ JSON payload support with memory-efficient 64 KB flush intervals.
HTTP/2 offers significant advantages over HTTP/1.1:
- Binary protocol with header compression (HPACK)
- Stream multiplexing - multiple concurrent requests over single connection
- Server push capabilities (configurable)
- Improved flow control with window scaling
- Enhanced performance for large payloads
- Reduced connection overhead and latency
Basic HTTP/2 Configuration
The <transportSender/> element for HTTP/2 transport:
<transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> <parameter name="maxConcurrentStreams">100</parameter> <parameter name="initialWindowSize">2097152</parameter> <!-- 2MB -- see note below --> <parameter name="serverPushEnabled">false</parameter> <parameter name="memoryOptimized">true</parameter> </transportSender>
Flow-control window vs. streaming flush interval
initialWindowSize and the FlushingOutputStream
64 KB flush interval are independent settings that should not be
"aligned" to the same value.
- FlushingOutputStream flush (server-side, 64 KB) — controls when serialized bytes are pushed into the HTTP/2 framing layer. 64 KB is a good cadence: it gives early time-to-first-byte and prevents reverse proxy timeouts on long-running serializations. This value is correct and should not change.
- initialWindowSize (client-side, per-stream) — controls how much data a stream may have in-flight before the sender pauses for a WINDOW_UPDATE acknowledgement from the receiver. A 10 MB response with a 64 KB window requires ~156 WINDOW_UPDATE round-trips; with a 2 MB window it requires ~5. Under concurrent load, these round-trips serialize on each TCP connection, adding significant latency.
A server flushing at 64 KB works well with a client whose window is 2 MB — the server sends 64 KB, the framing layer accumulates up to 2 MB of in-flight data, and the client acknowledges in bulk. Setting both to 64 KB forces the client to acknowledge every single flush, converting each 64 KB chunk into a synchronous round-trip.
HTTP/2 Configuration Parameters
| Parameter | Description | Default | Range |
|---|---|---|---|
| maxConcurrentStreams | Maximum concurrent streams per connection. Lower values (4-8) force the connection pool to spread streams across multiple TCP connections — better for workloads with few concurrent large payloads. Higher values (50-100) maximize multiplexing efficiency for many small concurrent requests. | 100 | 1-1000 |
| initialWindowSize | HTTP/2 per-stream flow-control window (bytes). Determines how much data can be in-flight per stream before the sender waits for a WINDOW_UPDATE. For payloads above 1 MB, use at least 1-2 MB to avoid excessive round-trips. Not related to the server-side FlushingOutputStream 64 KB flush interval. | 2097152 | 64KB-16MB |
| streamingBufferSize | Buffer size for streaming flush interval | 65536 | 8KB-1MB |
| connectionTimeout | Connection establishment timeout (ms) | 30000 | 1000-60000 |
| responseTimeout | Response timeout for large payloads (ms) | 300000 | 30000-600000 |
Tuning for Different Workloads
The optimal maxConcurrentStreams and
initialWindowSize depend on your traffic pattern. With
Apache HttpComponents 5.x, the PoolingAsyncClientConnectionManager
only opens a new TCP connection when all existing connections have reached
their maxConcurrentStreams limit. If this value is higher
than your typical concurrency, the pool will multiplex all streams onto a
single connection — which is efficient for many small requests but creates
flow-control contention for concurrent large payloads.
| Workload | Example | maxConcurrentStreams | initialWindowSize | maxConnPerRoute |
|---|---|---|---|---|
| Many small concurrent requests | Microservice mesh, API gateway | 50-100 | 2 MB | 10 |
| Few large concurrent payloads | Batch processing, ETL, report generation | 4-8 | 8 MB | 16-32 |
| Mixed traffic | General-purpose service client | 8-16 | 2 MB | 16 |
Client-side vs. server-side window: where tuning matters
HTTP/2 flow control is bidirectional — both client and server
advertise an initialWindowSize. For typical Axis2
deployments where the server produces large JSON responses and the
client sends smaller requests (query parameters, filter criteria),
the client-side window is the critical tuning point.
It governs how much response data the server can push before pausing
for a WINDOW_UPDATE from the client. A 64 KB client window on a
10 MB response means ~156 pause-and-acknowledge cycles.
The server's inbound window (configured in the application server —
e.g., WildFly's http2-initial-window-size, Tomcat's
http2InitialWindowSize) controls how much
request data the server allows in-flight. Since requests
are typically small relative to responses, the server-side default
(64 KB per the HTTP/2 spec) is usually adequate. Focus tuning effort
on the H2TransportSender client-side
initialWindowSize shown above.
If a single client consumes both small and large payload endpoints on
different hosts, consider configuring separate
CloseableHttpAsyncClient instances with per-workload tuning.
The connection pool's maxConnPerRoute already isolates
traffic by host, but maxConcurrentStreams and
initialWindowSize apply to the entire client.
Enterprise Big Data Configuration
For enterprise applications processing large JSON datasets (50MB+), use the following optimized configuration.
Note the lower maxConcurrentStreams (forces the pool to open multiple TCP connections under concurrent
load) and larger initialWindowSize (eliminates per-stream flow-control round-trips):
<transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender">
<parameter name="PROTOCOL">HTTP/2.0</parameter>
<!-- Stream Management: low stream count forces connection pooling
instead of multiplexing all large payloads onto one TCP connection -->
<parameter name="maxConcurrentStreams">4</parameter>
<parameter name="initialWindowSize">8388608</parameter> <!-- 8MB -- a 50MB payload completes in ~6 window updates -->
<parameter name="maxFrameSize">32768</parameter>
<!-- Large Payload Optimization -->
<parameter name="streamingBufferSize">65536</parameter>
<parameter name="memoryOptimized">true</parameter>
<!-- Connection Management: sized for concurrent large-payload fan-out -->
<parameter name="maxConnTotal">64</parameter>
<parameter name="maxConnPerRoute">32</parameter>
<!-- Timeouts for Large Payloads -->
<parameter name="connectionTimeout">30000</parameter>
<parameter name="responseTimeout">300000</parameter>
</transportSender>
HTTPS with HTTP/2 (ALPN)
HTTP/2 over HTTPS requires Application-Layer Protocol Negotiation (ALPN). The H2TransportSender automatically handles ALPN negotiation when used with HTTPS endpoints:
<transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> <parameter name="tlsRequired">true</parameter> <parameter name="alpnProtocols">h2,http/1.1</parameter> </transportSender>
Stream Multiplexing Configuration
HTTP/2 stream multiplexing allows multiple concurrent requests over a single connection, significantly improving performance for concurrent operations:
// Enable HTTP/2 multiplexing in client code Options options = new Options(); options.setProperty(HTTPConstants.TRANSPORT_NAME, "h2"); // HTTP/2 multiplexing is automatic when using the h2 transport. // No additional boolean flags are needed.
Large Payload Processing
The H2TransportSender provides three processing modes optimized for different payload sizes:
- Standard Processing (0MB-10MB): Regular HTTP/2 features
- Multiplexing Mode (10-50MB): Enhanced concurrent processing
- Streaming Mode (50MB+): Memory-efficient streaming with chunked processing
Streaming and memory optimization are controlled by the message formatter
selected in axis2.xml (e.g. MoshiStreamingMessageFormatter).
No client-side Options properties are required — the transport
sender negotiates HTTP/2 framing and flow control automatically.
Performance Monitoring
For production monitoring, use Micrometer with Prometheus/Grafana or Spring Boot Actuator endpoints. Application-level logging via the Axis2 log configuration provides per-request timing details.
Available metrics include:
- Stream allocation and utilization
- Memory usage and buffer efficiency
- Processing time and throughput
- Compression ratios and bandwidth savings
- Connection reuse statistics
Flow Control
HTTP/2 flow control is handled automatically by the transport layer.
The initialWindowSize parameter on the transport sender controls
the initial flow-control window; beyond that, the HTTP/2 implementation
manages window updates and back-pressure without additional configuration.
Compression
Response compression is handled by the servlet container (Tomcat, WildFly, etc.),
not by the Axis2 transport. Configure compression in your container's server
configuration (e.g., Tomcat's server.xml compression
attribute, or WildFly's Undertow content-encoding filter). HTTP/2 header
compression (HPACK) is always active and requires no Axis2 configuration.
Memory Management
Buffer management is handled internally by Apache HttpComponents 5.x.
The JVM's default direct memory limit (equal to -Xmx) is
sufficient for most deployments. No additional JVM flags are needed
for HTTP/2 buffer management.
Error Handling and Fallback
When the remote server does not support HTTP/2, the TLS ALPN negotiation falls back to HTTP/1.1 automatically. No explicit fallback parameters are required — Apache HttpComponents handles protocol negotiation.
Server Push
Server push is disabled by default — REST/JSON APIs follow request-response patterns where push provides no benefit. Enable only for web-app use cases with predictable resource dependencies:
<parameter name="serverPushEnabled">false</parameter> <!-- default -->
Service-Level HTTP/2 Configuration
Individual services can specify HTTP/2 preferences in their services.xml:
HTTP/2 is enabled at the transport level in axis2.xml, not per-service.
Select the H2TransportSender in the <transportSender> section
and configure its parameters there. For streaming large payloads, use the
streaming message formatter (e.g. MoshiStreamingMessageFormatter
or JSONStreamingMessageFormatter) in the service's message
receiver configuration. No service-level parameters are required.
Client-Side HTTP/2 Usage for SOAP (for JSON, see curl and Apache HTTPComponents section)
Complete client configuration example:
// Create HTTP/2 enabled service client
ConfigurationContext configContext = ConfigurationContextFactory
.createConfigurationContextFromFileSystem(null, null);
ServiceClient serviceClient = new ServiceClient(configContext, null);
// Configure HTTP/2 transport
Options options = new Options();
options.setProperty(HTTPConstants.TRANSPORT_NAME, "h2");
options.setTo(new EndpointReference("https://localhost:8443/services/BigDataService"));
// HTTP/2 is negotiated by the transport sender selected in axis2.xml.
// No additional boolean flags are needed — the h2 transport handles
// multiplexing, streaming, and flow control automatically.
// Timeout settings for large payloads
options.setTimeOutInMilliSeconds(300000); // 5 minutes
options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, 30000);
options.setProperty(HTTPConstants.SO_TIMEOUT, 300000);
serviceClient.setOptions(options);
Performance Comparison: HTTP/1.1 vs HTTP/2
HTTP/2 transport can provide substantial improvements over HTTP/1.1. The following are illustrative estimates — actual results depend on payload size, network conditions, and JVM configuration:
| Metric | HTTP/1.1 | HTTP/2 | Improvement |
|---|---|---|---|
| Connection Multiplexing | 6-8 connections | 100 concurrent streams | 1,150-1,567% |
| Memory Efficiency | Standard allocation | Pooled buffers | 30-50% |
| Large Payload (50MB) | Baseline | Streaming optimization | 50-200% |
| Compression | Basic gzip | JSON-aware optimization | 50-70% |
| Overall Throughput | Baseline | Combined optimizations | 70-150% |
Troubleshooting HTTP/2
Common HTTP/2 configuration issues and solutions:
ALPN Not Available
// Ensure ALPN support is available
System.setProperty("java.security.properties", "jdk.tls.alpnCharset=UTF-8");
Memory Issues with Large Payloads
// Increase heap size for large JSON payloads -Xmx4g -XX:+UseG1GC
Connection Issues
HTTP/2 fallback to HTTP/1.1 is automatic via TLS ALPN negotiation.
If the server does not advertise h2, the client falls back transparently.
Increase connectionTimeout on the transport sender if ALPN
negotiation is slow on your network.
Migration from HTTP/1.1 to HTTP/2
To migrate existing HTTP/1.1 configurations to HTTP/2:
- Change transport sender class to H2TransportSender
- Update protocol parameter to HTTP/2.0
- Add HTTP/2 specific parameters
- Configure HTTPS with ALPN support
- Test with fallback enabled
Example migration:
<!-- HTTP/1.1 Configuration --> <transportSender name="http" class="org.apache.axis2.transport.http.impl.httpclient5.HTTPClient5TransportSender"> <parameter name="PROTOCOL">HTTP/1.1</parameter> <parameter name="Transfer-Encoding">chunked</parameter> </transportSender> <!-- HTTP/2 Configuration --> <transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> <parameter name="maxConcurrentStreams">100</parameter> <parameter name="initialWindowSize">2097152</parameter> <!-- Fallback to HTTP/1.1 is automatic via TLS ALPN negotiation --> </transportSender>
SSL Client Authentication (2-Way SSL) with HTTP/2
HTTP/2 transport supports SSL client authentication (mutual TLS) similar to HTTP/1.1, with enhanced features for certificate management and ALPN negotiation. You can configure your own HttpAsyncClient with custom SSL context and certificate handling.
The HTTP/2 transport supports the same certificate management as HTTP/1.1 but uses async client architecture. To control max connections per host, SSL configuration, or other advanced parameters, set the cached HTTP/2 client using the CACHED_HTTP2_ASYNC_CLIENT property before making requests.
The following example shows SSL client authentication configuration tested with Axis2 on WildFly 32:
// Certificate and TrustStore setup (same as HTTP/1.1)
String wildflyserver_cert_path = "src/wildflyserver.crt";
Certificate certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(new FileInputStream(new File(wildflyserver_cert_path)));
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("server", certificate);
TrustManagerFactory trustManagerFactory = null;
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new Exception("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
// SSL Context with TLS 1.3 support for HTTP/2
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, trustManagers, new SecureRandom());
// HTTP/2 specific TLS strategy with ALPN support
TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
.setSslContext(sslContext)
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE) // For self-signed certificates
.setTlsDetailsFactory(sslEngine -> {
// Configure ALPN protocols for HTTP/2 negotiation
SSLParameters sslParams = sslEngine.getSSLParameters();
sslParams.setApplicationProtocols(new String[]{"h2", "http/1.1"});
sslEngine.setSSLParameters(sslParams);
return null;
})
.build();
// HTTP/2 async connection manager with SSL configuration
PoolingAsyncClientConnectionManager connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(tlsStrategy)
.setMaxConnTotal(100)
.setMaxConnPerRoute(100)
.build();
// Create HTTP/2 async client with SSL configuration
CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom()
.setConnectionManager(connManager)
.setConnectionManagerShared(true)
.setVersionPolicy(HttpVersionPolicy.NEGOTIATE) // Allow HTTP/2 negotiation
.build();
httpAsyncClient.start(); // Important: Start the async client
// Configure service client with HTTP/2 SSL client
Options options = new Options();
options.setTo(new EndpointReference("https://myserver:8443/services/MyService"));
options.setProperty(HTTPConstants.TRANSPORT_NAME, "h2"); // Use HTTP/2 transport
options.setTimeOutInMilliSeconds(120000);
// Set the cached HTTP/2 async client (HTTP/2 equivalent of CACHED_HTTP_CLIENT)
options.setProperty("CACHED_HTTP2_ASYNC_CLIENT", httpAsyncClient);
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
HTTP/2 SSL Configuration Parameters
The HTTP/2 transport provides additional SSL-specific parameters:
| Parameter | Description | Default | HTTP/1.1 Equivalent |
|---|---|---|---|
| CACHED_HTTP2_ASYNC_CLIENT | Custom HTTP/2 async client with SSL config | None | CACHED_HTTP_CLIENT |
| tlsRequired | Enforce HTTPS-only for HTTP/2 | true | N/A |
| alpnProtocols | ALPN protocol preferences | h2,http/1.1 | N/A |
| supportedTLSVersions | Supported TLS versions | TLSv1.2,TLSv1.3 | Similar |
| cipherSuites | Allowed cipher suites | TLS 1.3 defaults | Similar |
Advanced SSL Configuration for HTTP/2
For enterprise deployments requiring specific SSL configurations:
<transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> <!-- SSL/TLS Configuration --> <parameter name="tlsRequired">true</parameter> <parameter name="supportedTLSVersions">TLSv1.2,TLSv1.3</parameter> <parameter name="alpnProtocols">h2,http/1.1</parameter> <!-- ALPN Configuration --> <parameter name="alpnTimeout">5000</parameter> <parameter name="alpnFallbackEnabled">true</parameter> <!-- Certificate Validation --> <parameter name="hostnameVerification">strict</parameter> <parameter name="certificateValidation">strict</parameter> </transportSender>
Client Certificate Authentication
For mutual TLS (client certificate authentication) with HTTP/2:
// Load client certificate and private key
KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
clientKeyStore.load(new FileInputStream("client-cert.p12"), "password".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "password".toCharArray());
// SSL Context with client certificate
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, new SecureRandom());
// Configure HTTP/2 client with client certificate authentication
TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
.setSslContext(sslContext)
.setTlsDetailsFactory(sslEngine -> {
SSLParameters sslParams = sslEngine.getSSLParameters();
sslParams.setApplicationProtocols(new String[]{"h2", "http/1.1"});
sslParams.setNeedClientAuth(true); // Require client authentication
sslEngine.setSSLParameters(sslParams);
return null;
})
.build();
HTTP/2 vs HTTP/1.1 SSL Differences
Key differences in SSL handling between HTTP/1.1 and HTTP/2:
- ALPN Support: HTTP/2 requires ALPN negotiation for protocol selection
- TLS Version: HTTP/2 requires TLS 1.2 or higher (TLS 1.3 recommended)
- Cipher Suites: HTTP/2 has specific cipher suite requirements (RFC 7540)
- Async Architecture: Uses CloseableHttpAsyncClient instead of CloseableHttpClient
- Connection Multiplexing: Single SSL connection handles multiple streams
- Fallback Handling: Automatic fallback to HTTP/1.1 if HTTP/2 negotiation fails
SSL Notes
HTTP/2 requires TLS 1.2+ with ALPN. Use OpenJDK 11+ (ALPN built in). If ALPN negotiation fails, the transport falls back to HTTP/1.1 automatically (no configuration flag required).
Apache Axis2
