Learn to consume a SOAP web service in a Spring Boot application using auto client proxy class generation with the JAXB maven plugin. The WebServiceTemplate class simplifies the process of sending and receiving SOAP messages in a Spring Boot application. It also integrates with marshallers and unmarshallers (like JAXB) to convert between XML and Java objects.
This tutorial uses WebServiceGatewaySupport to facilitate the creation of web service clients. It simplifies the setup and use of WebServiceTemplate by providing configuration and template management out-of-the-box.
1. Prerequisite
- Before running this example, we need the SOAP web service running which we will invoke from this client code. For this, you may download the attached maven project (at the end of the article), and run that in the local workspace, and use that.
- Once you run this SOAP server project, you will get the WSDL from ‘http://localhost:8080/service/studentDetailsWsdl.wsdl‘. Download the WSDL somewhere as ‘studentDetailsWsdl.wsdl‘ and later we will place this in ‘resources/wsdl‘ folder of the client project which we will create next to generate the client proxy code.
2. Technology Stack
- JDK 21, IntelliJ IDE or Eclipse
- Spring Boot 3.2
- Maven-jaxb2-plugin plugin – for JAXB stub generation
3. Project Structure
The classes and files created for this demo would look like below.

4. Creating Soap Client using WebServiceTemplate
4.1. Create Boot Project
Create one spring boot project from Spring Initializr site with ‘Web Services‘ dependency only. After selecting the dependency and giving the proper maven GAV coordinates, download the project in zipped format. Unzip and then import the project in IDE as a maven project.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
4.2. Generating Domain Classes
Now use maven-jaxb2-plugin
maven plugin to generate the JAXB annotated stub classes. To do that add this maven plugin in the pom.xml
of the project.
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.15.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>com.example.howtodoinjava.schemas.school</generatePackage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>
</plugins>
</build>
Next, run the MVC compile command to trigger the code generation.
mvn compile
This plugin will generate the classes, the first time. For every subsequent run, it will check the generated timestamp of the classes so that those classes are generated only when any change in the WSDL happens.
4.3. Create SOAP Client with WebServiceTemplate
Create a class called SOAPConnector which will act as a generic web service client for all the requests to the web service.
- SOAPConnector class extends WebServiceGatewaySupport which injects one interface with the internal implementation of WebServiceTemplate which is available by
getWebServiceTemplate()
method. - We will use this WebServiceTemplate to invoke the SOAP service.
- This class also expects one injected spring bean called Marshaller and Unmarshaller which will be provided by a configuration class.
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
public class SOAPConnector extends WebServiceGatewaySupport {
public Object callWebService(String url, Object request){
return getWebServiceTemplate().marshalSendAndReceive(url, request);
}
}
5. Configuration
Now we need to create one configuration class annotated with @Configuration which will have the required bean definitions required for the SOAPConnector to make this work properly.
- WebServiceGatewaySupport requires Marshaller and Unmarshaller, which are instances of Jaxb2Marshaller class.
- It uses ‘com.example.howtodoinjava.schemas.school‘ as base package of the JAXB classes. It will use this package to create the JAXB context.
- We will use this Jaxb2Marshaller bean as Marshaller/Unmarshaller of SOAPConnector bean.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@Configuration
public class Config {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
// this is the package name specified in the <generatePackage> specified in
// pom.xml
marshaller.setContextPath("com.example.howtodoinjava.schemas.school");
return marshaller;
}
@Bean
public SOAPConnector soapConnector(Jaxb2Marshaller marshaller) {
SOAPConnector client = new SOAPConnector();
client.setDefaultUri("http://localhost:8080/service/student-details");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
6. Demo
For simplicity, We will create one Spring boot command-line runner application, using which will load the spring context and invoke a handler method, and will also pass the command line parameters to it. In real-time, we need to replace this command line runner with some other code that will be more aligned with the business.
We need to add this command line runner bean in the SpringBootApplication class as bellow.
import com.howtodoinjava.soap.client.SOAPConnector;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.example.howtodoinjava.schemas.school.StudentDetailsRequest;
import com.example.howtodoinjava.schemas.school.StudentDetailsResponse;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
CommandLineRunner lookup(SOAPConnector soapConnector) {
return args -> {
String name = "Lokesh"; //Default Name
if (args.length > 0) {
name = args[0];
}
StudentDetailsRequest request = new StudentDetailsRequest();
request.setName(name);
StudentDetailsResponse response = (StudentDetailsResponse) soapConnector.callWebService("http://localhost:8080/service/student-details", request);
System.out.println("Got Response As below ========= : ");
System.out.println("Name : " + response.getStudent().getName());
System.out.println("Standard : " + response.getStudent().getStandard());
System.out.println("Address : " + response.getStudent().getAddress());
};
}
}
Here we are taking the search parameter from the command line and creating the StudentDetailsRequest object and using SOAPConnector we are invoking the SOAP web service.
Optional Configurations
Open application.properties and add the below configuration of the SOAP web service application is already running on port 8080.
server.port = 9090
logging.level.org.springframework.ws=TRACE
Here we are overriding the default port to 9090
by server.port = 9090 as you have already noticed that our sample SOAP service runs in default port 8080
as two java process can’t run in same port.
Also, we are enabling TRACE
logging for the org.springframework.ws
package by logging.level.org.springframework.ws=TRACE
. This will print the SOAP payloads in the console.
That’s all we need to do for consuming a SOAP service using Spring boot, Now it is time for testing.
Run the Application
Now build the application using the maven command mvn clean install
. We can invoke the command line runner by command java -jar target\spring-boot-soap-client-0.0.1-SNAPSHOT.jar Lokesh
from the command prompt.
Please note that we are passing one command line parameter “Lokesh” here which will be used in the lookup method of the CommandLineRunner bean. If no name is passed we have passed one default name in that method.
Once the command line runner is invoked, we should see the SOAP service output and the response is properly unmarshalled to the JAXB object StudentDetailsResponse
. Also, we can see the full SOAP request/response in the TRACE log as below.
2024-05-29T15:24:50.527+05:30 DEBUG 11444 --- [ main] o.s.ws.client.core.WebServiceTemplate : Opening [org.springframework.ws.transport.http.HttpUrlConnection@10b687f2] to [http://localhost:8080/service/student-details]
2024-05-29T15:24:50.647+05:30 TRACE 11444 --- [ main] o.s.ws.client.MessageTracing.sent : Sent request [<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ns2:StudentDetailsRequest xmlns:ns2="http://www.howtodoinjava.com/xml/school"><ns2:name>Sajal</ns2:name></ns2:StudentDetailsRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>]
2024-05-29T15:24:51.122+05:30 TRACE 11444 --- [ main] o.s.ws.client.MessageTracing.received : Received response [<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ns2:StudentDetailsResponse xmlns:ns2="http://www.howtodoinjava.com/xml/school"><ns2:Student><ns2:name>Sajal</ns2:name><ns2:standard>5</ns2:standard><ns2:address>Pune</ns2:address></ns2:Student></ns2:StudentDetailsResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>] for request [<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ns2:StudentDetailsRequest xmlns:ns2="http://www.howtodoinjava.com/xml/school"><ns2:name>Sajal</ns2:name></ns2:StudentDetailsRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>]
Got Response As below ========= :
Name : Lokesh
Standard : 6
Address : Pune
7. Summary
In this SOAP tutorial, we learned how we can consume SOAP service from Spring boot soap client easily. You can use this approach whenever you have any requirement to consume any such SOAP service. Hope this will be useful for you.
Please add your feedback in the comments section.
Happy Learning !!
Comments