Axis2 JSON-RPC services deployed as a WAR in Apache Tomcat 11, using Spring Boot 3.x as a configuration framework only — there is no embedded container.
Tested with: Tomcat 11.0.20 · OpenJDK 21 · Spring Boot 3.4.3
JDK compatibility note: The WAR is compiled at Java 21 source level (
<java.version>21</java.version>) and has been tested on both OpenJDK 21 and OpenJDK 25 under Tomcat 11.
| Service | Operation | Path | Auth |
|---|---|---|---|
loginService | doLogin | POST /axis2-json-api/services/loginService | None (public) |
testws | doTestws | POST /axis2-json-api/services/testws | Bearer token |
BigDataH2Service | processBigDataSet | POST /axis2-json-api/services/BigDataH2Service | Bearer token |
FinancialBenchmarkService | portfolioVariance | POST /axis2-json-api/services/FinancialBenchmarkService | Bearer token |
FinancialBenchmarkService | monteCarlo | POST /axis2-json-api/services/FinancialBenchmarkService | Bearer token |
FinancialBenchmarkService | scenarioAnalysis | POST /axis2-json-api/services/FinancialBenchmarkService | Bearer token |
| OpenAPI spec (JSON) | — | GET /axis2-json-api/openapi.json | None |
| OpenAPI spec (YAML) | — | GET /axis2-json-api/openapi.yaml | None |
| Swagger UI | — | GET /axis2-json-api/swagger-ui | None |
| OpenAPI MCP | — | GET /axis2-json-api/openapi-mcp.json | None |
cd modules/samples/userguide/src/userguide/springbootdemo-tomcat11 mvn package
This produces an exploded WAR directory at target/deploy/axis2-json-api/.
# Copy exploded WAR to Tomcat webapps cp -r target/deploy/axis2-json-api /path/to/tomcat/webapps/ # Restart Tomcat /path/to/tomcat/bin/shutdown.sh && /path/to/tomcat/bin/startup.sh
Tomcat strips the .war suffix when deploying a packaged foo.war file, giving context path /foo. However, when deploying an exploded directory, Tomcat uses the directory name as-is. A directory named axis2-json-api.war/ deploys at context path /axis2-json-api.war, not /axis2-json-api.
The Maven build produces target/deploy/axis2-json-api (no .war suffix) for exactly this reason. Do not rename the directory before copying to webapps/.
All tests use HTTPS/HTTP2 on port 8443 with mTLS client certificates. The Tomcat connector requires certificateVerification="required" — plain HTTP is not available.
Set up the cert variables first:
CERTS=/path/to/axis-axis2-java-core/certs CURL_MTLS="curl -s --http2 --cert $CERTS/client.crt --key $CERTS/client.key --cacert $CERTS/ca.crt"
$CURL_MTLS https://localhost:8443/axis2-json-api/openapi.json $CURL_MTLS https://localhost:8443/axis2-json-api/openapi.yaml $CURL_MTLS https://localhost:8443/axis2-json-api/openapi-mcp.json # Interactive UI: $CURL_MTLS https://localhost:8443/axis2-json-api/swagger-ui
$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/loginService \ -H 'Content-Type: application/json' \ -d '{"doLogin":[{"arg0":{"email":"java-dev@axis.apache.org","credentials":"userguide"}}]}'
Response: {"response":{"token":"<TOKEN>","uuid":"<UUID>","status":"OK"}}
messagein must pass ESAPI SafeString validation ([A-Za-z0-9.,\-_ ]* — no + or special characters).
TOKEN="<token from step 2>" $CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/testws \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"doTestws":[{"arg0":{"messagein":"hello world"}}]}'
datasetSize is in bytes. Size determines processing path: under 10 MB → standard, 10–50 MB → multiplexing, >50 MB → streaming. Use at least 1 000 000 to get populated results.
$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/BigDataH2Service \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"processBigDataSet":[{"arg0":{"datasetId":"test-001","datasetSize":1000000,"processingMode":"streaming","enableMemoryOptimization":true,"analyticsType":"summary"}}]}'
Response includes processedRecordCount, http2Optimized, memoryOptimized, and a processedRecords array.
# Portfolio variance — O(n²) covariance matrix $CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{"nAssets":2,"weights":[0.6,0.4],"covarianceMatrix":[[0.04,0.006],[0.006,0.09]],"normalizeWeights":false,"nPeriodsPerYear":252}}]}' # Monte Carlo VaR — GBM simulation $CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"monteCarlo":[{"arg0":{"nSimulations":10000,"nPeriods":252,"initialValue":100.0,"expectedReturn":0.08,"volatility":0.20,"nPeriodsPerYear":252,"randomSeed":42}}]}' # Scenario analysis — probability-weighted expected return $CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"scenarioAnalysis":[{"arg0":{"assets":[{"assetId":1,"currentPrice":100.0,"positionSize":100,"scenarios":[{"price":120.0,"probability":0.3},{"price":100.0,"probability":0.5},{"price":75.0,"probability":0.2}]}],"useHashLookup":true,"probTolerance":0.001}}]}'
Axis2 2.0.1 includes streaming message formatters that prevent reverse proxy body-size rejections on large HTTP responses. Drop-in replacement — no service code changes required.
Problem solved (response-side): The default formatter buffers the entire JSON response before writing to the wire. A reverse proxy may return 502 Bad Gateway on large responses. The streaming formatter flushes every 64 KB (configurable), so the proxy sees a stream of chunks, never the full body.
Not solved (request-side): Large HTTP request bodies (client → server) are a client-side problem. If a client sends a 620 MB POST and the proxy rejects it, the fix is client-side: break the request into smaller payloads or add a pre-send size guard.
| Variant | Class |
|---|---|
| GSON | org.apache.axis2.json.streaming.JSONStreamingMessageFormatter |
| Moshi | org.apache.axis2.json.streaming.MoshiStreamingMessageFormatter |
Enable globally in axis2.xml:
<messageFormatter contentType="application/json" class="org.apache.axis2.json.streaming.MoshiStreamingMessageFormatter"/>
Optional flush interval tuning per-service in services.xml:
<parameter name="streamingFlushIntervalBytes">131072</parameter>
Applies to all services (BigDataH2Service, FinancialBenchmarkService, any custom service). Tested on WildFly 32 locally and behind a real reverse proxy (with HTTP/2 ALPN). Bit-identical results to the non-streaming formatter.
See the Streaming JSON Message Formatter guide for full documentation.
The top-level key is the operation name, and the value is an array containing one object whose key is the argument name (conventionally arg0) and whose value is the request POJO:
{ "operationName": [{ "arg0": { ...fields... } }] }
This is mandated by JsonUtils.invokeServiceClass() in the axis2-json module.
Axis2Application extends SpringBootServletInitializer, not SpringApplication.run(). Spring Boot only provides configuration; Tomcat is the server.DispatcherServlet — @GetMapping annotations are dead code in this module. OpenAPI endpoints are served by OpenApiServlet, a plain HttpServlet registered directly in Axis2WebAppInitializer at /openapi.json, /openapi.yaml, /swagger-ui, and /openapi-mcp.json.Axis2WebAppInitializer explicitly sets the axis2.repository.path servlet init parameter using ServletContext.getRealPath("/WEB-INF"). This is required on both Tomcat and WildFly to ensure WarBasedAxisConfigurator finds the WEB-INF/services/*.aar archives reliably, bypassing any VFS or lazy-init timing issues.axis2-openapi-<version>.jar is copied to WEB-INF/modules/openapi-<version>.mar by the Maven build. It must be present for GET /openapi.* and GET /swagger-ui to work.springbootdemo-wildflyspringbootdemo-tomcat11 and springbootdemo-wildfly share all Java source and resources via build-helper-maven-plugin. The only differences are container-specific:
| Aspect | springbootdemo-tomcat11 | springbootdemo-wildfly |
|---|---|---|
| Server | Apache Tomcat 11 | WildFly 32+ (Undertow) |
| Tested on | Tomcat 11.0.20 / Java 21 and Java 25 | WildFly 39 / Java 25 |
| WAR output | target/deploy/axis2-json-api/ (no .war suffix) | target/deploy/axis2-json-api/ |
| Extra WEB-INF files | — | jboss-deployment-structure.xml, jboss-web.xml, beans.xml |
| Context path | /axis2-json-api | /axis2-json-api |