我正在尝试使用Spring WS构建合同的第一个Web服务。附件是代码和SOAP UI测试文件。每当我尝试访问此Web服务时,我都会收到错误
unexpected element (uri:"http://www.aig.com/service/policyinquiry/1/soap", local:"PolicySearchByOwnerSSN")
您能让我知道缺少什么吗?
WSDL
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:accord="http://ACORD.org/Standards/Life/2" xmlns:tns="http://www.test.com/service/policyinquiry/1/soap"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="policyinquiry" targetNamespace="http://www.test.com/service/policyinquiry/1/soap">
<wsdl:types>
<xsd:schema targetNamespace="http://www.test.com/service/policyinquiry/1/soap" elementFormDefault="qualified">
<xsd:import namespace="http://ACORD.org/Standards/Life/2" schemaLocation="TXLife2.37.00.xsd"/>
<xsd:element name="PolicySearchByOwnerSSN">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLife"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="PolicySearchByOwnerSSNResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLifeResponse"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetPolicyDetails">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLife"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetPolicyDetailsResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLifeResponse"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="PolicySearchByOwnerSSNRequest">
<wsdl:part element="tns:PolicySearchByOwnerSSN" name="PolicySearchByOwnerSSN"/>
</wsdl:message>
<wsdl:message name="PolicySearchByOwnerSSNResponse">
<wsdl:part element="tns:PolicySearchByOwnerSSNResponse" name="PolicySearchByOwnerSSNResponse"/>
</wsdl:message>
<wsdl:message name="GetPolicyDetailsRequest">
<wsdl:part name="GetPolicyDetails" element="tns:GetPolicyDetails"></wsdl:part>
</wsdl:message>
<wsdl:message name="GetPolicyDetailsResponse">
<wsdl:part name="GetPolicyDetailsResponse" element="tns:GetPolicyDetailsResponse"></wsdl:part>
</wsdl:message>
<wsdl:portType name="policyinquiry">
<wsdl:operation name="PolicySearchByOwnerSSN">
<wsdl:input message="tns:PolicySearchByOwnerSSNRequest"/>
<wsdl:output message="tns:PolicySearchByOwnerSSNResponse"/>
</wsdl:operation>
<wsdl:operation name="GetPolicyDetails">
<wsdl:input message="tns:GetPolicyDetailsRequest"></wsdl:input>
<wsdl:output message="tns:GetPolicyDetailsResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="policyinquirySOAP" type="tns:policyinquiry">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="PolicySearchByOwnerSSN">
<soap:operation soapAction="http://www.test.com/service/policyinquiry/1/soap/PolicySearchByOwnerSSN"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetPolicyDetails">
<soap:operation soapAction="http://www.test.com/service/policyinquiry/1/soap/GetPolicyDetails"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="policyinquiry">
<wsdl:port binding="tns:policyinquirySOAP" name="PolicyInquiry">
<soap:address location="http://www.test.com/service/policyinquiry/1/soap"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
java端点
@Endpoint
public class PolicyServiceSOAPEndpoint {
public static final String NAMESPACE_URI = "http://www.test.com/service/policyinquiry/1/soap"; //"http://ACORD.org/Standards/Life/2";
@Autowired
PolicySearchByOwnerSSNService policySearchByOwnerSSNService;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "PolicySearchByOwnerSSN")
@ResponsePayload
public PolicySearchByOwnerSSNResponse policySearchByOwnerSSN(@RequestPayload PolicySearchByOwnerSSN policySearchByOwnerSSN){
Party owner = parties.get(ownerpartyid);
if(null == owner){
//TODO: Throw exception
}
String ownerssn = owner.getGovtID();
return policySearchByOwnerSSNService.getPoliciesByOwnerSSN(ownerssn);
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "GetPolicyDetails")
@ResponsePayload
public GetPolicyDetailsResponse getPolicyDetails(@RequestPayload GetPolicyDetails getPolicyDetails){
return null;
}
}
春季配置类
@EnableWs
@Configuration
public class PolicyInquiryServiceConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext appContext){
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(appContext);
servlet.setTransformWsdlLocations(false);
return new ServletRegistrationBean(servlet, "/policyservice/*");
}
@Bean
public SaajSoapMessageFactory messageFactory() {
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
// messageFactory.setSoapVersion(SoapVersion.SOAP_12);
messageFactory.setSoapVersion(SoapVersion.SOAP_11);
return messageFactory;
}
@Bean(name = "policyinquiry")
public Wsdl11Definition defaultWsdl11Definition(XsdSchema schema){
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("policyinquiry.wsdl"));
return wsdl11Definition;
}
@Bean
public XsdSchema txlifeSchema(){
//return new SimpleXsdSchema(new ClassPathResource("policyinquiry.wsdl"));
return null;
}
@Bean
public PayloadValidatingInterceptor payloadValidator(){
PayloadValidatingInterceptor payloadValidatingInterceptor = new PayloadValidatingInterceptor();
payloadValidatingInterceptor.setValidateRequest(false);
payloadValidatingInterceptor.setValidateResponse(true);
payloadValidatingInterceptor.setSchema(new ClassPathResource("TXLife2.37.00.xsd"));
return payloadValidatingInterceptor;
}
@Autowired
PayloadValidatingInterceptor payloadValidatingInterceptor;
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
// register the CustomEndpointInterceptor
interceptors.add(payloadValidatingInterceptor);
interceptors.add(new PayloadLoggingInterceptor());
interceptors.add(new SoapEnvelopeLoggingInterceptor());
}
}
SOAP UI测试XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://www.test.com/service/policyinquiry/1/soap" xmlns:ns="http://ACORD.org/Standards/Life/2">
<soapenv:Header/>
<soapenv:Body>
<soap:PolicySearchByOwnerSSN>
<ns:TXLife>
<ns:TransRefGUID>b08f35df-3490-4c40-91c9-13a6e702892a</ns:TransRefGUID>
<ns:TransType tc="212">Values Inquiry</ns:TransType>
<ns:TransSubType tc="1004921209">Withdrawal</ns:TransSubType>
<ns:TransExeDate>2017-06-21-07:00</ns:TransExeDate>
<ns:TransExeTime>14:26:03-04:00</ns:TransExeTime>
<ns:OLifE>
<ns:Holding id="AnnuityOrder1212130">
</ns:Holding>
<ns:Party id="Party_PrimaryOwner">
<ns:PartyTypeCode tc="1">Person</ns:PartyTypeCode>
<ns:GovtID>1234567</ns:GovtID>
</ns:Party>
<ns:Relation id="PrimaryOwner_Relation" OriginatingObjectID="AnnuityOrder1212130" RelatedObjectID="Party_PrimaryOwner">
<ns:OriginatingObjectType tc="4">Holding</ns:OriginatingObjectType>
<ns:RelatedObjectType tc="6">Party</ns:RelatedObjectType>
<ns:RelationRoleCode tc="8">Primary Owner</ns:RelationRoleCode>
</ns:Relation>
</ns:OLifE>
</ns:TXLife>
</soap:PolicySearchByOwnerSSN>
</soapenv:Body>
</soapenv:Envelope>
更改WS及其数据的名称空间
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:accord="http://ACORD.org/Standards/Life/2" xmlns:tns="http://www.test.com/service/policyinquiry/1/soap"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="policyinquiry" xmlns:types="http://www.test.com/service/policyinquiry/types" targetNamespace="http://www.test.com/service/policyinquiry/1/soap">
<wsdl:types>
<xsd:schema targetNamespace="http://www.test.com/service/policyinquiry/types" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" version="1.0">
<xsd:import namespace="http://ACORD.org/Standards/Life/2" schemaLocation="TXLife2.37.00.xsd" />
<xsd:element name="PolicySearchByOwnerSSN">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLife"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="PolicySearchByOwnerSSNResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLifeResponse"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetPolicyDetails">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLife"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetPolicyDetailsResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="accord:TXLifeResponse"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="PolicySearchByOwnerSSNRequest">
<wsdl:part element="types:PolicySearchByOwnerSSN" name="PolicySearchByOwnerSSN"/>
</wsdl:message>
<wsdl:message name="PolicySearchByOwnerSSNResponse">
<wsdl:part element="types:PolicySearchByOwnerSSNResponse" name="PolicySearchByOwnerSSNResponse"/>
</wsdl:message>
<wsdl:message name="GetPolicyDetailsRequest">
<wsdl:part name="GetPolicyDetails" element="types:GetPolicyDetails"></wsdl:part>
</wsdl:message>
<wsdl:message name="GetPolicyDetailsResponse">
<wsdl:part name="GetPolicyDetailsResponse" element="types:GetPolicyDetailsResponse"></wsdl:part>
</wsdl:message>
<wsdl:portType name="policyinquiry">
<wsdl:operation name="PolicySearchByOwnerSSN">
<wsdl:input message="tns:PolicySearchByOwnerSSNRequest"/>
<wsdl:output message="tns:PolicySearchByOwnerSSNResponse"/>
</wsdl:operation>
<wsdl:operation name="GetPolicyDetails">
<wsdl:input message="tns:GetPolicyDetailsRequest"></wsdl:input>
<wsdl:output message="tns:GetPolicyDetailsResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="policyinquirySOAP" type="tns:policyinquiry">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="PolicySearchByOwnerSSN">
<soap:operation soapAction="http://www.test.com/service/policyinquiry/1/soap/PolicySearchByOwnerSSN"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetPolicyDetails">
<soap:operation soapAction="http://www.test.com/service/policyinquiry/1/soap/GetPolicyDetails"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="policyinquiry">
<wsdl:port binding="tns:policyinquirySOAP" name="PolicyInquiry">
<soap:address location="http://www.test.com/service/policyinquiry/1/soap"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
响应有效载荷期望JAXBElement
在QNAME中同时通过NAMESPACE_URI
和Object
。我已经在下面使用了代码片段来解决问题:
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "ObjectName")
@ResponsePayload
public JAXBElement<ResponseObject> methodName(@RequestPayload JAXBElement<Object> parameters) {
//Method logic goes here
return createResponseJaxbElement(response, ResponseObject.class);
}
private JAXBElement createResponseJaxbElement(T object, Class clazz) {
return new JAXBElement<>(new QName(NAMESPACE_URI, clazz.getSimpleName()), clazz, object);
}