使用CXF时,SoapAction标头丢失

我有一个来自外部WS的WSDL文件,我正在连接到该文件。 我正在尝试使用CXF(适用于JAX-WS)。 但我从其他系统得到错误。 所以我决定看一下我们发送到该系统的数据,唯一不同的是CXF设置了空的SOAPAction http头。

我进行了一些阅读,看起来只有已知的解决方案直接指向WSDL。 但我已经这样做了。

有人对此有所了解吗?

             

头:

 POST /somepath HTTP/1.1 Content-Type: text/xml; charset=UTF-8 Accept: */* Authorization: Basic  SOAPAction: "" User-Agent: Apache CXF 2.7.6 Cache-Control: no-cache Pragma: no-cache Host: somehost:8080 Connection: keep-alive Content-Length: 2791 

这些都不是CXF特有的。 它都是标准的JAX-WS。

您可以使用@WebMethod批注的action属性来设置SOAP操作。 例如

 @WebMethod(operationName = "TestOperation", action="http://example.org/TestOperation") 

如果您使用wsimport从WSDL生成工件,那么您应该已经在@WebService注释接口中设置了此设置。

我能够使用这样的调用复制你描述的行为(SOAPAction头是“”):

 MyPortService service = new MyPortService(); MyPort port = service.getMyPortSoap11(); MyRequest request = new MyRequest(); MyResponse response = port.subscription( request ); 

以下是使用此调用的TCP转储的HTTP标头:

 POST /MyService/services HTTP/1.1 Content-Type: text/xml; charset=UTF-8 Accept: */* SOAPAction: "" User-Agent: Apache CXF 2.7.6 Cache-Control: no-cache Pragma: no-cache Host: redacted Connection: keep-alive Content-Length: 377 

我尝试添加一个out拦截器并确保将SOAPAction设置为标头,但无论我尝试了什么都不会导致SOAPAction作为HTTP请求的一部分发送。

然后我在这个post中找到了一个主角并重新格式化了我的调用:

 ClientProxyFactoryBean factory = new ClientProxyFactoryBean(); factory.setServiceClass( MyPort.class ); factory.setAddress( "http://www.host.com/service" ); factory.setServiceName( new QName( targetNamespace, wsdlBindingName ) ); Object myService = factory.create(); org.apache.cxf.endpoint.Client client = ClientProxy.getClient( myService ); Map> headers = new HashMap>(); headers.put("SOAPAction", Arrays.asList("mySoapAction")); client.getRequestContext().put(Message.PROTOCOL_HEADERS, headers); client.invoke( operationName, request ); 

以下是此样式中调用的TCP Dump的HTTP标头:

 POST /MyService/services HTTP/1.1 Content-Type: text/xml; charset=UTF-8 Accept: */* SOAPAction: mySoapAction User-Agent: Apache CXF 2.7.6 Cache-Control: no-cache Pragma: no-cache Host: redacted Connection: keep-alive Content-Length: 377 

希望这可以帮助。

如果它仍然是实际的。 面对同样的问题,写了拦截器。 它非常普遍:

 public class SoapActionInterceptor extends AbstractSoapInterceptor { private static final String SLASH = "/"; public SoapActionInterceptor() { super(Phase.POST_LOGICAL); } @Override public void handleMessage(SoapMessage message) throws Fault { BindingOperationInfo bindingOperationInfo = message.getExchange().getBindingOperationInfo(); OperationInfo operationInfo = bindingOperationInfo.getOperationInfo(); InterfaceInfo interfaceInfo = operationInfo.getInterface(); QName interfaceInfoNameQName = interfaceInfo.getName(); QName operationQName = operationInfo.getName(); Map> reqHeaders = CastUtils.cast((Map) message.get(Message.PROTOCOL_HEADERS)); if (reqHeaders == null) { reqHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); } if (reqHeaders.size() == 0) { message.put(Message.PROTOCOL_HEADERS, reqHeaders); } reqHeaders.put(SoapBindingConstants.SOAP_ACTION, Arrays.asList(interfaceInfoNameQName.getNamespaceURI() + SLASH + interfaceInfoNameQName.getLocalPart() + SLASH + operationQName.getLocalPart())); } } 

要在Spring + Apache CXF中使用它:

      

我找到了这个问题的另一个原因,所以我想我会继续发布这个答案,以防它帮助某人。

在创建SOAP服务,WSDL优先,并从XSD生成服务接口和相关类之后,我发现我在wsdl中设置的soap操作没有显示在CXF生成的WSDL中(您可以访问它)将“?wsdl”添加到您的服务端点并将其放入浏览器中。

例如: http:// localhost:8080 / mywar / services / myservice?wsdl

这个问题的原因是我没有正确地注释服务实现类。 虽然生成的接口上有相应的注释,但实现类是我的问题的原因。

我必须将以下内容添加到我的服务实现类中以解决此问题:

@WebService( targetNamespace="...", portName="...", endpointInterface="...", serviceName="...")

希望这有助于某人……