且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JAX-WS 客户端:访问本地 WSDL 的正确路径是什么?

更新时间:2023-09-11 22:02:04

***的选择是使用 jax-ws-catalog.xml

当您编译本地 WSDL 文件时,覆盖 WSDL 位置并将其设置为类似

http://localhost/wsdl/SOAService.wsdl

别担心,这只是一个 URI 而不是 URL,这意味着您不必在该地址获得 WSDL.
您可以通过将 wsdllocation 选项传递给 wsdl to java 编译器来实现这一点.

这样做会改变您的代理代码

静态{URL url = null;尝试 {URL baseUrl;baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");} catch (MalformedURLException e) {logger.warning("未能为 wsdl 位置创建 URL:'file:/C:/local/path/to/wsdl/SOAService.wsdl',作为本地文件重试");logger.warning(e.getMessage());}SOASERVICE_WSDL_LOCATION = url;}

静态{URL url = null;尝试 {URL baseUrl;baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");url = 新 URL(baseUrl, "http://localhost/wsdl/SOAService.wsdl");} catch (MalformedURLException e) {logger.warning("未能为 wsdl 位置创建 URL:'http://localhost/wsdl/SOAService.wsdl',作为本地文件重试");logger.warning(e.getMessage());}SOASERVICE_WSDL_LOCATION = url;}

注意在 URL 构造函数中 file://更改为 http://.

现在进入 jax-ws-catalog.xml.如果没有 jax-ws-catalog.xml,jax-ws 确实会尝试从

http://localhost/wsdl/SOAService.wsdl

并失败,因为没有这样的 WSDL 可用.

但是使用 jax-ws-catalog.xml,您可以在 jax-ws 尝试访问 WSDL 时将其重定向到本地打包的 WSDL @

http://localhost/wsdl/SOAService.wsdl

.

这里是 jax-ws-catalog.xml

<system systemId="http://localhost/wsdl/SOAService.wsdl"uri="wsdl/SOAService.wsdl"/></目录>

您正在做的是告诉 jax-ws,它何时需要从

http://localhost/wsdl/SOAService.wsdl

,它应该从本地路径 wsdl/SOAService.wsdl 加载它.

现在应该把 wsdl/SOAService.wsdl 和 jax-ws-catalog.xml 放在哪里?这不是百万美元的问题吗?
它应该在您的应用程序 jar 的 META-INF 目录中.

像这样

ABCD文件|__ 元信息|__ jax-ws-catalog.xml|__ wsdl|__ SOAService.wsdl

这样您甚至不必覆盖访问代理的客户端中的 URL.WSDL 是从您的 JAR 中提取的,您不必在代码中使用硬编码的文件系统路径.

有关 jax-ws-catalog.xml 的更多信息http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html

希望有帮助

The problem is I need to build a web service client from a file I'm been provided. I've stored this file on the local file system and, while I keep the WSDL file in the correct file system folder, everything is fine. When I deploy it to a server or remove the WSDL from the file system folder the proxy can't find the WSDL and rises an error. I've searched the web and I've found the following posts yet I'm not been able to make it work:
JAX-WS Loading WSDL from jar
http://www.java.net/forum/topic/glassfish/metro-and-jaxb/client-jar-cant-find-local-wsdl-0
http://blog.vinodsingh.com/2008/12/locally-packaged-wsdl.html

I'm using NetBeans 6.1 (this is a legacy application I've to update with this new web service client). Below is the JAX-WS proxy class :

    @WebServiceClient(name = "SOAService", targetNamespace = "http://soaservice.eci.ibm.com/", wsdlLocation = "file:/C:/local/path/to/wsdl/SOAService.wsdl")
public class SOAService
    extends Service
{

    private final static URL SOASERVICE_WSDL_LOCATION;
    private final static Logger logger = Logger.getLogger(com.ibm.eci.soaservice.SOAService.class.getName());

    static {
        URL url = null;
        try {
            URL baseUrl;
            baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
            url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");
        } catch (MalformedURLException e) {
            logger.warning("Failed to create URL for the wsdl Location: 'file:/C:/local/path/to/wsdl/SOAService.wsdl', retrying as a local file");
            logger.warning(e.getMessage());
        }
        SOASERVICE_WSDL_LOCATION = url;
    }

    public SOAService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public SOAService() {
        super(SOASERVICE_WSDL_LOCATION, new QName("http://soaservice.eci.ibm.com/", "SOAService"));
    }

    /**
     * @return
     *     returns SOAServiceSoap
     */
    @WebEndpoint(name = "SOAServiceSOAP")
    public SOAServiceSoap getSOAServiceSOAP() {
        return super.getPort(new QName("http://soaservice.eci.ibm.com/", "SOAServiceSOAP"), SOAServiceSoap.class);
    }

    /**
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns SOAServiceSoap
     */
    @WebEndpoint(name = "SOAServiceSOAP")
    public SOAServiceSoap getSOAServiceSOAP(WebServiceFeature... features) {
        return super.getPort(new QName("http://soaservice.eci.ibm.com/", "SOAServiceSOAP"), SOAServiceSoap.class, features);
    }

}


This is my code to use the proxy :

   WebServiceClient annotation = SOAService.class.getAnnotation(WebServiceClient.class);
   // trying to replicate proxy settings
   URL baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource("");//note : proxy uses "."
   URL url = new URL(baseUrl, "/WEB-INF/wsdl/client/SOAService.wsdl");
   //URL wsdlUrl = this.getClass().getResource("/META-INF/wsdl/SOAService.wsdl"); 
   SOAService serviceObj = new SOAService(url, new QName(annotation.targetNamespace(), annotation.name()));
   proxy = serviceObj.getSOAServiceSOAP();
   /* baseUrl;

   //classescomibmecisoaservice
   //URL url = new URL(baseUrl, "../../../../wsdl/SOAService.wsdl");

   proxy = new SOAService().getSOAServiceSOAP();*/
   //updating service endpoint 
   Map<String, Object> ctxt = ((BindingProvider)proxy ).getRequestContext();
   ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
   ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, WebServiceUrl);

NetBeans put a copy of the WSDL in web-inf/wsdl/client/SOAService, so I don't want to add it to META-INF too. Service classes are in WEB-INF/classes/com/ibm/eci/soaservice/ and baseurl variable contains the filesystem full path to it (c:path o heproject...soaservice ). The above code raises the error:

javax.xml.ws.WebServiceException: Failed to access the WSDL at: file:/WEB-INF/wsdl/client/SOAService.wsdl. It failed with: WEB-INFwsdlclientSOAService.wsdl (cannot find the path)

So, first of all, shall I update the wsdllocation of the proxy class? Then how do I tell the SOAService class in WEB-INF/classes/com/ibm/eci/soaservice to search for the WSDL in WEB-INFwsdlclientSOAService.wsdl?

EDITED: I've found this other link - http://jianmingli.com/wp/?cat=41, which say to put the WSDL into the classpath. I'm ashamed to ask: how do I put it into the web application classpath?

The best option is to use jax-ws-catalog.xml

When you compile the local WSDL file , override the WSDL location and set it to something like

http://localhost/wsdl/SOAService.wsdl

Don't worry this is only a URI and not a URL , meaning you don't have to have the WSDL available at that address.
You can do this by passing the wsdllocation option to the wsdl to java compiler.

Doing so will change your proxy code from

static {
    URL url = null;
    try {
        URL baseUrl;
        baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
        url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");
    } catch (MalformedURLException e) {
        logger.warning("Failed to create URL for the wsdl Location: 'file:/C:/local/path/to/wsdl/SOAService.wsdl', retrying as a local file");
        logger.warning(e.getMessage());
    }
    SOASERVICE_WSDL_LOCATION = url;
}

to

static {
    URL url = null;
    try {
        URL baseUrl;
        baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
        url = new URL(baseUrl, "http://localhost/wsdl/SOAService.wsdl");
    } catch (MalformedURLException e) {
        logger.warning("Failed to create URL for the wsdl Location: 'http://localhost/wsdl/SOAService.wsdl', retrying as a local file");
        logger.warning(e.getMessage());
    }
    SOASERVICE_WSDL_LOCATION = url;
}

Notice file:// changed to http:// in the URL constructor.

Now comes in jax-ws-catalog.xml. Without jax-ws-catalog.xml jax-ws will indeed try to load the WSDL from the location

http://localhost/wsdl/SOAService.wsdl

and fail, as no such WSDL will be available.

But with jax-ws-catalog.xml you can redirect jax-ws to a locally packaged WSDL whenever it tries to access the WSDL @

http://localhost/wsdl/SOAService.wsdl

.

Here's jax-ws-catalog.xml

<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
        <system systemId="http://localhost/wsdl/SOAService.wsdl"
                uri="wsdl/SOAService.wsdl"/>
    </catalog>

What you are doing is telling jax-ws that when ever it needs to load WSDL from

http://localhost/wsdl/SOAService.wsdl

, it should load it from local path wsdl/SOAService.wsdl.

Now where should you put wsdl/SOAService.wsdl and jax-ws-catalog.xml ? That's the million dollar question isn't it ?
It should be in the META-INF directory of your application jar.

so something like this

ABCD.jar  
|__ META-INF    
    |__ jax-ws-catalog.xml  
    |__ wsdl  
        |__ SOAService.wsdl  

This way you don't even have to override the URL in your client that access the proxy. The WSDL is picked up from within your JAR, and you avoid having to have hard-coded filesystem paths in your code.

More info on jax-ws-catalog.xml http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html

Hope that helps