mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Add support for Spring WS auto WSDL/XSD exposure
This commit adds support for auto-configuration of Spring WS automatic WSDL and XSD exposure i.e. registration of `WsdlDefinition` and `XsdDefinition` beans. The bean registration is triggered by configuring `spring.webservices.wsdl-locations` property which will search the provided locations for WSDL/XSD files and register appropriate beans. See gh-9635
This commit is contained in:
parent
32102c693b
commit
bb72a4abe1
@ -16,23 +16,40 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.webservices;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.config.annotation.EnableWs;
|
||||
import org.springframework.ws.config.annotation.WsConfigurationSupport;
|
||||
import org.springframework.ws.transport.http.MessageDispatcherServlet;
|
||||
import org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition;
|
||||
import org.springframework.xml.xsd.SimpleXsdSchema;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Web Services.
|
||||
@ -72,10 +89,76 @@ public class WebServicesAutoConfiguration {
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "spring.webservices", name = "wsdl-locations")
|
||||
public static WsdlDefinitionBeanFactoryPostProcessor wsdlDefinitionBeanFactoryPostProcessor() {
|
||||
return new WsdlDefinitionBeanFactoryPostProcessor();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWs
|
||||
protected static class WsConfiguration {
|
||||
|
||||
}
|
||||
|
||||
private static class WsdlDefinitionBeanFactoryPostProcessor
|
||||
implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
|
||||
throws BeansException {
|
||||
Binder binder = Binder.get(this.applicationContext.getEnvironment());
|
||||
List<String> wsdlLocations = binder
|
||||
.bind("spring.webservices.wsdl-locations",
|
||||
Bindable.listOf(String.class))
|
||||
.orElse(Collections.emptyList());
|
||||
for (String wsdlLocation : wsdlLocations) {
|
||||
registerBeans(wsdlLocation, "*.wsdl", SimpleWsdl11Definition.class, registry);
|
||||
registerBeans(wsdlLocation, "*.xsd", SimpleXsdSchema.class, registry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
private void registerBeans(String location, String pattern, Class<?> type,
|
||||
BeanDefinitionRegistry registry) {
|
||||
Resource[] resources = new Resource[] {};
|
||||
try {
|
||||
resources = this.applicationContext
|
||||
.getResources(ensureTrailingSlash(location) + pattern);
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
for (Resource resource : resources) {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(type);
|
||||
ConstructorArgumentValues constructorArguments = new ConstructorArgumentValues();
|
||||
constructorArguments.addIndexedArgumentValue(0, resource);
|
||||
beanDefinition.setConstructorArgumentValues(constructorArguments);
|
||||
|
||||
registry.registerBeanDefinition(
|
||||
StringUtils.stripFilenameExtension(resource.getFilename()),
|
||||
beanDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
private static String ensureTrailingSlash(String path) {
|
||||
if (!path.endsWith("/")) {
|
||||
return path + "/";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1183,6 +1183,11 @@
|
||||
{
|
||||
"name": "spring.thymeleaf.suffix",
|
||||
"defaultValue": ".html"
|
||||
},
|
||||
{
|
||||
"name": "spring.webservices.wsdl-locations",
|
||||
"type": "java.util.List<java.lang.String>",
|
||||
"description": "Comma-separated list of locations of WSDLs and accompanying XSDs to be exposed as beans."
|
||||
}
|
||||
],"hints": [
|
||||
{
|
||||
|
@ -26,6 +26,8 @@ import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition;
|
||||
import org.springframework.xml.xsd.SimpleXsdSchema;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ -90,6 +92,18 @@ public class WebServicesAutoConfigurationTests {
|
||||
.containsEntry("key2", "value2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withWsdlBeans() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.webservices.wsdl-locations=classpath:/wsdl")
|
||||
.run(context -> {
|
||||
assertThat(context.getBeansOfType(SimpleWsdl11Definition.class))
|
||||
.hasSize(1).containsKey("service");
|
||||
assertThat(context.getBeansOfType(SimpleXsdSchema.class)).hasSize(1)
|
||||
.containsKey("types");
|
||||
});
|
||||
}
|
||||
|
||||
private Collection<String> getUrlMappings(ApplicationContext context) {
|
||||
return getServletRegistrationBean(context).getUrlMappings();
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:tns="http://www.springframework.org/spring-ws/wsdl"
|
||||
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
targetNamespace="http://www.springframework.org/spring-ws/wsdl">
|
||||
|
||||
<wsdl:types>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://www.springframework.org/spring-ws/wsdl">
|
||||
<xsd:element name="request" type="xsd:string"/>
|
||||
<xsd:element name="response" type="xsd:string"/>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
|
||||
<wsdl:message name="responseMessage">
|
||||
<wsdl:part name="body" element="tns:response"/>
|
||||
</wsdl:message>
|
||||
|
||||
<wsdl:message name="requestMessage">
|
||||
<wsdl:part name="body" element="tns:request"/>
|
||||
</wsdl:message>
|
||||
|
||||
<wsdl:portType name="portType">
|
||||
<wsdl:operation name="operation">
|
||||
<wsdl:input message="tns:requestMessage" name="request"/>
|
||||
<wsdl:output message="tns:responseMessage" name="response"/>
|
||||
</wsdl:operation>
|
||||
</wsdl:portType>
|
||||
|
||||
<wsdl:binding name="binding" type="tns:portType">
|
||||
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
||||
<wsdl:operation name="operation">
|
||||
<wsdlsoap:operation soapAction=""/>
|
||||
<wsdl:input name="request">
|
||||
<wsdlsoap:body use="literal"/>
|
||||
</wsdl:input>
|
||||
<wsdl:output name="response">
|
||||
<wsdlsoap:body use="literal"/>
|
||||
</wsdl:output>
|
||||
</wsdl:operation>
|
||||
</wsdl:binding>
|
||||
|
||||
<wsdl:service name="service">
|
||||
<wsdl:port binding="tns:binding" name="port">
|
||||
<wsdlsoap:address location="/services"/>
|
||||
</wsdl:port>
|
||||
</wsdl:service>
|
||||
</wsdl:definitions>
|
||||
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://www.springframework.org/spring-ws/wsdl/schemas">
|
||||
<element name="request" type="string"/>
|
||||
<element name="response" type="string"/>
|
||||
</schema>
|
@ -472,6 +472,7 @@ content into your application; rather pick only the properties that you need.
|
||||
spring.webservices.path=/services # Path that serves as the base URI for the services.
|
||||
spring.webservices.servlet.init= # Servlet init parameters to pass to Spring Web Services.
|
||||
spring.webservices.servlet.load-on-startup=-1 # Load on startup priority of the Spring Web Services servlet.
|
||||
spring.webservices.wsdl-locations= # Comma-separated list of locations of WSDLs and accompanying XSDs to be exposed as beans.
|
||||
|
||||
|
||||
[[common-application-properties-security]]
|
||||
|
@ -6560,6 +6560,11 @@ your `Endpoints`.
|
||||
The {spring-webservices-reference}[Spring Web Services features] can be easily accessed
|
||||
via the `spring-boot-starter-webservices` module.
|
||||
|
||||
Spring Boot can also automatically expose your WSDLs and XSDs using
|
||||
`spring.webservices.wsdl-locations` configuration property. For the detected WSDL and XSD
|
||||
files Boot will register beans of type `SimpleWsdl11Definition` and `SimpleXsdSchema`,
|
||||
respectively.
|
||||
|
||||
|
||||
|
||||
[[boot-features-developing-auto-configuration]]
|
||||
|
@ -18,10 +18,8 @@ package sample.webservices;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
|
||||
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
|
||||
import org.springframework.xml.xsd.SimpleXsdSchema;
|
||||
import org.springframework.xml.xsd.XsdSchema;
|
||||
|
||||
@Configuration
|
||||
@ -37,9 +35,4 @@ public class WebServiceConfig extends WsConfigurerAdapter {
|
||||
return wsdl;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public XsdSchema countriesSchema() {
|
||||
return new SimpleXsdSchema(new ClassPathResource("META-INF/schemas/hr.xsd"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
spring.webservices.wsdl-locations=classpath:META-INF/schemas/
|
Loading…
Reference in New Issue
Block a user