您能否建议我是否可以在 JAX-RPC 中使用带有 DII概念的 WSDL,并在 CXF2.6(不支持 JAX-RPC)框架中编写一个方法来使用 JAX-RPC 服务?您是否看到与这种方法的任何类加载问题或 jar 冲突?
CXF 管道是否支持这样的调用?
原因是我们的供应商仍然使用 JAX-RPC,并且我们在 JAX-WS 框架上运行。我们无法控制托管供应商的实施。
萨卢多斯·卡提克
您能否建议我是否可以在 JAX-RPC 中使用带有 DII概念的 WSDL,并在 CXF2.6(不支持 JAX-RPC)框架中编写一个方法来使用 JAX-RPC 服务?您是否看到与这种方法的任何类加载问题或 jar 冲突?
CXF 管道是否支持这样的调用?
原因是我们的供应商仍然使用 JAX-RPC,并且我们在 JAX-WS 框架上运行。我们无法控制托管供应商的实施。
萨卢多斯·卡提克
你可以试试这个从 CXF 中改编而来的 DynamicClientFactory。这将允许您调用 RPC/编码的 Web 服务。
代码:
拨打电话:
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
org.apache.cxf.endpoint.Client client = dcf.createClient(url); //URL of WSDL
Object[] response = client.invoke(...);
DynamicClientFactory.java
package ar.com.nextel.nxsgst.daemon.core;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.CXFBusFactory;
import org.apache.cxf.common.i18n.Message;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.ClientImpl;
import org.apache.cxf.endpoint.EndpointImplFactory;
import org.apache.cxf.endpoint.SimpleEndpointImplFactory;
import org.apache.cxf.endpoint.dynamic.TypeClassInitializer;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.resource.URIResolver;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.factory.ServiceConstructionException;
import org.apache.cxf.service.model.SchemaInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JPackage;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.api.ErrorListener;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;
public class DynamicClientFactory {
private static final Logger LOG = LogUtils.getL7dLogger(DynamicClientFactory.class);
private Bus bus;
private boolean simpleBindingEnabled = true;
private Map<String, Object> jaxbContextProperties;
protected DynamicClientFactory(Bus bus) {
this.bus = bus;
}
protected EndpointImplFactory getEndpointImplFactory() {
return SimpleEndpointImplFactory.getSingleton();
}
/**
* Create a new instance using a specific <tt>Bus</tt>.
*
* @param b the <tt>Bus</tt> to use in subsequent operations with the
* instance
* @return the new instance
*/
public static DynamicClientFactory newInstance(Bus b) {
return new DynamicClientFactory(b);
}
/**
* Create a new instance using a default <tt>Bus</tt>.
*
* @return the new instance
* @see CXFBusFactory#getDefaultBus()
*/
public static DynamicClientFactory newInstance() {
Bus bus = CXFBusFactory.getThreadDefaultBus();
return new DynamicClientFactory(bus);
}
/**
* Create a new <code>Client</code> instance using the WSDL to be loaded
* from the specified URL and using the current classloading context.
*
* @param wsdlURL the URL to load
* @return
*/
public Client createClient(String wsdlUrl) {
return createClient(wsdlUrl, (QName)null, (QName)null);
}
/**
* Create a new <code>Client</code> instance using the WSDL to be loaded
* from the specified URL and with the specified <code>ClassLoader</code>
* as parent.
*
* @param wsdlUrl
* @param classLoader
* @return
*/
public Client createClient(String wsdlUrl, ClassLoader classLoader) {
return createClient(wsdlUrl, null, classLoader, null);
}
public Client createClient(String wsdlUrl, QName service) {
return createClient(wsdlUrl, service, null);
}
public Client createClient(String wsdlUrl, QName service, QName port) {
return createClient(wsdlUrl, service, null, port);
}
public Client createClient(String wsdlUrl, QName service, ClassLoader classLoader, QName port) {
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
URL u = composeUrl(wsdlUrl);
LOG.log(Level.FINE, "Creating client from URL " + u.toString());
ClientImpl client = new ClientImpl(bus, u, service, port,
getEndpointImplFactory());
Service svc = client.getEndpoint().getService();
//all SI's should have the same schemas
Collection<SchemaInfo> schemas = svc.getServiceInfos().get(0).getSchemas();
SchemaCompiler compiler = XJC.createSchemaCompiler();
ErrorListener elForRun = new InnerErrorListener(wsdlUrl);
compiler.setErrorListener(elForRun);
addSchemas(wsdlUrl, schemas, compiler);
S2JJAXBModel intermediateModel = compiler.bind();
JCodeModel codeModel = intermediateModel.generateCode(null, elForRun);
StringBuilder sb = new StringBuilder();
boolean firstnt = false;
for (Iterator<JPackage> packages = codeModel.packages(); packages.hasNext();) {
JPackage jpackage = packages.next();
if (!isValidPackage(jpackage)) {
continue;
}
if (firstnt) {
sb.append(':');
} else {
firstnt = true;
}
sb.append(jpackage.name());
}
outputDebug(codeModel);
String packageList = sb.toString();
JAXBContext context = null;
Map<String, Object> contextProperties = jaxbContextProperties;
if (contextProperties == null) {
contextProperties = Collections.emptyMap();
}
try {
if (StringUtils.isEmpty(packageList)) {
context = JAXBContext.newInstance(new Class[0], contextProperties);
}
} catch (JAXBException jbe) {
throw new IllegalStateException("Unable to create JAXBContext for generated packages: "
+ jbe.getMessage(), jbe);
}
JAXBDataBinding databinding = new JAXBDataBinding();
databinding.setContext(context);
svc.setDataBinding(databinding);
ServiceInfo svcfo = client.getEndpoint().getEndpointInfo().getService();
TypeClassInitializer visitor = new TypeClassInitializer(svcfo, intermediateModel);
visitor.walk();
return client;
}
private boolean isValidPackage(JPackage jpackage) {
if (jpackage == null) {
return false;
}
String name = jpackage.name();
if ("org.w3._2001.xmlschema".equals(name)
|| "java.lang".equals(name)
|| "java.io".equals(name)
|| "generated".equals(name)) {
return false;
}
Iterator<JDefinedClass> i = jpackage.classes();
while (i.hasNext()) {
JDefinedClass current = i.next();
if ("ObjectFactory".equals(current.name())) {
return true;
}
}
return false;
}
private void outputDebug(JCodeModel codeModel) {
if (!LOG.isLoggable(Level.INFO)) {
return;
}
StringBuffer sb = new StringBuffer();
boolean first = true;
for (Iterator<JPackage> itr = codeModel.packages(); itr.hasNext();) {
JPackage package1 = itr.next();
for (Iterator<JDefinedClass> citr = package1.classes(); citr.hasNext();) {
if (!first) {
sb.append(", ");
} else {
first = false;
}
sb.append(citr.next().fullName());
}
}
// LOG.log(Level.INFO, "Created classes: " + sb.toString());
}
private void addSchemas(String wsdlUrl, Collection<SchemaInfo> schemas, SchemaCompiler compiler) {
int num = 1;
for (SchemaInfo schema : schemas) {
Element el = schema.getElement();
compiler.parseSchema(wsdlUrl + "#types" + num, el);
num++;
}
if (simpleBindingEnabled && isJaxb21()) {
String id = "/org/apache/cxf/endpoint/dynamic/simple-binding.xjb";
LOG.info("Loading the JAXB 2.1 simple binding for client.");
InputSource source = new InputSource(getClass().getResourceAsStream(id));
source.setSystemId(id);
compiler.parseSchema(source);
}
}
private boolean isJaxb21() {
String id = Options.getBuildID();
StringTokenizer st = new StringTokenizer(id, ".");
String minor = null;
// major version
if (st.hasMoreTokens()) {
st.nextToken();
}
if (st.hasMoreTokens()) {
minor = st.nextToken();
}
try {
int i = Integer.valueOf(minor);
if (i >= 1) {
return true;
}
} catch (NumberFormatException e) {
// do nothing;
}
return false;
}
public boolean isSimpleBindingEnabled() {
return simpleBindingEnabled;
}
public void setSimpleBindingEnabled(boolean simpleBindingEnabled) {
this.simpleBindingEnabled = simpleBindingEnabled;
}
private URL composeUrl(String s) {
try {
URIResolver resolver = new URIResolver(null, s, getClass());
if (!resolver.isResolved())
throw new ServiceConstructionException(new Message("COULD_NOT_RESOLVE_URL", LOG, s));
return resolver.getURI().toURL();
} catch (IOException e) {
throw new ServiceConstructionException(new Message("COULD_NOT_RESOLVE_URL", LOG, s), e);
}
}
private class InnerErrorListener implements ErrorListener {
private String url;
InnerErrorListener(String url) {
this.url = url;
}
public void error(SAXParseException arg0) {
throw new RuntimeException("Error compiling schema from WSDL at {" + url + "}: "
+ arg0.getMessage(), arg0);
}
public void fatalError(SAXParseException arg0) {
throw new RuntimeException("Fatal error compiling schema from WSDL at {" + url + "}: "
+ arg0.getMessage(), arg0);
}
public void info(SAXParseException arg0) {
// ignore
}
public void warning(SAXParseException arg0) {
// ignore
}
}
/**
* Return the map of JAXB context properties used at the time that we create new contexts.
* @return the map
*/
public Map<String, Object> getJaxbContextProperties() {
return jaxbContextProperties;
}
/**
* Set the map of JAXB context properties used at the time that we create new contexts.
* @param jaxbContextProperties
*/
public void setJaxbContextProperties(Map<String, Object> jaxbContextProperties) {
this.jaxbContextProperties = jaxbContextProperties;
}
}