CXF动态客户端总是提示No operation was found with the name {...},命名空间问题:
[url]http://pangsir.iteye.com/blog/1492508[/url]
当我们使用CXF动态客户端调用WebService接口容易出现如下问题:
这个问题是由这个问题因为SIB和SEI类的targetNamespace统一导致的,解决方法
SIB的targetNamespace的命名空间为SEI对应的命名空间targetNamespace相同即可。
[b]1.第一种方式为配置SIB和SEI的targetNamespace相同:[/b]
[b]SIB:[/b]
[b]SEI:[/b]
SIB和SEI的@WebService注解中的targetNamespace要相同,
SIB的@WebService的targetNamespace对应为SEI的targetNamespace。
动态客户端:
[b]2.第二种方式动态客户端直接通过QName调用WebService对应的操作,
这种方式针对SIB和SEI的targetNamespace不相同,同时不再同一个包:[/b]
[b]动态客户端:[/b]
强烈建议使用第一种方式,符合规范。
[url]http://pangsir.iteye.com/blog/1492508[/url]
当我们使用CXF动态客户端调用WebService接口容易出现如下问题:
Exception in thread "main" org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name {http://impl.service.jws/}sum.
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:289)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:283)
at cxf.bootstrap.CxfDynamicClientOnJwsRtWeb.main(CxfDynamicClientOnJwsRtWeb.java:36)
这个问题是由这个问题因为SIB和SEI类的targetNamespace统一导致的,解决方法
SIB的targetNamespace的命名空间为SEI对应的命名空间targetNamespace相同即可。
[b]1.第一种方式为配置SIB和SEI的targetNamespace相同:[/b]
[b]SIB:[/b]
package jws.service.impl;
import javax.jws.WebService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import entity.User;
import jws.service.JwsIService;
/**
* Service implementation Bean(SIB)
* RPC接口实现
* 注意这里的targetNamespace的命名空间为SEI对应的命名空间,注意最后要加/
* 否则利用CXF动态客户端调用时,会找不到
* Exception in thread "main" org.apache.cxf.common.i18n.UncheckedException:
* No operation was found with the name {http://impl.service.jws/}sum.
* @author donald
* 2017年7月7日
* 下午5:11:49
*/
@WebService(endpointInterface="jws.service.JwsIService",
serviceName = "jwsService",
portName = "jwsPort",
targetNamespace = "http://service.jws/"
// targetNamespace = "http://www.donald.service/jws_service/"
)
public class JwsServiceImpl implements JwsIService {
private static final Logger log = LoggerFactory.getLogger(JwsServiceImpl.class);
@Override
public int sum(int firstNum, int secondNum) {
int result = firstNum+secondNum;
log.info("======"+firstNum+"+"+secondNum+"="+result);
return result;
}
}
[b]SEI:[/b]
package jws.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import entity.User;
/**
* service endpoint interface(SEI)
* RPC接口
* 如果返回结果时实例类,则targetNamespace必须用http://service.jws/,即http://+SEI倒序报名+/
* 没有的话可以,targetNamespace可任意指定http://www.donald.service/jws_service/
* @author donald
* 2017年7月7日
* 下午5:11:53
*/
@WebService(
targetNamespace = "http://service.jws/"
// targetNamespace = "http://www.donald.service/jws_service/"
)
public interface JwsIService {
//@WebMethod注解可写可不写
// @WebMethod
@WebResult(name="sumResult")
public int sum(@WebParam(name="firstNum")int firstNum,
@WebParam(name="secondNum")int secondNum);
}
SIB和SEI的@WebService注解中的targetNamespace要相同,
SIB的@WebService的targetNamespace对应为SEI的targetNamespace。
动态客户端:
package cxf.bootstrap;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jws.service.User;
import util.JsonUtil;
/**
* CXF 动态代理模式,不用生成本地WS代理类,
* 通过反射调用 WS 的对应的方法,传入相应的参数
* 访问cxf-server-web项目下的webservice;
* 测试jaxws-rt发布WebService web方式。
* 此测试实例,用于测试SEI和SIB的targetNamespace指定的webService接口:
* http://localhost:8080/cxf_server_web/jws_services?wsdl;
* @author donald
* 2017年7月8日
* 下午7:24:12
*/
public class CxfDynamicClientOnJwsRtWeb {
private static final Logger log = LoggerFactory.getLogger(CxfClient.class);
private static final String JWS_RT_WSDL_URI = "http://localhost:8080/cxf_server_web/jws_services?wsdl";
public static void main(String[] args) throws Exception {
log.info("======CXF-WS Dynamic Client start!======");
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient(JWS_RT_WSDL_URI);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setConnectionTimeout(10000);
policy.setAllowChunking(false);
policy.setReceiveTimeout(10000);
conduit.setClient(policy);
Object[] invokeResult = client.invoke("sum", 17,8);
log.info("=======sumResult:" + invokeResult[0]);
}
}
[b]2.第二种方式动态客户端直接通过QName调用WebService对应的操作,
这种方式针对SIB和SEI的targetNamespace不相同,同时不再同一个包:[/b]
[b]动态客户端:[/b]
package cxf.bootstrap;
import javax.xml.namespace.QName;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.service.model.BindingInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jws.service.User;
import util.JsonUtil;
/**
* CXF 动态代理模式,不用生成本地WS代理类,
* 通过反射调用 WS 的对应的方法,传入相应的参数
* 访问cxf-server-web项目下的webservice;
* 测试jaxws-rt发布WebService web方式。
* 此测试实例,用于测试SEI和SIB的targetNamespace未指定的webService接口:
* http://localhost:8080/cxf_server_web/jws_services?wsdl
* @author donald
* 2017年7月8日
* 下午7:24:12
*/
public class CxfDynamicClientOnJwsRtWebWithQname {
private static final Logger log = LoggerFactory.getLogger(CxfClient.class);
private static final String JWS_RT_WSDL_URI = "http://localhost:8080/cxf_server_web/jws_services?wsdl";
public static void main(String[] args) throws Exception {
log.info("======CXF-WS Dynamic Client start!======");
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient(JWS_RT_WSDL_URI);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setConnectionTimeout(10000);
policy.setAllowChunking(false);
policy.setReceiveTimeout(10000);
conduit.setClient(policy);
//获取操作对应的Qname
QName operateQName = getOperateQName(client,"sum");
//如果Qname已知,可以通过如下方式,直接创建QName
// operateQName = new QName("http://service.jws/","login");
Object[] invokeResult = client.invoke(operateQName, 17,8);
log.info("=======sumResult:" + invokeResult[0]);
}
/**
* 针对SEI和SIB不在统一个包内的情况,先查找操作对应的Qname,
* client通过Qname调用对应操作
* @param client
* @param operation
* @return
*/
private static QName getOperateQName(Client client,String operation){
Endpoint endpoint = client.getEndpoint();
QName opName = new QName(endpoint.getService().getName().getNamespaceURI(), operation);
BindingInfo bindingInfo = endpoint.getEndpointInfo().getBinding();
if (bindingInfo.getOperation(opName) == null) {
for (BindingOperationInfo operationInfo : bindingInfo.getOperations()) {
if (operation.equals(operationInfo.getName().getLocalPart())) {
opName = operationInfo.getName();
break;
}
}
}
log.info("Operation:"+operation+",namespaceURI:" + opName.getNamespaceURI());
return opName;
}
}
强烈建议使用第一种方式,符合规范。