This article is about consuming SOAP web services through a Spring Boot app. We will be creating a sample spring boot SOAP client to consume SOAP web services using the maven plugins. We will be demonstrating the client generation process using 2 different maven plugins - maven-jaxb2-plugin and cxf-codegen-plugin. Once, the stubs are generated, we will be using WebServiceTemplate to marshal our request and response.
As we know, there are 2 ways to go with SOAP - top-down web service and a bottom-up web service. Here, in this article, we won't be discussing about generating any .wsdl file instead we will be using an existing BLZService wsdl file. The same .wsdl file can be downloaded from here. We will import this WSDL file in our local workspace and generate stubs out of it using maven plugin and create spring boot SOAP client to consume these web services. In next aricle, we will be discussing the exception handling in SOAP web services.
Generating Spring Boot Starter Project
First, let us generate our sample spring boot app from start.spring.io. We have selected 2 dependencies for this web and web services as shown below. The web is required just to expose endpoint for testing purpose whereas the web services dependency provides all required artifacts related to SOAP web services.
Maven JAXB2 Plugin Config
As we mentioned earlier that we will be demonstrating usage of 2 different plugins to generate the stub, let us start with JAXB2 plugin first. Below is the maven plugin configuration that is required to generate stubs from local wsdl file. We have downloaded the wsdl file and placed inside wsdl directory at src/main/resources/wsdl.
<plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <version>0.14.0</version> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <generatePackage>com.devglan.springbootsoapclient.generated.blz</generatePackage> <generateDirectory>${project.basedir}/src/main/java</generateDirectory> <schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory> <schemaIncludes> <include>*.wsdl</include> </schemaIncludes> </configuration> </plugin>
generatePackage - Package location where stubs will be generated. In our case it is - com.devglan.springbootsoapclient.generated.blz
generateDirectory -Directory where stubs will be generated. In our case it is - src/main/java
schemaDirectory - WSDl location. In our case it is src/main/resources/wsdl
Now, if you run the maven command mvn clean install
with below project structure and above maven configuration, the stubs will be generated inside the package com.devglan.springbootsoapclient.generated.blz
Spring Boot Marshaller and Unmarshaller Config
Now let us define our bean configuration for Marshaller and Unmarshaller using Jaxb2Marshaller. Here, we have configured our base package where our stubs are generated and this Marshaller and Unmarshaller will be used by WebServiceGatewaySupport during marshalling and unmarshalling.
BeanConfig.javapackage com.devglan.springbootsoapclient.config; import com.devglan.springbootsoapclient.BlzServiceAdapter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.oxm.jaxb.Jaxb2Marshaller; @Configuration public class BeanConfig { @Bean public Jaxb2Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setContextPath("com.devglan.springbootsoapclient.generated.blz"); return marshaller; } @Bean public BlzServiceAdapter soapConnector(Jaxb2Marshaller marshaller) { BlzServiceAdapter client = new BlzServiceAdapter(); client.setDefaultUri("http://www.thomas-bayer.com/axis2/services/BLZService"); client.setMarshaller(marshaller); client.setUnmarshaller(marshaller); return client; } }
BlzServiceAdapter Implementation
This adaptr will actually invoke the Blz SOAP web service. getBank()
accepts two arguments URL and the payload and makes use of WebServiceTemplate to invoke the web service. You can visit my another article to add custom header in the SOAP request.
package com.devglan.springbootsoapclient; import com.devglan.springbootsoapclient.generated.blz.GetBankResponseType; import org.springframework.ws.client.core.support.WebServiceGatewaySupport; import javax.xml.bind.JAXBElement; public class BlzServiceAdapter extends WebServiceGatewaySupport { public GetBankResponseType getBank(String url, Object request){ JAXBElementres = (JAXBElement ) getWebServiceTemplate().marshalSendAndReceive(url, request); return res.getValue(); } }
Above implementation is a very simple client implementation. In real time, we need to take care of security and password authentication details in the header. In the next article, we will be discussing about adding custom header in the SOAP request with Spring.
Spring Boot Controller
This controller is only to expose a REST endpoint that accepts code as an input from user and invoke the adapter class getBank()
. This is only for testing purpose. You can also invoke this getBank()
method using command line.
@RestController @RequestMapping("/") public class BlzController { @Autowired private BlzServiceAdapter blzServiceAdapter; @GetMapping public DetailsType sum(@RequestParam String code){ ObjectFactory objectFactory = new ObjectFactory(); GetBankType type = new GetBankType(); type.setBlz(code); GetBankResponseType response = blzServiceAdapter.getBank("http://www.thomas-bayer.com/axis2/services/BLZService", objectFactory.createGetBank(type)); return response.getDetails(); } }
Running Spring Boot App
To boostrap our spring app, we have below SpringBootSoapClientApplication.java defined. We will run the below class as a java program.
@SpringBootApplication public class SpringBootSoapClientApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSoapClientApplication.class, args); } }
Now, we can hit the URL http://localhost:8080/?code=46062817. Internally, the BLZ SOAP web services will be called and below response can be seen in the browser.
Maven CXF Codegen Plugin Config
Following is the maven plugin conffiguration for CXF Codegen. You can include as many wsdl file you want using wsdlOption
.
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.2.4</version> </dependency> <plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase> <configuration> <sourceRoot>${basedir}/src/main/java/com/devglan/springbootsoapclient/generated/cxf/</sourceRoot> <wsdlOptions> <wsdlOption> <wsdl>${basedir}/src/main/resources/wsdl/blzservice.wsdl</wsdl> </wsdlOption> </wsdlOptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> </plugin>
Below is the complete pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.devglan</groupId> <artifactId>spring-boot-soap-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-soap-client</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.2.4</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>3.2.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <version>0.14.0</version> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <generatePackage>com.devglan.springbootsoapclient.generated.blz</generatePackage> <generateDirectory>${project.basedir}/src/main/java</generateDirectory> <schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory> <schemaIncludes> <include>*.wsdl</include> </schemaIncludes> </configuration> </plugin> <!--<plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase> <configuration> <sourceRoot>${basedir}/src/main/java/com/devglan/springbootsoapclient/generated/cxf/</sourceRoot> <wsdlOptions> <wsdlOption> <wsdl>${basedir}/src/main/resources/wsdl/blzservice.wsdl</wsdl> </wsdlOption> </wsdlOptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> </plugin>--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Conclusion
In this article, we discussed about consuming SOAP web services through a Spring Boot app. We created a sample spring boot SOAP client to consume SOAP web services using the maven plugins. We demonstrated the client generation process using 2 different maven plugins - maven-jaxb2-plugin and cxf-codegen-plugin