春天-WS客户端不设置SOAPAction头(Spring-WS client not settin

2019-07-18 21:19发布

我发送SOAP请求和服务器抱怨SOAPAction头是空的。 我想我的设置是正确的,但显然我不是。 Wireshark的显示它没有设置。

@Test
public void testLogin() throws Exception {
    StringBuffer loginXml = new StringBuffer();
    loginXml.append("<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:ns=\"http://example.com/xyz/2010/08\">");
    loginXml.append("  <soapenv:Header>");
    loginXml.append("    <ns:loginOperationDetails>");
    loginXml.append("    </ns:loginOperationDetails>");
    loginXml.append("  </soapenv:Header>");
    loginXml.append("  <soapenv:Body>");
    loginXml.append("    <ns:LogIn>");
    loginXml.append("      <ns:logInInfo>");
    loginXml.append("        <ns:CustomerAccountId>customer1</ns:CustomerAccountId>");
    loginXml.append("        <ns:Username>JDoe</ns:Username>");
    loginXml.append("        <ns:Password>abc123</ns:Password>");
    loginXml.append("      </ns:logInInfo>");
    loginXml.append("    </ns:LogIn>");
    loginXml.append("  </soapenv:Body>");
    loginXml.append("</soapenv:Envelope>");

    WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
    MessageFactory msgFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    SaajSoapMessageFactory newSoapMessageFactory = new SaajSoapMessageFactory(msgFactory);
    webServiceTemplate.setMessageFactory(newSoapMessageFactory);

    String uri = "http://xyz.example.com/xyz_1.0/membership.svc/ws";
    webServiceTemplate.setDefaultUri(uri);

    StreamSource source = new StreamSource(new StringReader(loginXml.toString()));
    StreamResult result = new StreamResult(System.out);

    boolean resultReturned = false;
    try {
        resultReturned = webServiceTemplate.sendSourceAndReceiveToResult(source, 
            new SoapActionCallback("http://example.com/xyz/2010/08/MembershipService/LogIn"), 
            result);
    } 
    catch (SoapFaultClientException sfe) {
        logger.error("SoapFaultClientException resultReturned: " + resultReturned, sfe);
        fail();
    }
}

我是从服务器取回的错误说:

500 Internal Server Error
The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://example.com/xyz/2010/08/MembershipService/LogIn'.

Answer 1:

完整的回答变为如下。

当您使用WebServiceTemplate为一类与网络服务来沟通,我不明白为什么,但它没有正确填写HTTP标头。

有些WSDL有一部分说:

<soap:operation
            soapAction="SOMELINK"
            style="document" />

WebServiceTemplate忽略这一部分。 上述错误意味着你soapAction在头参数为空。 它应该是没有。 请使用Wireshark。 我做了 - 使用Chrome的某些SOAP客户端和Spring。 第二个具有无效的报头。


为了解决这个问题,你需要按照第6.2.4节在这里: http://docs.spring.io/spring-ws/sites/2.0/reference/html/client.html

它说什么,基本上添加页眉部分你自己,用WebServiceMessageCallback接口。 你可以阅读更多的参考。

基本上,它最终是这样的:

 webServiceTemplate.marshalSendAndReceive(o, new WebServiceMessageCallback() {

    public void doWithMessage(WebServiceMessage message) {
        ((SoapMessage)message).setSoapAction("http://tempuri.org/Action");
    }
});

在这里您可以正确设置标头值。 工作对我来说太。 阅读整整一天。



Answer 2:

我工作了这一点,但从来没有公布答案。 这里是我结束了行之有效:

public WebServiceTemplate getWebServiceTemplate() throws SOAPException {
  if (webServiceTemplate == null) {
    final MessageFactory msgFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    final SaajSoapMessageFactory newSoapMessageFactory = new SaajSoapMessageFactory(msgFactory);
    webServiceTemplate = new WebServiceTemplate(newSoapMessageFactory);
  }   

  return webServiceTemplate;
}

public Object sendReceive(Object requestObject, ArrayList<String> classesToMarshall, final String action)
        throws ClassNotFoundException, SoapFaultException, SoapFaultClientException, WebServiceTransportException,
        IllegalStateException, SOAPException {

  final WebServiceTemplate wst = getWebServiceTemplate();

    final SoapMarshallUtil smu = getSoapMarshallUtil();
    smu.configureMarshaller(wst, classesToMarshall);

    // soap 1.2
    SoapActionCallback requestCallback = new SoapActionCallback(action) {
        public void doWithMessage(WebServiceMessage message) {
            SaajSoapMessage soapMessage = (SaajSoapMessage) message;
            SoapHeader soapHeader = soapMessage.getSoapHeader();

            QName wsaToQName = new QName("http://www.w3.org/2005/08/addressing", "To", "wsa");
            SoapHeaderElement wsaTo =  soapHeader.addHeaderElement(wsaToQName);
            wsaTo.setText(uri);

            QName wsaActionQName = new QName("http://www.w3.org/2005/08/addressing", "Action", "wsa");
            SoapHeaderElement wsaAction =  soapHeader.addHeaderElement(wsaActionQName);
            wsaAction.setText(action);
        }
    };

    Object responseObject = wst.marshalSendAndReceive(this.uri, requestObject, requestCallback);
    return responseObject;
}


Answer 3:

另一个-走动是添加一个拦截器和所述内设置的soapAction handleRequest()的入站接收方法MessageContext从其中SoapMessage可以导出;

之后,你可以方便地设置的soapAction调用setSoapAction()方法。

这里是拦截器类的代码:

public class SecurityInterceptor implements ClientInterceptor {

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {

        SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();
        soapMessage.setSoapAction("mySoapAction");    

        return true;
    }

    //TODO:: other methods and constructor..
}

当然拦截器添加到WebTemplate

WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller);
ClientInterceptor[] interceptors = new ClientInterceptor[]{new SecurityInterceptor(parameters)};
webServiceTemplate.setInterceptors();
webServiceTemplate.marshalSendAndReceive(uriWebService, request)


文章来源: Spring-WS client not setting SOAPAction header