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

4ioopgfo  于 2022-11-24  发布在  其他
关注(0)|答案(8)|浏览(276)

问题是我需要从提供给我的文件构建一个Web服务客户端,我已经将这个文件存储在本地文件系统中,一切正常。当我将其部署到服务器或从文件系统文件夹中删除WSDL时,代理无法找到WSDL并引发错误。我搜索了Web,并发现“我发现以下职位,但我不能使它的工作:
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
我使用的是NetBeans 6.1(这是一个遗留的应用程序,我必须使用这个新的Web服务客户端进行更新)。

@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);
    }

}

下面是我使用代理的代码:

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;

   //classes\com\ibm\eci\soaservice
   //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将WSDL的副本放在 web-inf/wsdl/client/SOAService 中,因此我不想将它也添加到 META-INF 中。服务类位于 WEB-INF/classes/com/ibm/eci/soaservice/ 中,baseurl变量包含指向它的文件系统完整路径(c:\path\to\the\project...\soaservice)。上面的代码引发错误:
javax.xml.ws.WebServiceException:无法访问以下位置的WSDL:文件:/WEB-INF/wsdl/client/SOAService. wsdl。它失败,原因是:\WEB-INF\wsdl\客户端\SOA服务.wsdl(找不到路径)
那么,首先,我应该更新代理类的wsdllocation吗?然后,我如何告诉WEB-INF/classes/com/ibm/eci/soaservice中的SOAService类在\WEB-INF\wsdl\client\SOAService.wsdl中搜索WSDL?

EDITED:我找到了另一个链接-http://jianmingli.com/wp/?cat=41,它说要将WSDL放入类路径中。如何将其放入Web应用程序类路径中?

368yc8dk

368yc8dk1#

最好的选择是使用jax-ws-catalog.xml
编译本地WSDL文件时,重写WSDL位置并将其设置为类似于

http://localhost/wsdl/SOAService.wsdl

不要担心,这只是一个URI而不是URL,这意味着您不必在该地址上提供WSDL。
您可以通过将wsdllocation选项传递给wsdl to java编译器来完成此操作。
这样做会将您的代理代码从

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;
}

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;
}

请注意,URL建构函式中的file://已变更为http://。
如果没有jax-ws-catalog.xml,jax-ws将尝试从该位置加载WSDL

[http://localhost/wsdl/SOAService.wsdl](http://localhost/wsdl/SOAService.wsdl)

并失败,因为没有这样WSDL可用。
但是使用jax-ws-catalog.xml,您可以在jax-ws尝试访问WSDL @时将其重定向到本地打包的WSDL。

[http://localhost/wsdl/SOAService.wsdl](http://localhost/wsdl/SOAService.wsdl)

中的一个。
下面是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>

您所做的就是告诉jax-ws,当它需要从

[http://localhost/wsdl/SOAService.wsdl](http://localhost/wsdl/SOAService.wsdl)

,它应该从本地路径wsdl/SOAService. wsdl加载它。
现在,您应该将wsdl/SOAService.wsdl和jax-ws-catalog.xml放在哪里?这是一个价值百万美元的问题,不是吗?
它应该位于应用程序jar的META-INF目录中。
所以像这样的东西

ABCD.jar  
|__ META-INF    
    |__ 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
希望能有所帮助

o2gm4chl

o2gm4chl2#

我们成功采用的另一种方法是使用wsimport(来自Ant,作为Ant任务)生成WS客户端代理代码,并指定wsdlLocation属性。

<wsimport debug="true" keep="true" verbose="false" target="2.1" sourcedestdir="${generated.client}" wsdl="${src}${wsdl.file}" wsdlLocation="${wsdl.file}">
</wsimport>

由于我们是为包含多个WSDL的项目运行此脚本,因此该脚本将解析$(wsdl.file}值,该值被动态设置为相对于JavaSource位置的/META-INF/wsdl/YourWebServiceName.wsdl(或/src,具体取决于项目的设置方式)。在生成过程中,WSDL和XSD文件被复制到这个位置并打包到JAR文件中。(类似于Bhasakar在上面描述的解决方案)

MyApp.jar
|__META-INF
   |__wsdl
      |__YourWebServiceName.wsdl
      |__YourWebServiceName_schema1.xsd
      |__YourWebServiceName_schmea2.xsd

注意:请确保WSDL文件使用的是任何导入的XSD的相对引用,而不是http URL:

<types>
    <xsd:schema>
      <xsd:import namespace="http://valueobject.common.services.xyz.com/" schemaLocation="YourWebService_schema1.xsd"/>
    </xsd:schema>
    <xsd:schema>
      <xsd:import namespace="http://exceptions.util.xyz.com/" schemaLocation="YourWebService_schema2.xsd"/>
    </xsd:schema>
  </types>

生成的代码中,我们发现:

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2-b05-
 * Generated source version: 2.1
 * 
 */
@WebServiceClient(name = "YourService", targetNamespace = "http://test.webservice.services.xyz.com/", wsdlLocation = "/META-INF/wsdl/YourService.wsdl")
public class YourService_Service
    extends Service
{

    private final static URL YOURWEBSERVICE_WSDL_LOCATION;
    private final static WebServiceException YOURWEBSERVICE_EXCEPTION;
    private final static QName YOURWEBSERVICE_QNAME = new QName("http://test.webservice.services.xyz.com/", "YourService");

    static {
        YOURWEBSERVICE_WSDL_LOCATION = com.xyz.services.webservice.test.YourService_Service.class.getResource("/META-INF/wsdl/YourService.wsdl");
        WebServiceException e = null;
        if (YOURWEBSERVICE_WSDL_LOCATION == null) {
            e = new WebServiceException("Cannot find '/META-INF/wsdl/YourService.wsdl' wsdl. Place the resource correctly in the classpath.");
        }
        YOURWEBSERVICE_EXCEPTION = e;
    }

    public YourService_Service() {
        super(__getWsdlLocation(), YOURWEBSERVICE_QNAME);
    }

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

    /**
     * 
     * @return
     *     returns YourService
     */
    @WebEndpoint(name = "YourServicePort")
    public YourService getYourServicePort() {
        return super.getPort(new QName("http://test.webservice.services.xyz.com/", "YourServicePort"), YourService.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 YourService
     */
    @WebEndpoint(name = "YourServicePort")
    public YourService getYourServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("http://test.webservice.services.xyz.com/", "YourServicePort"), YourService.class, features);
    }

    private static URL __getWsdlLocation() {
        if (YOURWEBSERVICE_EXCEPTION!= null) {
            throw YOURWEBSERVICE_EXCEPTION;
        }
        return YOURWEBSERVICE_WSDL_LOCATION;
    }

}

也许这也会有帮助,这只是一种不同的方法,不使用“目录”方法。

kiayqfof

kiayqfof3#

对于那些还在这里寻求解决方案的人来说,最简单的解决方案是使用<wsdlLocation>,而不需要修改任何代码。工作步骤如下:
1.将wsdl放到资源目录中,如下所示:src/main/resource
1.在pom文件中,同时添加wsdlDirectory和wsdlLocation(不要在wsdlLocation的开头遗漏/),如下所示,而wsdlDirectory用于生成代码,wsdlLocation用于在运行时创建动态代理。

<wsdlDirectory>src/main/resources/mydir</wsdlDirectory>
<wsdlLocation>/mydir/my.wsdl</wsdlLocation>

1.然后在java代码中(使用无参数构造函数):

MyPort myPort = new MyPortService().getMyPort();

1.为了完整性,我在这里提供了完整的代码生成部分,在生成的代码中有流畅的api。

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>

<dependencies>
    <dependency>
        <groupId>org.jvnet.jaxb2_commons</groupId>
        <artifactId>jaxb2-fluent-api</artifactId>
        <version>3.0</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-tools</artifactId>
        <version>2.3.0</version>
    </dependency>
</dependencies>

<executions>
    <execution>
        <id>wsdl-to-java-generator</id>
        <goals>
            <goal>wsimport</goal>
        </goals>
        <configuration>
            <xjcArgs>
                <xjcArg>-Xfluent-api</xjcArg>
            </xjcArgs>
            <keep>true</keep>
            <wsdlDirectory>src/main/resources/package</wsdlDirectory>
            <wsdlLocation>/package/my.wsdl</wsdlLocation>
            <sourceDestDir>${project.build.directory}/generated-sources/annotations/jaxb</sourceDestDir>
            <packageName>full.package.here</packageName>
        </configuration>
    </execution>
</executions>
ny6fqffe

ny6fqffe4#

非常感谢Bhaskar Karambelkar的回答,它详细地解释了我的问题,并且解决了我的问题。但是我也想用三个简单的步骤来重新表达这个问题的答案,因为有人急于解决这个问题
1.将wsdl本地位置引用设置为wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
1.在src下创建一个META-INF文件夹。将wsdl文件放在META-INF下的文件夹中,例如META-INF/wsdl
1.在META-INF下创建一个xml文件jax-ws-catalog.xml,如下所示
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system"> <system systemId="http://localhost/wsdl/yourwsdlname.wsdl" uri="wsdl/yourwsdlname.wsdl" /> </catalog>
现在打包您的jar。不再引用本地目录,它全部打包并引用在

ejk8hzay

ejk8hzay5#

对于那些使用Spring的人来说,你可以简单地使用classpath-protocol引用任何classpath-resource。

<wsdlLocation>classpath:META-INF/webservice.wsdl</wsdlLocation>

请注意,这不是标准的Java行为。另请参阅:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html

x8goxv8g

x8goxv8g6#

无论我做了什么,按照上面的例子,改变我的WSDL文件的位置(在我们的例子中是从一个web服务器),它仍然引用嵌入在服务器进程的源树中的原始位置。
经过许多小时的调试,我注意到异常总是从同一行抛出(在我的例子41中)。最后,今天早上,我决定将我的源客户机代码发送给我们的贸易伙伴,这样他们至少可以了解代码的外观,但也许会构建自己的。令我震惊恐怖的是,我发现在我的客户端源代码树中,一堆类文件与我的.java文件混在一起。多么奇怪!!我怀疑这些是JAX的副产品-WS客户端构建器工具。
一旦我清除了那些愚蠢的.class文件,并对客户端代码进行了彻底的清理和重建,一切都工作得很完美!!Redonculous!!
安德鲁·伊姆夫

5lhxktic

5lhxktic7#

对于那些使用多个wsdl文件:

pom.xml文件

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.6</version>
<executions>
    <execution>
        <phase>generate-sources</phase>
        <goals>
            <goal>wsimport</goal>
        </goals>
        <configuration>
            <bindingDirectory>${basedir}/src/main/resources/jaxws</bindingDirectory>
            <bindingFiles>
                <bindingFile>binding.xjb</bindingFile>
            </bindingFiles>
            <wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
            <wsdlFiles>
                <wsdlFile>VN_PCSApplicationManagementService_v21.xml</wsdlFile>
                <wsdlFile>VN_PCSApplicationOfferManagementService_v7.xml</wsdlFile>
                <wsdlFile>VN_PCSOnlineDebtService_v2.xml</wsdlFile>
            </wsdlFiles>
        </configuration>
    </execution>
</executions>

创建服务客户端时:

@Bean
public ApplicationOfferManagementWSV7 getAppOfferWS() {
    String wsdlLocation = OnlineDebtWSv2Soap11QSService.class.getAnnotation(WebServiceClient.class).wsdlLocation().replaceFirst(".+wsdl/", "/wsdl/");
    URL url = this.getClass().getResource(wsdlLocation);
    ApplicationOfferManagementWSV7 applicationManagementWSV21 = new ApplicationOfferManagementWSV7Soap11QSService(url)
            .getApplicationOfferManagementWSV7Soap11QSPort();

    BindingProvider binding = (BindingProvider) applicationManagementWSV21;
    binding.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
    binding.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
    binding.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, offerEndpoint);

    return applicationManagementWSV21;
}
de90aj5v

de90aj5v8#

在我的示例中,我必须从.classpath文件中删除“src”条目的(不包括=“META-INF”),然后在Proxy类中将wsdl路径从/META-INF更改为META-INF

相关问题