[BAEL-5346] Code for @WebServiceServerTest article (#12229)

This commit is contained in:
Haroon Khan 2022-05-28 04:27:51 +01:00 committed by GitHub
parent 62ac961191
commit f8edd495ba
13 changed files with 518 additions and 0 deletions

View File

@ -19,13 +19,52 @@
<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>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-test</artifactId>
<version>3.1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.15.1</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/webservice</schemaDirectory>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<generatePackage>com.baeldung.webservice.generated</generatePackage>
<episode>false</episode>
<noFileHeader>true</noFileHeader>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<start-class>com.baeldung.boot.Application</start-class>
</properties>

View File

@ -0,0 +1,15 @@
package com.baeldung.webservice;
import com.baeldung.webservice.generated.Product;
import org.springframework.stereotype.Component;
@Component
public class InMemoryProductRepository implements ProductRepository {
public Product findProduct(String id) {
Product product = new Product();
product.setId(id);
product.setName("Product " + id);
return product;
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.webservice;
import com.baeldung.webservice.generated.GetProductRequest;
import com.baeldung.webservice.generated.GetProductResponse;
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;
@Endpoint
public class ProductEndpoint {
private static final String NAMESPACE_URI = "http://baeldung.com/spring-boot-web-service";
@Autowired
private ProductRepository productRepository;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getProductRequest")
@ResponsePayload
public GetProductResponse getProduct(@RequestPayload GetProductRequest request) {
GetProductResponse response = new GetProductResponse();
response.setProduct(productRepository.findProduct(request.getId()));
return response;
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.webservice;
import com.baeldung.webservice.generated.Product;
public interface ProductRepository {
Product findProduct(String id);
}

View File

@ -0,0 +1,13 @@
package com.baeldung.webservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebServiceApplication {
public static void main(String[] args) {
SpringApplication.run(WebServiceApplication.class, args);
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.webservice.config;
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.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
@EnableWs
@Configuration
public class WebServiceConfig {
@Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean<>(servlet, "/ws/*");
}
@Bean(name = "products")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema productsSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("ProductsPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://baeldung.com/spring-boot-web-service");
wsdl11Definition.setSchema(productsSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema productsSchema() {
return new SimpleXsdSchema(new ClassPathResource("webservice/products.xsd"));
}
}

View File

@ -0,0 +1,64 @@
package com.baeldung.webservice.generated;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType&gt;
* &lt;complexContent&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
* &lt;sequence&gt;
* &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/&gt;
* &lt;/sequence&gt;
* &lt;/restriction&gt;
* &lt;/complexContent&gt;
* &lt;/complexType&gt;
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id"
})
@XmlRootElement(name = "getProductRequest")
public class GetProductRequest {
@XmlElement(required = true)
protected String id;
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setId(String value) {
this.id = value;
}
}

View File

@ -0,0 +1,64 @@
package com.baeldung.webservice.generated;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType&gt;
* &lt;complexContent&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
* &lt;sequence&gt;
* &lt;element name="product" type="{http://baeldung.com/spring-boot-web-service}product"/&gt;
* &lt;/sequence&gt;
* &lt;/restriction&gt;
* &lt;/complexContent&gt;
* &lt;/complexType&gt;
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"product"
})
@XmlRootElement(name = "getProductResponse")
public class GetProductResponse {
@XmlElement(required = true)
protected Product product;
/**
* Gets the value of the product property.
*
* @return
* possible object is
* {@link Product }
*
*/
public Product getProduct() {
return product;
}
/**
* Sets the value of the product property.
*
* @param value
* allowed object is
* {@link Product }
*
*/
public void setProduct(Product value) {
this.product = value;
}
}

View File

@ -0,0 +1,56 @@
package com.baeldung.webservice.generated;
import javax.xml.bind.annotation.XmlRegistry;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the com.baeldung.webservice.generated package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
@XmlRegistry
public class ObjectFactory {
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.webservice.generated
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link GetProductRequest }
*
*/
public GetProductRequest createGetProductRequest() {
return new GetProductRequest();
}
/**
* Create an instance of {@link GetProductResponse }
*
*/
public GetProductResponse createGetProductResponse() {
return new GetProductResponse();
}
/**
* Create an instance of {@link Product }
*
*/
public Product createProduct() {
return new Product();
}
}

View File

@ -0,0 +1,90 @@
package com.baeldung.webservice.generated;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for product complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="product"&gt;
* &lt;complexContent&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
* &lt;sequence&gt;
* &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/&gt;
* &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/&gt;
* &lt;/sequence&gt;
* &lt;/restriction&gt;
* &lt;/complexContent&gt;
* &lt;/complexType&gt;
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "product", propOrder = {
"id",
"name"
})
public class Product {
@XmlElement(required = true)
protected String id;
@XmlElement(required = true)
protected String name;
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setId(String value) {
this.id = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
}

View File

@ -0,0 +1,2 @@
@javax.xml.bind.annotation.XmlSchema(namespace = "http://baeldung.com/spring-boot-web-service", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.baeldung.webservice.generated;

View File

@ -0,0 +1,26 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:bd="http://baeldung.com/spring-boot-web-service"
targetNamespace="http://baeldung.com/spring-boot-web-service" elementFormDefault="qualified">
<xs:element name="getProductRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getProductResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="product" type="bd:product"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="product">
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

View File

@ -0,0 +1,69 @@
package com.baeldung.webservice;
import com.baeldung.webservice.generated.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.webservices.server.WebServiceServerTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.test.server.MockWebServiceClient;
import org.springframework.xml.transform.StringSource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.mockito.Mockito.when;
import static org.springframework.ws.test.server.RequestCreators.withPayload;
import static org.springframework.ws.test.server.ResponseMatchers.noFault;
import static org.springframework.ws.test.server.ResponseMatchers.payload;
import static org.springframework.ws.test.server.ResponseMatchers.validPayload;
import static org.springframework.ws.test.server.ResponseMatchers.xpath;
@WebServiceServerTest
class ProductEndpointIntegrationTest {
private static final Map<String, String> NAMESPACE_MAPPING = createMapping();
@Autowired
private MockWebServiceClient client;
@MockBean
private ProductRepository productRepository;
@Test
void givenXmlRequest_whenServiceInvoked_thenValidResponse() throws IOException {
Product product = new Product();
product.setId("1");
product.setName("Product 1");
when(productRepository.findProduct("1")).thenReturn(product);
StringSource request = new StringSource(
"<bd:getProductRequest xmlns:bd='http://baeldung.com/spring-boot-web-service'>" +
"<bd:id>1</bd:id>" +
"</bd:getProductRequest>"
);
StringSource response = new StringSource(
"<bd:getProductResponse xmlns:bd='http://baeldung.com/spring-boot-web-service'>" +
"<bd:product>" +
"<bd:id>1</bd:id>" +
"<bd:name>Product 1</bd:name>" +
"</bd:product>" +
"</bd:getProductResponse>"
);
client.sendRequest(withPayload(request))
.andExpect(noFault())
.andExpect(validPayload(new ClassPathResource("webservice/products.xsd")))
.andExpect(xpath("/bd:getProductResponse/bd:product[1]/bd:name", NAMESPACE_MAPPING)
.evaluatesTo("Product 1"))
.andExpect(payload(response));
}
private static Map<String, String> createMapping() {
Map<String, String> mapping = new HashMap<>();
mapping.put("bd", "http://baeldung.com/spring-boot-web-service");
return mapping;
}
}