1

您能否建议我是否可以在 JAX-RPC 中使用带有 DII概念的 WSDL,并在 CXF2.6(不支持 JAX-RPC)框架中编写一个方法来使用 JAX-RPC 服务?您是否看到与这种方法的任何类加载问题或 jar 冲突?

CXF 管道是否支持这样的调用?

原因是我们的供应商仍然使用 JAX-RPC,并且我们在 JAX-WS 框架上运行。我们无法控制托管供应商的实施。

萨卢多斯·卡提克

4

1 回答 1

0

你可以试试这个从 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;
    }
}
于 2012-08-03T21:22:11.397 回答