- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在寻找一种解决方案,将 CXF 作为 Web 服务实现的提供者集成到应用程序中。应用程序应该能够基于提供的 WSDL 文件以动态方式实现 Web 服务(这意味着 SEI 类不可用)。由于应用程序通过自己的 servlet 管理 http 请求和 url 映射,因此使用标准 CXF servlet 发布端点是不可行的。另外,我想使用 JAXB 数据绑定(bind)。理想情况下,CXF 应该调用我的 Object invoke(String oper, Object...args)
来进行 Web 服务的实际处理。总体而言,它应该看起来像动态客户端,但针对服务器部分实现。
我已经设法使代码几乎可以工作,但遇到了一些我不明白的事情 - 稍后再讨论。
首先,我将 WSDL 读入字符串并创建其定义。定义已预先缓存在 wsdlManager 中,以便可以通过唯一引用进行访问。然后我创建 JaxWS 动态客户端并获取 CXF 为其生成的 JAXB 数据绑定(bind)。
WSDLManager wsdlManager = serviceBus.getExtension(WSDLManager.class);
WSDLFactory wsdlFactory = wsdlManager.getWSDLFactory();
// Reader
WSDLReader reader = wsdlFactory.newWSDLReader();
reader.setFeature("javax.wsdl.verbose", true);
reader.setFeature("javax.wsdl.importDocuments", true);
Definition def = reader.readWSDL(null, TypeCast.getInputSource(wsdl)); // wsdl is a String containing wsdl definition
// Precache definition using listenerRef as unique identifier
wsdlManager.addDefinition(listenerRef, def);
String[] compileOptions = null;
// Create JAXWS dynamic client using precached address
Client client = createClient(listenerRef, simpleDataBinding, allowElementReferences, compileOptions);
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.initServiceListener: service client is created succefully: " + listenerName);
EndpointInfo cei = client.getEndpoint().getEndpointInfo();
// Use JAXB generated databinding
DataBinding db = client.getEndpoint().getService().getDataBinding();
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.initServiceListener: databinding: " + db);
动态客户端的创建很简单
public Client createClient(String serviceDescription, boolean simpleDataBinding, boolean allowElementReferences, String[] schemaOptions) {
ClassLoader old = Thread.currentThread().getContextClassLoader();
try {
ParentClassLoader dynaLoader = new ParentClassLoader();
JaxWsDynamicClientFactory dynamicClientFactory = JaxWsDynamicClientFactory.newInstance(serviceBus);
dynamicClientFactory.setSimpleBindingEnabled(simpleDataBinding);
dynamicClientFactory.setAllowElementReferences(allowElementReferences);
if (schemaOptions != null) {
dynamicClientFactory.setSchemaCompilerOptions(schemaOptions);
}
return dynamicClientFactory.createClient(serviceDescription, dynaLoader);
} catch (Throwable ex) {
Logger.error("WebServiceProcessor.createClient: exception is caught: " + ex, ex);
return null;
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
接下来,为了创建服务器内容,声明了一些帮助器类
protected class MyWSDLServiceFactory extends WSDLServiceFactory {
public MyWSDLServiceFactory(Bus b, Definition d) {
super(b, d);
}
@Override
public Service create() {
Service svc = super.create();
// Post init
initializeDefaultInterceptors();
initializeDataBindings();
return svc;
}
}
public class MyInvoker extends AbstractInvoker {
protected final Object implementor = new Object();
public MyInvoker() {
}
@Override
public Object getServiceObject(Exchange context) {
return implementor;
}
protected void throwable() throws Exception {
}
@Override
public Object invoke(Exchange exchange, Object o) {
List<Object> params = null;
if (o instanceof List) {
params = CastUtils.cast((List<?>)o);
} else if (o != null) {
params = new MessageContentsList(o);
}
if (Logger.isTraceEnabled()) {
for (Object arg : params)
Logger.trace("MyInvoker.invoke: arg: " + arg);
}
// Method holding declararions of throwable exceptions
Method m = null;
try {
m = MsyInvoker.class.getMethod("throwable");
} catch (NoSuchMethodException ex) {
// Strange
}
return invoke(exchange, null, m, params);
}
@Override
protected Object performInvocation(Exchange exchange, Object serviceObject, Method m, Object[] paramArray) throws Exception {
Message inMessage = exchange.getInMessage();
BindingOperationInfo bop = exchange.getBindingOperationInfo();
String oper = bop.getName().getLocalPart();
// Process request
return processWebListenerRequest(oper, paramArray);
}
}
protected class MyDestinationFactory implements DestinationFactory {
protected final Set<String> prefixes = Collections.unmodifiableSet(new HashSet<String> (Arrays.asList("http://", "https://")));
@Override
public Destination getDestination(EndpointInfo ei, Bus bus) throws IOException {
return new MyDestination(ei, ei.getAddress());
}
@Override
public Set<String> getUriPrefixes() {
return prefixes;
}
@Override
public List<String> getTransportIds() {
return null;
}
}
protected class MyDestination extends ServletDestination {
public MyDestination(EndpointInfo ei, String path) throws IOException {
super(serviceBus, null, ei, path, false);
// Disable async support
isServlet3 = false;
}
@Override
protected void setupMessage(final Message inMessage, final ServletConfig config, final ServletContext context, final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
super.setupMessage(inMessage, config, context, req, resp);
}
@Override
protected String getBasePath(String contextPath) throws IOException {
if (endpointInfo.getAddress() == null) {
return "";
}
return endpointInfo.getAddress();
}
}
然后我们准备创建服务器:
MyWSDLServiceFactory sf = new MyWSDLServiceFactory(serviceBus, def);
sf.setAllowElementRefs(allowElementReferences);
sf.setDataBinding(db);
Service svc = sf.create();
// Clear cached definition
wsdlManager.removeDefinition(def);
svc.setInvoker(new MyInvoker());
// Create endpoints
for (ServiceInfo inf : svc.getServiceInfos()) {
for (EndpointInfo ei : inf.getEndpoints()) {
if (ei.getName().equals(cei.getName())) {
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.initServiceListener: endpoint: " + ei.getName());
String addr = "/" + listenerRef;
try {
ei.setAddress(addr);
JaxWsEndpointImpl ep = new JaxWsEndpointImpl(serviceBus, svc, ei);
svc.getEndpoints().put(ei.getName(), ep);
ep.addHandlerInterceptors();
ep.getInInterceptors().add(new SoapUtil.SoapInLogger());
BindingFactoryManager bfm = serviceBus.getExtension(BindingFactoryManager.class);
// tried this but no effect
// ei.getBinding().setProperty("soap.force.doclit.bare", Boolean.TRUE);
String bindingId = ei.getBinding().getBindingId();
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.initServiceListener: binding id: " + bindingId);
BindingFactory bindingFactory = bfm.getBindingFactory(bindingId);
Server server = new ServerImpl(serviceBus, ep, new MyDestinationFactory(), bindingFactory);
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.initServiceListener: starting server: " + ei.getName());
server.start();
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.initServiceListener: server is started: " + server.isStarted());
// Set reference
listeners.put(listenerRef, server); // Our map to keep web server listeners
} catch (EndpointException e) {
throw new ServiceConstructionException(e);
}
}
}
}
服务器调用看起来像
String address = "/" + listenerRef;
Server server = listeners.get(listenerRef); // Find our server listener in a map
if (server != null) {
Endpoint ep = server.getEndpoint();
EndpointInfo ei = ep.getEndpointInfo();
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.invoke: endpoint: " + listenerName);
try {
AbstractHTTPDestination dest = (AbstractHTTPDestination) server.getDestination();
AsyncContext asyncCtx = requestContext.getAsyncContext();
HttpServletRequest req = (HttpServletRequest) asyncCtx.getRequest();
HttpServletResponse resp = (HttpServletResponse) asyncCtx.getResponse();
ServletContext sctx = req.getServletContext();
ServletConfig scfg = null;
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.invoke: destination resolved successfully: " + listenerName);
// Trigger CXF processing
dest.invoke(scfg, sctx, req, resp);
if (Logger.isDebugEnabled())
Logger.debug("WebServiceProcessor.invoke: endpoint processed successfully: " + listenerName);
} catch (Exception ex) {
Logger.error("WebServiceProcessor.invoke: exception is caught: " + ex, ex);
}
}
正如我已经提到的,该解决方案几乎有效,我尝试使用 CXF 3.3 和我以 http://www.dneonline.com/calculator.asmx?WSDL 为例的一个 WSDL 来测试它。 。我设法使用 SoapUI 调用该服务并获得响应。但现在是奇怪的部分。当我使用标准请求调用网络服务时
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>1</intA><intB>2</intB>
</Add>
</soap:Body>
</soap:Envelope>
由于解码错误而失败
org.apache.cxf.interceptor.Fault: Unmarshalling Error: unexpected element (uri:"http://tempuri.org/", local:"intA"). Expected elements are <{http://tempuri.org/}Add>,<{http://tempuri.org/}AddResponse>,<{http://tempuri.org/}Divide>,<{http://tempuri.org/}DivideResponse>,<{http://tempuri.org/}Multiply>,<{http://tempuri.org/}MultiplyResponse>,<{http://tempuri.org/}Subtract>,<{http://tempuri.org/}SubtractResponse>
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:932) ~[cxf-rt-databinding-jaxb-3.3.6.jar:3.3.6]
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:738) ~[cxf-rt-databinding-jaxb-3.3.6.jar:3.3.6]
at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:170) ~[cxf-rt-databinding-jaxb-3.3.6.jar:3.3.6]
at org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor.getPara(DocLiteralInInterceptor.java:325) ~[cxf-rt-wsdl-3.3.6.jar:3.3.6]
at org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:127) ~[cxf-rt-wsdl-3.3.6.jar:3.3.6]
但它成功通过了验证
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
<Add xmlns="http://tempuri.org/">
<Add>
<intA>1</intA><intB>2</intB>
</Add>
</Add>
</soap:Body>
</soap:Envelope>
但在本例中,传递给 MyInvoker 的参数是一个包含两个 null 元素的数组。尽管如此,它还是生成了格式正确的响应(除了计算值错误,因为输入参数为空)响应
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<ns1:AddResponse xmlns:ns1="http://tempuri.org/">
<AddResult xmlns="http://tempuri.org/">0</AddResult>
</ns1:AddResponse>
</soap:Body>
</soap:Envelope>
所以问题是 - 解码以下有效请求可能会出现什么问题?
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>1</intA><intB>2</intB>
</Add>
</soap:Body>
</soap:Envelope>
我已经使用经过测试的 WSDL 检查了 CXF 动态客户端调用,我从中借用了 JAXB 数据绑定(bind),并且在调用此服务时它生成了完全相同的请求,但由于某种原因似乎无法对其进行解码。
另一个问题,我认为它与第一个问题相关,是为什么在第二个请求的情况下,中的未编码参数为空?对下一步该去哪里有什么建议吗?
提前致谢
最佳答案
这是我自己问题的答案。如果从动态客户端重用 CXF 服务实例并添加一些服务器部分拦截器,事情就会变得正确:
Service svc = client.getEndpoint().getService();
// Server part interceptors
svc.getInInterceptors().add(new ServiceInvokerInterceptor());
svc.getInInterceptors().add(new OutgoingChainInterceptor());
svc.getInInterceptors().add(new OneWayProcessorInterceptor());
关于java - 使用 JAXB 数据绑定(bind)的基于 CXF WSDL 的通用服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61156797/
我将Eclipse Helios Service Release 2版本用于apache cxf。当我转到windo->首选项-> Web服务-> CXF 2.x首选项,并设置cxf运行时时,版本和类
我是任何开放框架的新手(我是基于 java 的解决方案工程师)并试图构建一个 cxf 项目。 我知道我需要 applicationContext.xml文件和内容之类的
我想为不同的目的注册不同的类,以便在同一阶段调用 (Phase.PRE_INVOKE)。是否可以? 最佳答案 看这里http://cxf.apache.org/docs/interceptors.ht
我想使用 wsdl2java(CXF) 命令生成自定义包。 我的 WSDL 结构是: wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/w
我在通过 JAXRSClientFactoryBean.create 创建的 CXF 中有一个 JAX-RS 客户端。如何设置连接/接收超时? 我想我需要掌握管道,但不知道如何操作。这个项目没有使用
鉴于来自 fuse 源的 apache-servicemix-4.4.1-fuse-00-08 的“cxf-osgi”示例,使用 maven 3.0.3 构建,将其部署到 apache karaf 2
这个问题在这里已经有了答案: How do I fix a NoSuchMethodError? (33 个答案) 关闭 29 天前。 我刚刚尝试通过 Maven 使用 Apache CXF 和 S
我正在尝试使用 Apache CXF 开发一个 API 调用,该调用会随请求一起接收附件。我遵循了 this 教程,这就是我到目前为止所得到的。 @POST @Path("/upload") @Req
'org.apache.cxf.tools.wsdlto.WSDLToJava' 将 wsdl 转换为 java 类。 它是在内部使用 JAXB 吗?为什么这个命令能够生成类似于“xjc”创建的类?有
我已经使用 CXF 和 Spring 开发了一个 Java Web 服务。 由于安全原因,我想隐藏 WSDL,尽管 WS 仍然可用。 有没有办法使用 CXF 做到这一点? 最佳答案 您可以在 web.
我有一个生成的 JAXB 类(来自 XSD)。我能够以 XML 和 JSON 的形式返回,但是一旦我将 text/html 添加到我的 Produces 注释中,我就会得到: "No message
我创建了一个非常简单的基于 cxf 的非 spring Servlet,它加载了一个 javax.ws.rs.Application类型。 这是 web.xml: CXFSe
我正在使用 JBOSS EAP 6.2 来部署 restful web 服务。 restful web 服务使用 apache cxf,它取自 jboss eap。目前它使用 jar cxf-api-
我有一个服务方法定义为: public JaxbList getDeal() { List deals = new ArrayList(); Deal type = new Deal(
我需要将 wadl 转换为 java pojo,为此我已经下载了 apache cxf 3.0.1 版本。但是当我在命令提示符下运行 wadl2java bat 文件时,出现以下异常 D:\softw
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: Which maven2 artifacts are necessary to build a WS with CX
我想将一个简单的 CXF Jax-Ws 服务器部署到 ServiceMix。它只是一个同时具有服务接口(interface)和 impl 类的 OSGI 包。我需要将它部署到不同的 ServiceMi
是否可以在 wso2 ESB 中部署 CXF Web 服务? 目前我已经开始从 WSO2 User Guide 引用 wso2 的文档。我想将现有的 CXF Web 服务部署到 ESB。因此,有关这方
我想了解 cxf-bundle和 cxf-bundle-jaxrs jar 。它们是两个不同的 jar ,还是前者本身包含后者? 谢谢,巴蒂亚 最佳答案 前者包含后者。 但是,您实际上不应该使用其中任
我已经built and deployed a custom web services consumer in Java on Domino using the available CXF frame
我是一名优秀的程序员,十分优秀!