我有一个来自外部WS的WSDL文件,我正在连接到该文件。我正在尝试使用CXF(与JAX-WS一起使用)。但我从其他系统得到错误。所以我决定看一下我们发送到该系统的数据,唯一不同的是CXF设置了空的SOAPAction http头。
我进行了一些阅读,看起来只有已知的解决方案直接指向WSDL。但我已经这样做了。
任何人都有这方面的线索吗?
<bean id="object" class="xxx.XxxObject" factory-bean="objectFActory"
factory-method="create"/>
<bean id="objectFActory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="xxx.XxxObject"/>
<property name="wsdlLocation" value="http://blebleble"/>
<property name="address" value="http://blebleble"/>
<property name="username" value="user"/>
<property name="password" value="password"/>
<property name="properties">
<map>
<entry key="javax.xml.ws.session.maintain" value-type="java.lang.Boolean" value="true"/>
</map>
</property>
</bean>
接头:
POST /somepath HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: */*
Authorization: Basic <randomhex>
SOAPAction: ""
User-Agent: Apache CXF 2.7.6
Cache-Control: no-cache
Pragma: no-cache
Host: somehost:8080
Connection: keep-alive
Content-Length: 2791
答案 0 :(得分:8)
这些都不是CXF特有的。它都是标准的JAX-WS。
您可以使用@WebMethod注释的action属性来设置SOAP操作。例如
@WebMethod(operationName = "TestOperation", action="http://example.org/TestOperation")
如果您使用wsimport从WSDL生成工件,那么您应该已经在@WebService带注释的界面中设置了此设置。
答案 1 :(得分:3)
我能够使用这样的调用复制你描述的行为(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请求的一部分发送。
然后我在这个thread找到了一个主角并重新格式化了我的调用:
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<String, List<String>> headers = new HashMap<String, List<String>>();
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
希望这有帮助。
答案 2 :(得分:1)
如果它仍然是实际的。面对同样的问题,写了拦截器。它非常普遍:
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<String, List<String>> 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中使用它:
<jaxws:client id="client" serviceClass="some.generated.webservice.Interface"
wsdlLocation="/META-INF/wsdl/webservice.wsdl"
address="http://example.address/service">
<jaxws:outInterceptors>
<bean class="some.package.interceptor.SoapActionInterceptor"/>
</jaxws:outInterceptors>
</jaxws:client>
答案 3 :(得分:0)
我发现了这个问题的另一个原因,所以我想我会继续发布这个答案,以防它帮助某人。
在创建SOAP服务,WSDL优先,并从XSD生成服务接口和相关类之后,我发现我在wsdl中设置的soap操作没有出现在CXF生成的WSDL中(你在可以通过将“?wsdl”添加到您的服务端点并将其放入浏览器中来实现。
ex:http://localhost:8080/mywar/services/myservice?wsdl
这个问题的原因是我没有正确地注释服务实现类。虽然生成的接口上有相应的注释,但实现类是我的问题的原因。
我必须将以下内容添加到我的服务实现类中以解决此问题:
@WebService(
targetNamespace="...",
portName="...",
endpointInterface="...",
serviceName="...")
希望这有助于某人...