diff --git a/spring-boot-modules/spring-boot-testing-2/pom.xml b/spring-boot-modules/spring-boot-testing-2/pom.xml index dfe41d684d..556142b480 100644 --- a/spring-boot-modules/spring-boot-testing-2/pom.xml +++ b/spring-boot-modules/spring-boot-testing-2/pom.xml @@ -19,13 +19,52 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-web-services + + + wsdl4j + wsdl4j + org.springframework.boot spring-boot-starter-test test + + org.springframework.ws + spring-ws-test + 3.1.3 + test + + + + + org.jvnet.jaxb2.maven2 + maven-jaxb2-plugin + 0.15.1 + + + xjc + + generate + + + ${project.basedir}/src/main/resources/webservice + ${project.basedir}/src/main/java + com.baeldung.webservice.generated + false + true + + + + + + + com.baeldung.boot.Application diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/InMemoryProductRepository.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/InMemoryProductRepository.java new file mode 100644 index 0000000000..be11426aca --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/InMemoryProductRepository.java @@ -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; + } +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java new file mode 100644 index 0000000000..c3ba5c04a8 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductEndpoint.java @@ -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; + } +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductRepository.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductRepository.java new file mode 100644 index 0000000000..35eb6fcb97 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/ProductRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.webservice; + +import com.baeldung.webservice.generated.Product; + +public interface ProductRepository { + + Product findProduct(String id); + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/WebServiceApplication.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/WebServiceApplication.java new file mode 100644 index 0000000000..305738dcf2 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/WebServiceApplication.java @@ -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); + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/config/WebServiceConfig.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/config/WebServiceConfig.java new file mode 100644 index 0000000000..d444db09fb --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/config/WebServiceConfig.java @@ -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(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")); + } + + + + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java new file mode 100644 index 0000000000..d04302456b --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductRequest.java @@ -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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java new file mode 100644 index 0000000000..f8fcaa094f --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/GetProductResponse.java @@ -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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="product" type="{http://baeldung.com/spring-boot-web-service}product"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java new file mode 100644 index 0000000000..015ecc3f0a --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/ObjectFactory.java @@ -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. + *

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(); + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java new file mode 100644 index 0000000000..5957aa44b4 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/Product.java @@ -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; + + +/** + *

Java class for product complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="product">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java new file mode 100644 index 0000000000..298ae9374b --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/webservice/generated/package-info.java @@ -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; diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/resources/webservice/products.xsd b/spring-boot-modules/spring-boot-testing-2/src/main/resources/webservice/products.xsd new file mode 100644 index 0000000000..3819b465be --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/resources/webservice/products.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java new file mode 100644 index 0000000000..ea9924193b --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/webservice/ProductEndpointIntegrationTest.java @@ -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 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( + "" + + "1" + + "" + ); + StringSource response = new StringSource( + "" + + "" + + "1" + + "Product 1" + + "" + + "" + ); + + 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 createMapping() { + Map mapping = new HashMap<>(); + mapping.put("bd", "http://baeldung.com/spring-boot-web-service"); + return mapping; + } +}