Building a SOAP web service with Spring Boot and JAX-WS
Despite SOAP often being dismissed by developers chasing the latest REST trends, it remains deeply entrenched across Australian enterprise systems. Banks in Sydney and Melbourne still rely on SOAP integrations with ATO gateways, BPAY settlement systems, and legacy superannuation platforms. For many dev teams in Brisbane or Perth, exposing SOAP endpoints from a modern Spring Boot application is more than an academic exercise; it's a daily reality.
JAX-WS, the Java API for XML Web Services, has been part of the Jakarta EE ecosystem for years. Combined with Spring Boot's auto-configuration, you get a stack that bridges legacy XML contracts with the rapid development cycle modern teams expect. The pairing works particularly well when integrating with government services or healthcare platforms that haven't embraced JSON protocols yet.
This walkthrough covers the essentials of building a SOAP web service using Spring Boot and JAX-WS, from contract definition through to deployment. You'll see practical code samples, configuration tips, and advice drawn from real Australian integration scenarios.
Understanding SOAP and JAX-WS fundamentals
SOAP uses XML envelopes to structure requests and responses. Unlike REST, SOAP enforces a strict contract defined by WSDL. This contract-first approach explains why Australian regulatory bodies and banks keep favouring SOAP for sensitive integrations: the message structure is fixed, validated, and easier to audit.
JAX-WS is the standard Java API for building and consuming SOAP services. It abstracts away much of the XML marshalling boilerplate using JAXB. When you combine JAX-WS with Spring Boot, you can leverage dependency injection, property files, and profile-specific configuration alongside your web service implementation.
A typical JAX-WS service in Spring Boot consists of three pieces: a WSDL file, a service endpoint interface (SEI), and an implementation class. Spring Boot provides the runtime container and bean wiring, while JAX-WS handles the SOAP protocol mechanics. Many Australian teams pair this stack with a Hibernate backend, so understanding persistence patterns alongside your SOAP contract is worthwhile. If you need a refresher, a guide to Hibernate covers the essentials.
Setting up your Spring Boot project
Start by generating a fresh Spring Boot project through Spring Initializr. Most Australian enterprise teams default to Maven, though Gradle works equally. Include spring-boot-starter-web and add spring-boot-starter-web-services to pull in Spring Web Services support.
You'll also need a JAX-WS runtime. While Java's reference implementation is no longer bundled with modern JDKs, you can add Metro or Apache CXF as your provider. For developers juggling multiple integration projects, Maven's BOM approach keeps version drift manageable.
Configure your application.properties with sensible defaults: server port, application name, and any endpoint-specific properties. If you're building a service that talks to the ATO or Medicare, you'll need additional security configuration, which deserves a separate discussion.
Core dependencies and tools for the project:
spring-boot-starter-web-servicesfor Spring WS supportjakarta.xml.ws:jakarta.xml.ws-apifor the JAX-WS API- A JAX-WS runtime such as Metro or Apache CXF
wsdl4jfor WSDL parsing at runtime if needed- SoapUI or ReadyAPI for manual endpoint testing
Defining the WSDL contract
Contract-first development means designing your WSDL before writing any Java code. Place your WSDL and accompanying XSD schema files under src/main/resources/wsdl/. This folder layout matters where audit traceability between contract artefacts and source code is required, which is common in government integration projects.
When crafting your WSDL, define your operations, message types, and port types clearly. Use XML namespaces consistently, and align your schema definitions with the domain objects your service exposes. A clean WSDL reduces integration friction when enterprise architects review your work.
Tools like Oxygen XML Editor or Visual Studio Code with the right extensions make WSDL editing less painful. If you're building an endpoint that mirrors an existing service, say, an EFPOS payment adapter, your WSDL needs to match the upstream provider's contract precisely.
Implementing the endpoint and service
Create your Service Endpoint Interface with @WebService and @WebMethod annotations, then implement it as a regular Spring @Service bean. Spring's SimpleJaxWsServiceExporter or a custom servlet config bean publishes your endpoint at the desired URL.
Here's a skeleton to get started:
@WebService(serviceName = "PaymentService")
public interface PaymentServiceEndpoint {
@WebMethod
PaymentResponse processPayment(PaymentRequest request);
}
@Service
@WebService(serviceName = "PaymentService",
endpointInterface = "com.example.PaymentServiceEndpoint")
public class PaymentServiceImpl implements PaymentServiceEndpoint {
@Override
public PaymentResponse processPayment(PaymentRequest request) {
return response;
}
}
Add a @Configuration class to expose your endpoint via SimpleJaxWsServiceExporter or by registering a servlet. Mind your thread pool settings if you expect heavy concurrent traffic, particularly during peak settlement windows in Australian banking hours.
Testing and deployment considerations
Testing SOAP services requires tools that understand WSDL contracts. SoapUI is still the go-to for many Australian testers, though Postman now offers reasonable SOAP support. For automated tests, generate client classes from your WSDL using wsimport or cxf-codegen-plugin, then exercise the endpoint with JUnit.
Pitfalls to watch for when integrating with Australian systems:
- Missing JAXB annotations causing marshal errors during NPP message handling
- Namespace mismatches between WSDL and incoming requests
- Time zone handling when bridging systems across states
- Certificate-based authentication for ATO or BPAY endpoints
- WSDL location drift between dev, test, and production environments
When deploying to production, containerise your application and target AWS Sydney (ap-southeast-2) or Melbourne regions for data sovereignty reasons. Configure health checks and metrics via Spring Boot Actuator so your operations team can spot issues before peak settlement loads.