Published in · 5 min read · Dec 30, 2024
In this guide, we’ll walk through how to consume a SOAP service using a WSDL file with Spring Boot and Maven. This includes understanding SOAP and WSDL, generating Java classes from the WSDL, setting up your Spring Boot application, and interacting with the SOAP service programmatically.
Before jumping into the code, let’s briefly explore the concepts:
SOAP (Simple Object Access Protocol)
SOAP is a messaging protocol to exchange structured information between systems using XML.
Key features include:
- XML-based Communication: SOAP messages are XML documents sent over HTTP, which are formatted based on the information in the WSDL.
- Transport Protocols: Commonly uses HTTP but can work with other protocols like SMTP.
- Reliable Messaging: Ensures data integrity and delivery between web applications, much like a postal service for software.
WSDL (Web Services Description Language)
WSDL serves as a contract between a web service provider and its clients.
Key features include:
- Service Description — Usability: It’s like a menu at a restaurant. WSDL tells you what services a SOAP web service offers, what parameters it expects (requests), and what it serves back to you(responses).
- XML-based Format: A standardized XML-based file format that describes the operations, inputs, outputs, and data types of a SOAP web service
The benefits of SOAP services include:
- Platform and Language Independence: As SOAP is XML-based, it facilitates seamless communication between different platforms and programming languages, simplifying system integration.
- Standardized Protocol: Operating over defined protocols such as HTTP and SMTP, SOAP provides a reliable and standards-compliant framework.
- Enhanced Security Support: With WS-Security standards, it ensures data integrity and confidentiality, making it a secure choice for communication.
- Stateless Communication: SOAP operates in a stateless manner between client and server, promoting scalability and a stateless architecture.
Now that we have an understanding of SOAP and WSDL, let’s move on to the code! 😎🦾
First, create a Spring Boot project using your favorite IDE or Spring Initializr. Use the following settings:
- Java Version: 21
- Spring Boot Version:3.4.1 (or the latest stable release)
Add the following sependencies to pom.xml:
- Spring Web: Provides REST and web-related functionalities.
- Spring Web Services: Required for working with SOAP.
- JAXB: For mapping XML to Java objects.
- Lombok (optional): Reduces boilerplate code.
- DevTools (optional): Enables hot-reloading for development.
<dependencies>
<!-- Spring Web for building web applications -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- Spring Web Services for SOAP -->
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
</dependency>
<!-- JAXB for XML Binding -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- Apache CXF for generating Java classes from WSDL -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
</dependency>
</dependencies>
First, let’s take a look at the WSDL (Web Services Description Language) for the SOAP service we’ll consume. In the example below, the WSDL describes two operations: ping and findById.
WSDL Example:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:web="http://www.yourwsdlservice.com/wsdl"
targetNamespace="http://www.yourwsdlservice.com/wsdl"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<!-- Ping Service -->
<message name="PingRequest">
<part name="message" type="xsd:string"/>
</message>
<message name="PingResponse">
<part name="response" type="xsd:string"/>
</message> <portType name="PingServicePortType">
<operation name="ping">
<input message="web:PingRequest"/>
<output message="web:PingResponse"/>
</operation>
</portType>
<binding name="PingServiceBinding" type="web:PingServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="ping">
<soap:operation soapAction="http://www.yourwsdlservice.com/wsdl/ping"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="PingService">
<port name="PingServicePort" binding="web:PingServiceBinding">
<soap:address location="http://www.yourwsdlservice.com/wsdl/ping"/>
</port>
</service>
<!-- FindById Service -->
<message name="FindByIdRequest">
<part name="id" type="xsd:int"/>
</message>
<message name="FindByIdResponse">
<part name="result" type="xsd:string"/>
</message>
<portType name="FindByIdServicePortType">
<operation name="findById">
<input message="web:FindByIdRequest"/>
<output message="web:FindByIdResponse"/>
</operation>
</portType>
<binding name="FindByIdServiceBinding" type="web:FindByIdServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="findById">
<soap:operation soapAction="http://www.yourwsdlservice.com/wsdl/findById"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="FindByIdService">
<port name="FindByIdServicePort" binding="web:FindByIdServiceBinding">
<soap:address location="http://www.yourwsdlservice.com/wsdl/findById"/>
</port>
</service>
</definitions>
We use the CXF Maven Plugin to generate Java classes from the WSDL, add the Plugin to pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>http://www.yourwsdlservice.com/wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Run Maven Command
After configuring the plugin in your pom.xml, you can run:
mvn clean compile
This will generate Java classes for the SOAP service, including the necessary request and response objects for your soap services.
The generated classes will be located under target/generated-sources.
Now that the Java classes are generated, let’s create the SOAP client.
Configure Web Service Template
Let’s configure a WebServiceTemplate to interact with the SOAP service.
package com.example.soapclient;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
@Configuration
public class SoapClientConfig {
@Bean
public WebServiceTemplate webServiceTemplate() {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMessageSender(new HttpComponentsMessageSender());
return webServiceTemplate;
}
}
Calling our Methods (here, ping and findById)
Now, we’ll write a service class for consuming the SOAP operations; here, we call the ping and findById SOAP operations for example:
package com.example.soapclient;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.SOAPFaultClientException;
@Service
public class SoapClientService {
@Autowired
private WebServiceTemplate webServiceTemplate;
private static final String PING_URL = "http://www.yourwsdlservice.com/wsdl/ping";
private static final String FIND_BY_ID_URL = "http://www.yourwsdlservice.com/wsdl/findById";
public String ping(String message) {
PingRequest request = new PingRequest();
request.setMessage(message);
try {
PingResponse response = (PingResponse) webServiceTemplate.marshalSendAndReceive(PING_URL, request);
return response.getResponse();
} catch (SOAPFaultClientException e) {
return "Error: " + e.getMessage();
}
}
public String findById(int id) {
FindByIdRequest request = new FindByIdRequest();
request.setId(id);
try {
FindByIdResponse response = (FindByIdResponse) webServiceTemplate.marshalSendAndReceive(FIND_BY_ID_URL, request);
return response.getResult();
} catch (SOAPFaultClientException e) {
return "Error: " + e.getMessage();
}
}
}
Now, you can test your client by calling the ping and findById methods in a Spring Boot controller or a command-line runner:
package com.example.soapclient;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SoapClientApplication implements CommandLineRunner {
@Autowired
private SoapClientService soapClientService;
public static void main(String[] args) {
SpringApplication.run(SoapClientApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// Test ping
String pingResponse = soapClientService.ping("Hello");
System.out.println("Ping Response: " + pingResponse);
// Test findById
String findByIdResponse = soapClientService.findById(123);
System.out.println("FindById Response: " + findByIdResponse);
}
}
In this guide, we have demonstrated how to consume a SOAP service in a Spring Boot application using a WSDL. We used Maven to generate Java classes from the WSDL, configured a SOAP client with WebServiceTemplate, and invoked the ping and findById methods. By following this approach, you can easily integrate SOAP-based services into your Spring Boot applications.
Feel free to reach out to me if you have any questions or would like to add something! 😇
Happy learning! 🦾🎉🥳