Web Services spring-ws SOAP -缺少消息和绑定

sh7euo9m  于 2022-11-15  发布在  Spring
关注(0)|答案(1)|浏览(192)

我想使用spring-ws实现我自己的SOAP webservcie。我已经写了一个xsd,从它生成了一个Java类。
这是我的Web服务配置:

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
    MessageDispatcherServlet servlet = new MessageDispatcherServlet();
    servlet.setApplicationContext(applicationContext);
    servlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean(servlet, "/ws/*");
}

@Bean(name = "foo")
public DefaultWsdl11Definition defaultWsdl11DefinitionFoo(){
    DefaultWsdl11Definition defaultWsdl11Definition = new DefaultWsdl11Definition();
    defaultWsdl11Definition.setPortTypeName("FooPort");
    defaultWsdl11Definition.setLocationUri("/ws");
    defaultWsdl11Definition.setTargetNamespace("foo");
    defaultWsdl11Definition.setSchema(fooSchema());
    return defaultWsdl11Definition;
}

@Bean
public XsdSchema fooSchema() {
    return new SimpleXsdSchema(new ClassPathResource("foo.xsd"));
}

这是我的xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="foo" elementFormDefault="qualified">
<xs:complexType name="Foobject">
    <xs:sequence>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="population" type="xs:int"/>
    </xs:sequence>
</xs:complexType>

这是我的端点:

@Endpoint
public class Fooendpoint {

private static final String NAMESPACE_URI = "foo";

@PayloadRoot(namespace = NAMESPACE_URI, localPart = "bar")
@ResponsePayload
public Foobject getCountry(@RequestPayload Foobject request) {
    return new Foobject("string", 0);
}}

最后,这是Web服务在http://localhost:8080/ws/foo.wsdl发布时自动生成的WSDL

<wsdl:definitions targetNamespace="foo" xmlns:sch="foo" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="foo" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
    <xs:schema elementFormDefault="qualified" targetNamespace="foo" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:complexType name="Foobject">
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="population" type="xs:int"/>
            </xs:sequence>
        </xs:complexType>
    </xs:schema>
</wsdl:types>
<wsdl:portType name="FooPort"/>
<wsdl:binding name="FooPortSoap11" type="tns:FooPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
</wsdl:binding>
<wsdl:service name="FooPortService">
    <wsdl:port binding="tns:FooPortSoap11" name="FooPortSoap11">
        <soap:address location="http://localhost:8080/ws"/>
    </wsdl:port>
</wsdl:service>

在WSDL中没有消息和操作。我遗漏了什么?

**更新:**我修改了XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="foo" elementFormDefault="qualified" xmlns:tns="foo">

<xs:element name="fooRequest">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="foo" type="tns:Foobject"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="fooResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="string" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:complexType name="Foobject">
    <xs:sequence>
        <xs:element name="string" type="xs:string"/>
        <xs:element name="int" type="xs:int"/>
    </xs:sequence>
</xs:complexType>

WSDL现在具有消息和绑定:

<wsdl:definitions targetNamespace="foo" xmlns:sch="foo" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="foo" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
    <xs:schema elementFormDefault="qualified" targetNamespace="foo" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="fooRequest">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="foo" type="tns:Foobject"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
        <xs:element name="fooResponse">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="string" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
        <xs:complexType name="Foobject">
            <xs:sequence>
                <xs:element name="string" type="xs:string"/>
                <xs:element name="int" type="xs:int"/>
            </xs:sequence>
        </xs:complexType>
    </xs:schema>
</wsdl:types>
<wsdl:message name="fooResponse">
    <wsdl:part element="tns:fooResponse" name="fooResponse"/>
</wsdl:message>
<wsdl:message name="fooRequest">
    <wsdl:part element="tns:fooRequest" name="fooRequest"/>
</wsdl:message>
<wsdl:portType name="FooPort">
    <wsdl:operation name="foo">
        <wsdl:input message="tns:fooRequest" name="fooRequest"/>
        <wsdl:output message="tns:fooResponse" name="fooResponse"/>
    </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="FooPortSoap11" type="tns:FooPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="foo">
        <soap:operation soapAction=""/>
        <wsdl:input name="fooRequest">
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output name="fooResponse">
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>
<wsdl:service name="FooPortService">
    <wsdl:port binding="tns:FooPortSoap11" name="FooPortSoap11">
        <soap:address location="http://localhost:8080/ws"/>
    </wsdl:port>
</wsdl:service>

但是当我通过SoapUI发送请求时,找不到终结点:

No endpoint mapping found for [SaajSoapMessage {foo}fooRequest]
w3nuxt5m

w3nuxt5m1#

对于任何需要“解决方案”的人来说,这里有一个小的(真实的的)解决问题的技巧。这个问题在spring的参数匹配算法中。它检查“parameter instanceof org.w3c.Element”。如果没有,你就没有匹配,方法也不会被调用。

顺便说一句:如果有人有更好的解决方案,请让我知道!它一定在某个地方。

以防万一,你会得到:

// No adapter for endpoint [public <CorrectType> <CorrectMethod>(<CorrectArgumentType>)]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?

您可以将方法更改为:

public org.w3c.Element correctMethod(org.w3c.Element parameter) {...

现在调用该方法,您可以解组参数并使用JAXBContext编组结果。
对于封送处理,可以使用如下方法:

private <T> T unmarshalParameter(Element element, Class<? extends T> targetClass) {
        JAXBContext context = null;
        try {
            context = JAXBContext.newInstance(targetClass);
            return context.createUnmarshaller().unmarshal(element, targetClass).getValue();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }

结果的封送行程可以像这样完成:

private <T> Element marshal(T response, String elementName) {
        JAXBContext jaxbContext = null;
        try {
            Document document =
                    DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            jaxbContext = JAXBContext.newInstance(response.getClass());
            DOMResult res = new DOMResult(document);
            JAXBElement<?> jaxbElement =
                    new JAXBElement<>( new QName(NAMESPACE_URI,elementName),
                            (Class<T>)response.getClass(),
                            response);
            jaxbContext.createMarshaller().marshal(jaxbElement,res);
            Element e = (Element)document.getDocumentElement();
            return e;
        } catch (JAXBException | ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

相关问题