Spring Boot SOAP Service with Hibernate Example
1. Introduction
Java Persistence API (JPA) is Java’s standard API specification for object-relational mapping. Hibernate is a JPA provider and provides a framework for mapping an object-oriented domain model to a relational database. Spring Boot defines a list of starter projects, in which each project includes a set of default component dependencies and an automatic configuration of components. The Spring Web Service starter project enables developers to write the contract-first SOAP service easily.
In this example, I will create a SOAP service with Hibernate in a Spring Boot application.
2. Technologies Used
The example code in this article was built and run using:
- Java 1.8.101
- Maven 3.3.9
- Eclipse Oxygen
- Spring Boot 1.5.16
- Hibernate 5.0.12.Final
- H2 1.4.197
3. Maven Project
Spring Boot Starters provides more than 30 starters to ease the dependency management for your projects. The easiest way to generate a Spring Boot Web Service with Hibernate via Spring Initializer:
- Go to
https://start.spring.io/
. - Select
Maven Project
withJava
and Spring Boot version1.5.16
. AddJPA
,Web Services
, andH2
in the “search for dependencies” section. - Enter the group name:
jcg.zheng.demo
and artifact:spring-boot-soap-hibernate
. - Click the
Generate Project
button.
A maven project will be generated and downloaded to your workstation. Import it into your Eclipse workspace.
3.1 Dependencies
The generated pom.xml
includes H2
, spring-boot-starter-data-jpa
, spring-boot-starter-web-services
, and spring-boot-starter-test
. I will include wsdl4j
and maven-jaxb2-plugin
.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jcg.zheng.demo</groupId> <artifactId>spring-boot-soap-hibernate</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-soap-hibernate</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.15.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <version>0.13.1</version> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <schemaDirectory>src/main/resources/wsdl</schemaDirectory> <schemaIncludes> <include>*.wsdl</include> </schemaIncludes> </configuration> <dependencies> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-osgi</artifactId> <version>2.2.11</version> </dependency> </dependencies> </plugin> </plugins> </build> </project>
3.2 Spring Boot Application
In this step, I will modify the generated Spring Boot application to include a step to save test data.
SpringBootSoapHibernateApplication.java
package jcg.zheng.demo.springbootsoaphibernate; import java.util.Random; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.scheduling.annotation.EnableAsync; import jcg.zheng.demo.springbootsoaphibernate.entity.Employee; import jcg.zheng.demo.springbootsoaphibernate.repository.EmployeeRepository; import payroll.bestpay.employee.EmployeeType; @SpringBootApplication @EnableAsync public class SpringBootSoapHibernateApplication { public static void main(String[] args) { ConfigurableApplicationContext ctx = SpringApplication.run(SpringBootSoapHibernateApplication.class, args); EmployeeRepository empRepo = ctx.getBean(EmployeeRepository.class); empRepo.save(buildDummyEmployee("John", "Zhang")); empRepo.save(buildDummyEmployee("Dan", "Zhao")); empRepo.save(buildDummyEmployee("Tom", "Zheng")); empRepo.save(buildDummyEmployee("Mary", "Zheng")); } private static Employee buildDummyEmployee(String firstName, String lastName) { Employee emp = new Employee(); emp.setType(EmployeeType.HOURLY); Random rand = new Random(); emp.setFirstName(firstName); emp.setLastName(lastName); emp.setDepartment("dummy dept"); emp.setManagerId("1"); emp.setHourlyRate(rand.nextInt(100)); return emp; } }
3.3 Application Properties
In this step, I will include two properties to set the Hibernate SQL logger level to DEBUG
. Click here to see the default properties.
applicaiton.properties
logging.level.root=INFO logging.level.org.hibernate.SQL=DEBUG spring.jap.generate-ddl=true
4. Employee WSDL
The Web Services Description Language (WSDL) is an XML-based interface definition language that is used for describing the functionality offered by a web service. In this step, employee.wsdl
is an XML document which describes the EmployeeLookup
web service and specifies how to access and use its methods.
employee.wsdl
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://bestpay.payroll/employee" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://bestpay.payroll/employee"> <wsdl:documentation> Service: EmployeeService Version: 1.0 Owner: Mary Zheng </wsdl:documentation> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://bestpay.payroll/employee" xmlns:tns="http://bestpay.payroll/employee" elementFormDefault="qualified"> <xs:simpleType name="EmployeeId"> <xs:restriction base="xs:string"> <xs:length value="7" /> <xs:pattern value="E[0-9]{7}" /> </xs:restriction> </xs:simpleType> <xs:simpleType name="EmployeeType"> <xs:restriction base="xs:string"> <xs:enumeration value="Hourly" /> <xs:enumeration value="Salary" /> </xs:restriction> </xs:simpleType> <xs:complexType name="EmployeeInfo"> <xs:sequence> <xs:element name="eid" type="tns:EmployeeId" minOccurs="0" nillable="false" /> <xs:element name="firstName" type="xs:string" minOccurs="0" nillable="false" /> <xs:element name="lastName" type="xs:string" minOccurs="0" nillable="false" /> <xs:element name="hourlyRate" type="xs:decimal" minOccurs="0" nillable="false" /> <xs:element name="type" type="tns:EmployeeType" minOccurs="0" nillable="false" /> </xs:sequence> </xs:complexType> <xs:complexType name="EmployeeInfoWrapper"> <xs:sequence> <xs:element name="employeeInfo" type="tns:EmployeeInfo" minOccurs="0" maxOccurs="unbounded" nillable="false" /> </xs:sequence> </xs:complexType> <xs:complexType name="EmployeeIdWrapper"> <xs:sequence> <xs:element name="eid" type="tns:EmployeeId" minOccurs="0" maxOccurs="unbounded" nillable="false" /> </xs:sequence> </xs:complexType> <xs:element name="employeeLookupRequest" type="tns:EmployeeIdWrapper" /> <xs:element name="employeeServiceResponse" type="tns:EmployeeInfoWrapper" /> </xs:schema> </wsdl:types> <wsdl:message name="employeeLookupRequest"> <wsdl:part element="tns:employeeLookupRequest" name="employeeLookupRequest" /> </wsdl:message> <wsdl:message name="employeeLookupResponse"> <wsdl:part element="tns:employeeServiceResponse" name="employeeServiceResponse" /> </wsdl:message> <wsdl:portType name="employeeLookupService"> <wsdl:documentation>Employee Lookup interface </wsdl:documentation> <wsdl:operation name="employeeLookup"> <wsdl:input message="tns:employeeLookupRequest" /> <wsdl:output message="tns:employeeLookupResponse" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="employeeLookupBinding" type="tns:employeeLookupService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="employeeLookup"> <soap:operation soapAction="http://bestpay.payroll/employee/employeeLookup" /> <wsdl:input> <soap:body parts="employeeLookupRequest" use="literal" /> </wsdl:input> <wsdl:output> <soap:body parts="employeeServiceResponse" use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="employeeLookupService"> <wsdl:port binding="tns:employeeLookupBinding" name="employeeLookupPort"> <soap:address location="http://localhost:8080/soap/ws/employee" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
4.1 WSDL Validation
Predic8 provides a free online tool to validate the WSDL file. I used it to validate employee.wsdl
. The validation results included reports for TargetNamespace
, Message
, PortType
, Operation
, Binding
, and Service
.
4.2 Generated Java Files
The Maven plug-in, maven-jaxb2-plugin
, scans src/main/resource/wsdl/employee.wsdl
. Execute mvn clean install
to generate the Java stubs under C:\MZheng_Java_workspace\Java Code Geek Examples\spring-boot-soap-hibernate\target\generated-sources\xjc
.
No modification needed to the generated files.
Generated Java Stubs
C:\MZheng_Java_workspace\Java Code Geek Examples\spring-boot-soap-hibernate\target\generated-sources\xjc\payroll\bestpay\employee>dir Volume in drive C is OSDisk Volume Serial Number is 3A10-C6D4 Directory of C:\MZheng_Java_workspace\Java Code Geek Examples\spring-boot-soap-hibernate\target\generated-sources\xjc\payroll\bestpay\employee 09/18/2018 08:13 PM <DIR> . 09/18/2018 08:13 PM <DIR> .. 09/18/2018 08:13 PM 2,174 EmployeeIdWrapper.java 09/18/2018 08:13 PM 4,480 EmployeeInfo.java 09/18/2018 08:13 PM 2,298 EmployeeInfoWrapper.java 09/18/2018 08:13 PM 1,549 EmployeeType.java 09/18/2018 08:13 PM 3,148 ObjectFactory.java 09/18/2018 08:13 PM 530 package-info.java 6 File(s) 14,179 bytes 2 Dir(s) 16,617,570,304 bytes free
5. Employee Service
In this step, I will create a Spring service to look up the employee based on its identifier and transform it to EmployeeInfo
.
5.1 Employee Entity
@javax.persistence.Entity
annotation defines that a class can be mapped to a table. An entity class must have a field annotated with @Id
.
In this step, I will create an Employee
entity to map to a T_Employee
table.
Employee.java
package jcg.zheng.demo.springbootsoaphibernate.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import payroll.bestpay.employee.EmployeeType; @Entity @Table(name = "T_Employee") public class Employee { @Id @GeneratedValue @Column(name = "Id") private Long id; @Column(name = "First_Name") private String firstName; @Column(name = "Last_Name") private String lastName; @Column(name = "Hourly_Rate") private float hourlyRate; @Column(name = "Employee_Type") @Enumerated(EnumType.STRING) private EmployeeType type; private String department; private String managerId; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public float getHourlyRate() { return hourlyRate; } public void setHourlyRate(float hourlyRate) { this.hourlyRate = hourlyRate; } public EmployeeType getType() { return type; } public void setType(EmployeeType type) { this.type = type; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public String getManagerId() { return managerId; } public void setManagerId(String managerId) { this.managerId = managerId; } @Override public String toString() { return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", hourlyRate=" + hourlyRate + ", type=" + type + ", department=" + department + ", managerId=" + managerId + "]"; } }
5.2 EmployeeTransformer
In this step, I will create an EmployeeTransformer
which transforms the Employee
entity to the generated EmployeeInfo
class.
EmployeeTransformer.java
package jcg.zheng.demo.springbootsoaphibernate.component; import java.math.BigDecimal; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Component; import jcg.zheng.demo.springbootsoaphibernate.aop.LoggableService; import jcg.zheng.demo.springbootsoaphibernate.entity.Employee; import payroll.bestpay.employee.EmployeeInfo; @Component public class EmployeeTransformer { @LoggableService public EmployeeInfo convert(Employee emp) { EmployeeInfo empInfor = new EmployeeInfo(); BeanUtils.copyProperties(emp, empInfor); empInfor.setHourlyRate(new BigDecimal(emp.getHourlyRate())); empInfor.setEid(String.valueOf(emp.getId())); return empInfor; } }
5.3 EmployeeRepository
Spring data scans the base package and all its sub-packages for any interfaces extending @Repository
or one of its sub-interfaces. For each interface found, Spring creates the appropriate bean to handle invocation of the query methods. In this step, I will create an EmployeeRespository
interface.
EmployeeRepository.java
package jcg.zheng.demo.springbootsoaphibernate.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import jcg.zheng.demo.springbootsoaphibernate.entity.Employee; @Repository @Transactional public interface EmployeeRepository extends JpaRepository<Employee, Long> { }
5.4 EmployeeService
In this step, I will create an EmployeeService
which injects EmployeeRepository
and EmployeeTransformer
to look up an employee and convert it to EmployeeInfo
.
EmployeeService.java
package jcg.zheng.demo.springbootsoaphibernate.component; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import jcg.zheng.demo.springbootsoaphibernate.aop.LoggableService; import jcg.zheng.demo.springbootsoaphibernate.entity.Employee; import jcg.zheng.demo.springbootsoaphibernate.repository.EmployeeRepository; import payroll.bestpay.employee.EmployeeInfo; @Service public class EmployeeService { @Autowired private EmployeeRepository empRepo; @Autowired private EmployeeTransformer convertor; @LoggableService public EmployeeInfo employeeLookup(String employeeId) { Employee employee = empRepo.findOne(Long.parseLong(employeeId)); if (employee != null) { return convertor.convert(employee); } return null; } }
6. Employee SOAP Service
I will create an EmployeeServiceEndPoint
which defines the employeeLookup
web method and exposes it as a SOAP service.
6.1 EmployeeServiceEndPoint
In this step, I will create an EmployeeServiceEndPoint
annotate it with @Endpoint
. I will annotate the web method with @PayloadRoot
and @ResponsePayload
. It uses the generated Java stubs in step 4.2 and the EmployeeService
created in step 5.4.
EmployeeServiceEndPoint.java
package jcg.zheng.demo.springbootsoaphibernate.soap; import javax.xml.bind.JAXBElement; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.RequestPayload; import org.springframework.ws.server.endpoint.annotation.ResponsePayload; import jcg.zheng.demo.springbootsoaphibernate.aop.LoggableService; import jcg.zheng.demo.springbootsoaphibernate.component.EmployeeService; import payroll.bestpay.employee.EmployeeIdWrapper; import payroll.bestpay.employee.EmployeeInfo; import payroll.bestpay.employee.EmployeeInfoWrapper; import payroll.bestpay.employee.ObjectFactory; @Endpoint public class EmployeeServiceEndPoint { private static final String NAMESPACE_URI = "http://bestpay.payroll/employee"; @Autowired private EmployeeService empService; @PayloadRoot(namespace = NAMESPACE_URI, localPart = "employeeLookupRequest") @ResponsePayload @LoggableService public JAXBElement<EmployeeInfoWrapper> employeeLookup(@RequestPayload JAXBElement<EmployeeIdWrapper> request) { ObjectFactory factory = new ObjectFactory(); EmployeeInfoWrapper response = factory.createEmployeeInfoWrapper(); for (String empId : request.getValue().getEid()) { EmployeeInfo found = empService.employeeLookup(empId); if( found != null) { response.getEmployeeInfo().add(found); } } return factory.createEmployeeServiceResponse(response); } }
6.2 SoapServiceConfiguration
In this step, I will create a SoapServiceConfiguration
with @EnableWs
and configure a SOAP service with employee.wsdl
.
SoapServiceConfiguration.java
package jcg.zheng.demo.springbootsoaphibernate.soap; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.ws.config.annotation.EnableWs; import org.springframework.ws.transport.http.MessageDispatcherServlet; import org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition; import org.springframework.ws.wsdl.wsdl11.Wsdl11Definition; @EnableWs @Configuration public class SoapServiceConfiguration { @Bean public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { MessageDispatcherServlet servlet = new MessageDispatcherServlet(); servlet.setApplicationContext(applicationContext); return new ServletRegistrationBean(servlet, "/soap/ws/*"); } @Bean(name = "employee") public Wsdl11Definition employeeWsdl11Definition() { SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition(); wsdl11Definition.setWsdl(new ClassPathResource("/wsdl/employee.wsdl")); return wsdl11Definition; } }
7. Demo
SoapUI is a great tool for testing web services. Click here to download it.
Start the Spring Boot application created in step 3.2. Verify that the service is started with four employees in the server log.
Server Log
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.15.RELEASE) 2018-09-21 16:17:25.114 INFO 7176 --- [ main] z.d.s.SpringBootSoapHibernateApplication : Starting SpringBootSoapHibernateApplication on SL2LS431841 with PID 7176 (started by shu.shan in C:\MZheng_Java_workspace\Java Code Geek Examples\spring-boot-soap-hibernate) 2018-09-21 16:17:25.119 INFO 7176 --- [ main] z.d.s.SpringBootSoapHibernateApplication : No active profile set, falling back to default profiles: default 2018-09-21 16:17:25.196 INFO 7176 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6166e06f: startup date [Fri Sep 21 16:17:25 CDT 2018]; root of context hierarchy 2018-09-21 16:17:26.670 INFO 7176 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [org.springframework.ws.config.annotation.DelegatingWsConfiguration$EnhancerBySpringCGLIB$29ae6cb0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-09-21 16:17:26.720 INFO 7176 --- [ main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0] 2018-09-21 16:17:26.925 INFO 7176 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$EnhancerBySpringCGLIB$8516a7b1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-09-21 16:17:28.133 INFO 7176 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2018-09-21 16:17:28.175 INFO 7176 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-09-21 16:17:28.175 INFO 7176 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.32 2018-09-21 16:17:28.359 INFO 7176 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-09-21 16:17:28.359 INFO 7176 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3167 ms 2018-09-21 16:17:28.614 INFO 7176 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'messageDispatcherServlet' to [/soap/ws/*] 2018-09-21 16:17:28.615 INFO 7176 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2018-09-21 16:17:28.619 INFO 7176 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2018-09-21 16:17:28.620 INFO 7176 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2018-09-21 16:17:28.620 INFO 7176 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] 2018-09-21 16:17:28.620 INFO 7176 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] 2018-09-21 16:17:29.357 INFO 7176 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' 2018-09-21 16:17:29.380 INFO 7176 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: default ...] 2018-09-21 16:17:29.492 INFO 7176 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} 2018-09-21 16:17:29.495 INFO 7176 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found 2018-09-21 16:17:29.497 INFO 7176 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist 2018-09-21 16:17:29.560 INFO 7176 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 2018-09-21 16:17:29.759 INFO 7176 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 2018-09-21 16:17:30.343 INFO 7176 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export 2018-09-21 16:17:30.350 DEBUG 7176 --- [ main] org.hibernate.SQL : drop table t_employee if exists 2018-09-21 16:17:30.351 DEBUG 7176 --- [ main] org.hibernate.SQL : create table t_employee (id bigint generated by default as identity, department varchar(255), first_name varchar(255), hourly_rate float, last_name varchar(255), manager_id varchar(255), employee_type varchar(255), primary key (id)) 2018-09-21 16:17:30.361 INFO 7176 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete 2018-09-21 16:17:30.412 INFO 7176 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2018-09-21 16:17:31.259 INFO 7176 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6166e06f: startup date [Fri Sep 21 16:17:25 CDT 2018]; root of context hierarchy 2018-09-21 16:17:31.374 INFO 7176 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2018-09-21 16:17:31.376 INFO 7176 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2018-09-21 16:17:31.428 INFO 7176 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-09-21 16:17:31.428 INFO 7176 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-09-21 16:17:31.489 INFO 7176 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-09-21 16:17:31.825 INFO 7176 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2018-09-21 16:17:31.880 INFO 7176 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2018-09-21 16:17:31.886 INFO 7176 --- [ main] z.d.s.SpringBootSoapHibernateApplication : Started SpringBootSoapHibernateApplication in 7.174 seconds (JVM running for 7.636) 2018-09-21 16:17:31.929 DEBUG 7176 --- [ main] org.hibernate.SQL : insert into t_employee (id, department, first_name, hourly_rate, last_name, manager_id, employee_type) values (null, ?, ?, ?, ?, ?, ?) 2018-09-21 16:17:31.959 DEBUG 7176 --- [ main] org.hibernate.SQL : insert into t_employee (id, department, first_name, hourly_rate, last_name, manager_id, employee_type) values (null, ?, ?, ?, ?, ?, ?) 2018-09-21 16:17:31.961 DEBUG 7176 --- [ main] org.hibernate.SQL : insert into t_employee (id, department, first_name, hourly_rate, last_name, manager_id, employee_type) values (null, ?, ?, ?, ?, ?, ?) 2018-09-21 16:17:31.962 DEBUG 7176 --- [ main] org.hibernate.SQL : insert into t_employee (id, department, first_name, hourly_rate, last_name, manager_id, employee_type) values (null, ?, ?, ?, ?, ?, ?)
In this step, I will create a new SOAP project:
- Click
File
->New SOAP Project
- Enter the Initial WSDL:
http://localhost:8080/soap/ws/employee.wsdl
and ClickOK
- Expand the newly created project, then click
employeeLookup
, andRequest 1
- A SOAP message is populated, replace
?
with the test data - Submit the request
- Wait for a response
SoapUI Input
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emp="http://bestpay.payroll/employee"> <soapenv:Header/> <soapenv:Body> <emp:employeeLookupRequest> <!--Zero or more repetitions:--> <emp:eid>1</emp:eid> <emp:eid>2</emp:eid> <emp:eid>3</emp:eid> <emp:eid>4</emp:eid> </emp:employeeLookupRequest> </soapenv:Body> </soapenv:Envelope>
SoapUI Output
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> <ns2:employeeServiceResponse xmlns:ns2="http://bestpay.payroll/employee"> <ns2:employeeInfo> <ns2:eid>1</ns2:eid> <ns2:firstName>John</ns2:firstName> <ns2:lastName>Zhang</ns2:lastName> <ns2:hourlyRate>14</ns2:hourlyRate> <ns2:type>Hourly</ns2:type> </ns2:employeeInfo> <ns2:employeeInfo> <ns2:eid>2</ns2:eid> <ns2:firstName>Dan</ns2:firstName> <ns2:lastName>Zhao</ns2:lastName> <ns2:hourlyRate>32</ns2:hourlyRate> <ns2:type>Hourly</ns2:type> </ns2:employeeInfo> <ns2:employeeInfo> <ns2:eid>3</ns2:eid> <ns2:firstName>Tom</ns2:firstName> <ns2:lastName>Zheng</ns2:lastName> <ns2:hourlyRate>25</ns2:hourlyRate> <ns2:type>Hourly</ns2:type> </ns2:employeeInfo> <ns2:employeeInfo> <ns2:eid>4</ns2:eid> <ns2:firstName>Mary</ns2:firstName> <ns2:lastName>Zheng</ns2:lastName> <ns2:hourlyRate>87</ns2:hourlyRate> <ns2:type>Hourly</ns2:type> </ns2:employeeInfo> </ns2:employeeServiceResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Capture the server.log and compare the time executed for each request. You will see that the first query took 60ms and all subsequent queries take less than 10ms. Hibernate improves the performance.
Server.log
2018-09-21 16:18:55.489 INFO 7176 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'messageDispatcherServlet' 2018-09-21 16:18:55.490 INFO 7176 --- [nio-8080-exec-1] o.s.w.t.http.MessageDispatcherServlet : FrameworkServlet 'messageDispatcherServlet': initialization started 2018-09-21 16:18:55.496 INFO 7176 --- [nio-8080-exec-1] o.s.ws.soap.saaj.SaajSoapMessageFactory : Creating SAAJ 1.3 MessageFactory with SOAP 1.1 Protocol 2018-09-21 16:18:55.511 INFO 7176 --- [nio-8080-exec-1] o.s.w.t.http.MessageDispatcherServlet : FrameworkServlet 'messageDispatcherServlet': initialization completed in 21 ms 2018-09-21 16:18:55.750 DEBUG 7176 --- [nio-8080-exec-1] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:18:55.784 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=1, firstName=John, lastName=Zhang, hourlyRate=14.0, type=HOURLY, department=dummy dept, managerId=1], executed in 15ms 2018-09-21 16:18:55.784 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=1, executed in 60ms 2018-09-21 16:18:55.786 DEBUG 7176 --- [nio-8080-exec-1] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:18:55.787 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=2, firstName=Dan, lastName=Zhao, hourlyRate=32.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:18:55.787 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=2, executed in 2ms 2018-09-21 16:18:55.789 DEBUG 7176 --- [nio-8080-exec-1] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:18:55.790 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=3, firstName=Tom, lastName=Zheng, hourlyRate=25.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:18:55.790 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=3, executed in 3ms 2018-09-21 16:18:55.791 DEBUG 7176 --- [nio-8080-exec-1] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:18:55.792 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=4, firstName=Mary, lastName=Zheng, hourlyRate=87.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:18:55.793 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=4, executed in 3ms 2018-09-21 16:18:55.794 INFO 7176 --- [nio-8080-exec-1] j.z.d.s.soap.EmployeeServiceEndPoint : method=employeeLookup, request=javax.xml.bind.JAXBElement@766b499d, executed in 77ms 2018-09-21 16:22:33.348 DEBUG 7176 --- [nio-8080-exec-3] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:33.350 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=1, firstName=John, lastName=Zhang, hourlyRate=14.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:33.353 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=1, executed in 6ms 2018-09-21 16:22:33.353 DEBUG 7176 --- [nio-8080-exec-3] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:33.354 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=2, firstName=Dan, lastName=Zhao, hourlyRate=32.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:33.354 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=2, executed in 1ms 2018-09-21 16:22:33.355 DEBUG 7176 --- [nio-8080-exec-3] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:33.356 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=3, firstName=Tom, lastName=Zheng, hourlyRate=25.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:33.356 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=3, executed in 1ms 2018-09-21 16:22:33.357 DEBUG 7176 --- [nio-8080-exec-3] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:33.359 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=4, firstName=Mary, lastName=Zheng, hourlyRate=87.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:33.359 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=4, executed in 3ms 2018-09-21 16:22:33.359 INFO 7176 --- [nio-8080-exec-3] j.z.d.s.soap.EmployeeServiceEndPoint : method=employeeLookup, request=javax.xml.bind.JAXBElement@6fd566cb, executed in 12ms 2018-09-21 16:22:40.330 DEBUG 7176 --- [nio-8080-exec-4] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:40.331 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=5, executed in 1ms 2018-09-21 16:22:40.331 DEBUG 7176 --- [nio-8080-exec-4] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:40.333 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=2, firstName=Dan, lastName=Zhao, hourlyRate=32.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:40.333 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=2, executed in 2ms 2018-09-21 16:22:40.335 DEBUG 7176 --- [nio-8080-exec-4] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:40.338 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=3, firstName=Tom, lastName=Zheng, hourlyRate=25.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:40.338 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=3, executed in 5ms 2018-09-21 16:22:40.339 DEBUG 7176 --- [nio-8080-exec-4] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:40.341 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=4, firstName=Mary, lastName=Zheng, hourlyRate=87.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:40.341 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=4, executed in 3ms 2018-09-21 16:22:40.341 INFO 7176 --- [nio-8080-exec-4] j.z.d.s.soap.EmployeeServiceEndPoint : method=employeeLookup, request=javax.xml.bind.JAXBElement@76468e65, executed in 11ms 2018-09-21 16:22:41.594 DEBUG 7176 --- [nio-8080-exec-5] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:41.594 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=5, executed in 3ms 2018-09-21 16:22:41.595 DEBUG 7176 --- [nio-8080-exec-5] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:41.596 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=2, firstName=Dan, lastName=Zhao, hourlyRate=32.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:41.596 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=2, executed in 2ms 2018-09-21 16:22:41.596 DEBUG 7176 --- [nio-8080-exec-5] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:41.598 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=3, firstName=Tom, lastName=Zheng, hourlyRate=25.0, type=HOURLY, department=dummy dept, managerId=1], executed in 0ms 2018-09-21 16:22:41.598 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=3, executed in 2ms 2018-09-21 16:22:41.602 DEBUG 7176 --- [nio-8080-exec-5] org.hibernate.SQL : select employee0_.id as id1_0_0_, employee0_.department as departme2_0_0_, employee0_.first_name as first_na3_0_0_, employee0_.hourly_rate as hourly_r4_0_0_, employee0_.last_name as last_nam5_0_0_, employee0_.manager_id as manager_6_0_0_, employee0_.employee_type as employee7_0_0_ from t_employee employee0_ where employee0_.id=? 2018-09-21 16:22:41.604 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeTransformer : method=convert, emp=Employee [id=4, firstName=Mary, lastName=Zheng, hourlyRate=87.0, type=HOURLY, department=dummy dept, managerId=1], executed in 1ms 2018-09-21 16:22:41.604 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.component.EmployeeService : method=employeeLookup, employeeId=4, executed in 6ms 2018-09-21 16:22:41.604 INFO 7176 --- [nio-8080-exec-5] j.z.d.s.soap.EmployeeServiceEndPoint : method=employeeLookup, request=javax.xml.bind.JAXBElement@6fb9dd63, executed in 13ms
8. Spring Boot SOAP Service with Hibernate- Summary
In this article, I demonstrated how to create a SOAP web service using Hibernate in a Spring Boot Maven project in four steps:
- Generate Java stubs from a WSDL file.
- Create an
Entity
class andRepository
Interface - Create a web service endpoint
- Configure a
SimpleWsdl11Definition
with WSDL
9. Download the Source Code
This tutorial consists of a Spring Boot Maven project which creates a SOAP service with Hibernate from a WSDL file.
You can download the full source code of this example here: Spring Boot SOAP Service with Hibernate Example
Nice post !
Very helpful in refresh SOAP WS knowledge.