JAX-WSクライアント:ローカルWSDLにアクセスするための正しいパスは何ですか?


86

問題は、提供されたファイルからWebサービスクライアントを構築する必要があることです。このファイルをローカルファイルシステムに保存しました。WSDLファイルを正しいファイルシステムフォルダーに保存していますが、すべて問題ありません。サーバーにデプロイするか、ファイルシステムフォルダーからWSDLを削除すると、プロキシはWSDLを見つけることができず、エラーが発生します。Webを検索しましたが、次の投稿が見つかりましたが、機能させることができませんでした
。JAX-WSjarからのWSDLのロード
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サービスクライアントで更新する必要があるレガシーアプリケーションです)。以下はJAX-WSプロキシクラスです。

    @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:ファイル:/WEB-INF/wsdl/client/SOAService.wsdlでWSDLにアクセスできませんでした。次のエラーで失敗しました:\ WEB-INF \ wsdl \ client \ SOAService.wsdl(パスが見つかりません)

それでは、まず、プロキシクラスのwsdllocationを更新しますか?次に、WEB-INF / classes / com / ibm / eci / soaserviceのSOAServiceクラスに、\ WEB-INF \ wsdl \ client \ SOAService.wsdlでWSDLを検索するように指示するにはどうすればよいですか?

編集済み:この他のリンク(http://jianmingli.com/wp/?cat=41)を見つけました。これは、WSDLをクラスパスに入れることを示しています。私は質問するのが恥ずかしいです:どうすればそれをWebアプリケーションのクラスパスに入れることができますか?


回答:


117

最良のオプションは、jax-ws-catalog.xmlを使用することです。

ローカルのWSDLファイルをコンパイルするときは、WSDLの場所をオーバーライドして、次のように設定します。

http://localhost/wsdl/SOAService.wsdl

これはURIであり、URLではないことを心配しないでください。つまり、そのアドレスでWSDLを使用できるようにする必要はありません。
これを行うには、wsdllocationオプションをwsdl tojavaコンパイラーに渡します。

そうすることで、プロキシコードがから変更されます

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-catalog.xmlがないと、jax-wsは実際にその場所からWSDLを読み込もうとします。

http://localhost/wsdl/SOAService.wsdl
そのようなWSDLが利用できないため、失敗します。

ただし、jax-ws-catalog.xmlを使用すると、WSDL @にアクセスしようとするたびに、jax-wsをローカルにパッケージ化された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>

あなたがしていることは、いつでもからWSDLをロードする必要があることをjax-wsに伝えることです

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

お役に立てば幸いです


わかりました。Webアプリケーション内でこの方法で問題を解決することはできません。おそらく知識が不足しているために、wsdlをweb-inf内に配置しようとしましたが成功しませんでした。とにかくそれはjarで動作するので、最初から行う必要があるので、ラッパーライブラリを作成します。ご支援いただきありがとうございます

私はこの答えをうまく使うことができました、そしてこれは他の記事やチュートリアルが文書化する他のすべての選択肢よりも良い解決策であると信じています。だから私にとってこれはベストプラクティスです。なぜこのソリューションがJAX-WSトピックをカバーする他の公式記事やチュートリアルに文書化されていないのか疑問に思います。
Rahul Khimasia 2018

19

私たちが成功したもう1つのアプローチは、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の場所(または/ src、プロジェクトの設定方法によって異なります)ビルドプロセス中に、WSDLファイルとXSDファイルがこの場所にコピーされ、JARファイルにパッケージ化されます(上記のBhasakarで説明されているソリューションと同様)。

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

注:WSDLファイルがhttp URLではなく、インポートされたXSDへの相対参照を使用していることを確認してください。

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

}

おそらくこれも役立つかもしれません。これは、「カタログ」アプローチを使用しない別のアプローチです。


私はこのアプローチが好きです...しかし、なぜMETA-INFディレクトリなのですか?
icedDante 2014年

1
これには、デフォルトでJDK 6に付属している2.1ではなく、JAX-WS RI 2.2を使用する必要があることに注意してください
ᄂᄀ 2014年

4

詳細に説明し、私の問題を修正したBhaskarKarambelkarの回答に感謝します。しかし、私はまた、修正を急いでいる人のために、3つの簡単なステップで答えを言い換えたいと思います

  1. wsdlローカルロケーション参照を次のように作成します wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. srcのすぐ下にMETA-INFフォルダーを作成します。wsdlファイルをMETA-INFの下のフォルダー(META-INF / wsdlなど)に配置します。
  3. 以下のように、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ファイルをパッケージ化します。ローカルディレクトリへの参照はもうありません。すべてパッケージ化され、


4

ここでまだ解決策を探している人にとって、最も簡単な解決策は<wsdlLocation>、コードを変更せずにを使用することです。作業手順を以下に示します。

  1. wsdlを次のようなリソースディレクトリに配置します。 src/main/resource
  2. pomファイルに、以下のようにwsdlDirectoryとwsdlLocationの両方を追加します(wsdlLocationの先頭に/を見逃さないでください)。wsdlDirectoryはコードの生成に使用され、wsdlLocationは実行時に動的プロキシを作成するために使用されます。

    <wsdlDirectory>src/main/resources/mydir</wsdlDirectory>
    <wsdlLocation>/mydir/my.wsdl</wsdlLocation>
    
  3. 次に、Javaコード(引数なしのコンストラクターを使用)で:

    MyPort myPort = new MyPortService().getMyPort();
    
  4. 完全を期すために、ここでは、生成されたコードに流暢な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>
    


2

Springを使用している場合は、classpath-protocolを使用して任意のclasspath-resourceを簡単に参照できます。したがって、wsdlLocationの場合、これは次のようになります。

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

これは標準のJavaの動作ではないことに注意してください。参照:http//docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html


0

持っていた正確な本明細書に記載されているのと同じ問題を。上記の例に従って、WSDLファイルの場所(この場合はWebサーバーから)を変更するために何をしたとしても、サーバープロセスのソースツリーに埋め込まれた元の場所を参照していました。

MANYこれをデバッグしようとしている時間、私は例外はいつも(私の場合41)とまったく同じラインからスローされていたことに気づきました。ついに今朝、私はソースクライアントコードをトレードパートナーに送信することにしました。これにより、少なくともコードがどのように見えるかを理解できますが、おそらく独自のコードを作成できます。私に衝撃恐怖私は私のクライアントのソースツリー内の私の.javaファイルとで混合クラスファイルの束を発見しました。なんて奇妙なんだ!これらはJAX-WSクライアントビルダーツールの副産物だと思います。

これらのばかげた.classファイルをザッピングし、クライアントコードの完全なクリーンアップと再構築を実行すると、すべてが完全に機能します。やり直し!!

YMMV、アンドリュー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.