Apache Axis2 JSON and REST with Spring Boot 3 and Apache Tomcat 11 User's Guide

This guide covers writing and deploying JSON-RPC and REST services using Axis2 with Spring Boot 3 and Spring Security on Apache Tomcat 11. For the WildFly equivalent, see the WildFly guide. For the Spring Boot Starter (one-dependency setup), see the Starter guide.

More docs concerning Axis2 and JSON can be found in the Pure JSON Support documentation and JSON User Guide

Introduction

This user guide is written based on the Axis2 Standard Binary Distribution. The Standard Binary Distribution can be directly downloaded or built using the Source Distribution. If you choose the latter, then the Installation Guide will instruct you on how to build Axis2 Standard Binary Distribution using the source.

The source code for this guide provides a pom.xml for an entire demo WAR application built by maven.

Please note that Axis2 is an open-source effort. If you feel the code could use some new features or fixes, please get involved and lend us a hand! The Axis developer community welcomes your participation.

Let us know what you think! Send your feedback to "java-user@axis.apache.org". (Subscription details are available on the Axis2 site.) Kindly prefix the subject of the mail with [Axis2].

Differences from the WildFly 32 Guide

This guide is based on the Apache Axis2 JSON and REST with Spring Boot 3 User's Guide, which targets WildFly 32. The following table summarises all differences:

Aspect WildFly 32 / 39 Tomcat 11
Context root /axis2-json-api (WAR name becomes context root automatically) / (deployed into webapps/ROOT/); base URL is http://localhost:8080/services/...
Deploy method Copy WAR directory to standalone/deployments/, then touch axis2-json-api.war.dodeploy cp -r target/deploy/axis2-json-api.war/* $CATALINA_HOME/webapps/ROOT/ then start Tomcat
WildFly-specific files WEB-INF/jboss-deployment-structure.xml, WEB-INF/jboss-web.xml required These files must not be present; springbootdemo-tomcat11 omits them
DataSource auto-configuration WildFly's JPA subsystem suppresses Spring Boot's DataSource auto-config automatically Must exclude explicitly in @SpringBootApplication: exclude={DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class}
HTTP/2 configuration Configured via WildFly subsystem Requires <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/> in server.xml HTTPS connector; Java 9+ ALPN, no native library needed
JSON request format Identical for both servers: {"methodName":[{"paramName":{...}}]}

All sample source code for this guide is located in the "modules/samples/userguide/src/springbootdemo-tomcat11" directory of Axis2 standard binary distribution.

See Also: Axis2/C 2.0.0

Axis2/C 2.0.0 is in release vote and expected to ship around the same time as Axis2/Java 2.0.1. It provides equivalent services (BigDataH2, Login, TestWS) implemented in native C with Apache httpd and mod_h2. For most Java users this is of no interest. For those who need maximum throughput or minimal memory footprint, native C achieves 240MB peak for a 50MB JSON payload versus JVM heap overhead, and 26 MB/s JSON throughput with zero warm-up time.

The performance headroom is sufficient to run the full HTTP/2 service stack on Android — the Axis2/C Android guide covers a camera control service that uses this approach. This is a notable milestone: the previous Axis2/C release was 1.6 in 2009.

HTTP/2 Transport

Axis2's HTTP/2 support is integrated into the serialization pipeline — the streaming JSON formatter flushes every 64 KB, producing HTTP/2 DATA frames during serialization, not after. This keeps server memory flat regardless of response size. For configuration details, see the HTTP/2 Transport documentation and the HTTP/2 overview.

See also: OpenAPI REST User Guide for auto-generated API documentation.

Enabling HTTP/2 on Tomcat 11

Tomcat 11 supports HTTP/2 via NIO2 with Java 9+ ALPN — no native (APR) library is required. To enable HTTP/2, update the HTTPS connector in $CATALINA_HOME/conf/server.xml:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="200" SSLEnabled="true">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    <SSLHostConfig>
        <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                     type="RSA" />
    </SSLHostConfig>
</Connector>

The <UpgradeProtocol> element activates HTTP/2 with ALPN negotiation. Clients that do not support HTTP/2 automatically fall back to HTTP/1.1 over TLS.

To generate a self-signed keystore for development:

keytool -genkey -alias localhost -keyalg RSA -keysize 2048 \
        -keystore $CATALINA_HOME/conf/localhost-rsa.jks \
        -validity 365 -storepass changeit -keypass changeit \
        -dname "CN=localhost, OU=Dev, O=Test, L=City, ST=State, C=US"

Building and Deploying to Tomcat 11

Build the WAR with Maven:

cd modules/samples/userguide/src/userguide/springbootdemo-tomcat11
mvn clean install

The build produces an exploded WAR directory at target/deploy/axis2-json-api.war/. Deploy it to Tomcat 11 by copying the directory contents into the ROOT (or another) context:

# Deploy as root context
$CATALINA_HOME/bin/shutdown.sh
rm -rf $CATALINA_HOME/webapps/ROOT/*
cp -r target/deploy/axis2-json-api.war/* $CATALINA_HOME/webapps/ROOT/
$CATALINA_HOME/bin/startup.sh

Note: The build output is an exploded directory, not a zip file — do not use jar -xf or treat it as a compressed archive. The cp -r command is required so that WEB-INF/conf/axis2.xml and the service .aar files are included in the deployment.

Verify deployment in the Tomcat manager or by checking the logs:

tail -f $CATALINA_HOME/logs/catalina.out

You should see the Spring Boot application context starting and Axis2 servlet registering without errors. Because the contents are deployed into webapps/ROOT/, the context root is / — service URLs begin with http://localhost:8080/services/..., not /axis2-json-api/services/... as on WildFly.

Getting Started

This user guide explains how to write and deploy a new JSON and REST based Web Service using Axis2, and how to invoke a Web Service client using JSON with Curl.

All the sample code mentioned in this guide is located in the "modules/samples/userguide/src/springbootdemo-tomcat11" directory of Axis2 standard binary distribution.

This guide supplies a pom.xml for building an exploded WAR with Spring Boot 3 - however this WAR does not have an embedded web server such as Tomcat.

Testing was carried out on Apache Tomcat 11.0.20 with OpenJDK 21 and OpenJDK 25, by installing the WAR in its app server.

Please deploy the result of the maven build via 'mvn clean install', axis2-json-api.war, into your servlet container and ensure that it installs without any errors.

Creating secure Web Services

Areas out of scope for this guide are JWT and JWE for token generation and validation, since they require elliptic curve cryptography. A sample token that is not meant for production is generated in this demo - with the intent that the following standards should be used in its place. This demo merely shows a place to implement these standards.

https://datatracker.ietf.org/doc/html/rfc7519

https://datatracker.ietf.org/doc/html/rfc7516

Tip: com.nimbusds is recommended as an open-source Java implementation of these standards, for both token generation and validation.

DB operations are also out of scope. There is a minimal DAO layer for authentication. Very limited credential validation is done.

The NoOpPasswordEncoder Spring class included in this guide is meant for demos and testing only. Do not use this code as is in production.

This guide provides three JSON based web services: LoginService, TestwsService, and the new BigDataH2Service which demonstrates HTTP/2 transport capabilities for enterprise big data processing.

BigDataH2Service - HTTP/2 Big Data Processing Service

The BigDataH2Service showcases HTTP/2 transport benefits for large JSON datasets:

  • Large Dataset Processing: Handles JSON datasets from small (1MB) to enterprise-scale (100MB+)
  • Automatic Optimization: Selects optimal processing mode based on dataset size
  • Memory Efficiency: Streaming and chunked processing for memory-constrained environments
  • Performance Metrics: Built-in monitoring for throughput, memory usage, and HTTP/2 optimization indicators
  • Security Validation: OWASP ESAPI input validation and HTTPS-only enforcement

The login, if successful, will return a simple token not meant for anything beyond demos. The intent of this guide is to show a place that the JWT and JWE standards can be implemented.

Axis2 JSON support is via POJO Objects. LoginRequest and LoginResponse are coded in the LoginService as the names would indicate. A flag in the supplied axis2.xml file, enableJSONOnly, disables Axis2 functionality not required for JSON and sets up the server to expect JSON.

Security Benefits of enableJSONOnly

The enableJSONOnly parameter provides significant security hardening by enforcing strict JSON-only processing:

  • Content-Type Enforcement: Rejects requests without "Content-Type: application/json" header, preventing content-type confusion attacks
  • Protocol Restriction: Disables SOAP, XML, and other message formats that could introduce XXE (XML External Entity) vulnerabilities
  • Attack Surface Reduction: Eliminates unused Axis2 functionality, reducing potential security vulnerabilities in XML parsing and SOAP processing
  • Input Validation: Ensures only well-formed JSON payloads are accepted, preventing malformed request attacks
  • Request Filtering: Blocks non-JSON requests at the transport level, providing an additional security barrier

Security Best Practice: When combined with HTTPS-only enforcement (required for HTTP/2), enableJSONOnly creates a secure, hardened API endpoint that accepts only authenticated JSON requests over encrypted connections.

Also provided is a test service, TestwsService. It includes two POJO Objects as would be expected, TestwsRequest and TestwsResponse. This service attempts to return a String with some Javascript, that is HTML encoded by Axis2 and thereby eliminating the possibility of a Javascript engine executing the response i.e. a reflected XSS attack.

Concerning Spring Security and Spring Boot 3, the Axis2Application class that extends SpringBootServletInitializer as typically done utilizes a List of SecurityFilterChain as a binary choice; A login url will match, otherwise invoke JWTAuthenticationFilter. All URL's to other services besides the login, will proceed after JWTAuthenticationFilter verifies the token.

The JWTAuthenticationFilter class expects a token from the web services JSON client in the form of "Authorization: Bearer mytoken".

The Axis2WebAppInitializer class supplied in this guide, is the config class that registers AxisServlet with Spring Boot 3.

Axis2 web services are installed via a WEB-INF/services directory that contains files with an .aar extension for each service. These aar files are similar to jar files, and contain a services.xml that defines the web service behavior. The pom.xml supplied in this guide generates these files.

Tip: don't expose methods in your web services that are not meant to be exposed, such as getters and setters. Axis2 determines the available methods by reflection. For JSON, the message name at the start of the JSON received by the Axis2 server defines the Axis2 operation to invoke. It is recommended that only one method per class be exposed as a starting point. The place to add method exclusion is the services.xml file:

    <excludeOperations>
        <operation>setMyVar</operation>
    </excludeOperations>

The axis2.xml file can define GSON or Moshi as the JSON engine. GSON was the original however development has largely ceased. Moshi is very similar and is widely considered to be the superior implementation in terms of performance. GSON will likely continue to be supported in Axis2 because it is helpful to have two JSON implementations to compare with for debugging.

JSON based web services in the binary distribution of axis2.xml are not enabled by default. See the supplied axis2.xml of this guide, and note the places were it has "moshi". Just replace "moshi" with "gson" as a global search and replace to switch to GSON.

Axis2 web services that are JSON based must be invoked from a client that sets an HTTP header as "Content-Type: application/json". In order for axis2 to properly handle JSON requests, this header behavior needs to be defined in the file WEB-INF/conf/axis2.xml.

    <message name="requestMessage">
        <messageFormatter contentType="application/json"
                          class="org.apache.axis2.json.moshi.JsonFormatter"/>

Other required classes for JSON in the axis2.xml file include JsonRpcMessageReceiver, JsonInOnlyRPCMessageReceiver, JsonBuilder, JSONBasedDefaultDispatcher and JSONMessageHandler.

HTTP/2 Transport Configuration

To enable HTTP/2 transport for enterprise big data processing, add the following transport sender configuration to your axis2.xml file:

<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>
    <parameter name="serverPushEnabled">false</parameter>
    <parameter name="connectionTimeout">30000</parameter>
    <parameter name="responseTimeout">300000</parameter>
    <parameter name="streamingBufferSize">65536</parameter>
</transportSender>

HTTP/2 Configuration Parameters

  • maxConcurrentStreams: Maximum concurrent HTTP/2 streams (default: 100)
  • initialWindowSize: HTTP/2 flow control window size (default: 64KB, 2MB recommended for large payloads)
  • connectionTimeout: Connection establishment timeout in ms (default: 30000)
  • responseTimeout: Timeout for large payload processing (default: 300000 = 5 minutes)
  • streamingBufferSize: Buffer size for streaming operations (default: 65536 = 64KB)

Client Usage with cURL

Invoking the client for a login that returns a token can be done as follows:

curl -v -H "Content-Type: application/json" -X POST --data @login.dat http://localhost:8080/services/loginService

Where the contents of login.dat are:

{"doLogin":[{"arg0":{"email":"user@example.org","credentials":"userguide"}}]}

Response:

{"response":{"status":"OK","token":"95104Rn2I2oEATfuI90N","uuid":"99b92d7a-2799-4b20-b029-9fbd6108798a"}}

Invoking the client for a Test Service that validates a sample token can be done as follows:

curl -v -H "Authorization: Bearer 95104Rn2I2oEATfuI90N" -H "Content-Type: application/json" -X POST --data @test.dat http://localhost:8080/services/testws'

Where the contents of test.dat are below. arg0 is a var name and is used by Axis2 as part of its reflection based code:

{"doTestws":[{"arg0":{"messagein":hello}}]}

Response, HTML encoded to prevent XSS. For the results with encoding see src/site/xdoc/docs/json-springboot-tomcat11-userguide.xml.

{"response":{"messageout":"<script xmlns=\"http://www.w3.org/1999/xhtml\">alert('Hello');</script> \">","status":"OK"}}

BigDataH2Service Example

The BigDataH2Service demonstrates HTTP/2 streaming for large JSON payloads:

curl -v -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -X POST \
     --data '{"processBigDataSet":[{"arg0":{"datasetId":"test_001","datasetSize":52428800}}]}' \
     https://localhost:8443/services/BigDataH2Service

The service returns processing metrics including throughput (MB/s), memory usage, and record count. For the HTTP/2 Java client example showing how to stream large responses without buffering, see the sample code.