web-dev-qa-db-ja.com

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

問題は、提供されたファイルからWebサービスクライアントを構築する必要があることです。このファイルをローカルファイルシステムに保存しました。WSDLファイルを正しいファイルシステムフォルダーに保持している間は、すべて問題ありません。サーバーにデプロイするか、ファイルシステムフォルダーからWSDLを削除すると、プロキシがWSDLを見つけられず、エラーが発生します。ウェブを検索しましたが、次の投稿を見つけましたが、機能させることができませんでした:
JAX-WS jarからWSDLを読み込んでいます
http://www.Java.net/forum/topic/glassfish/metro-and-jaxb/client-jar-cant-find-local-wsdl-
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 \プロジェクト...\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アプリケーションのクラスパスにどのように入れるのですか?

81
user260192

最適なオプションは、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-catalog.xmlがない場合、jax-wsは実際に場所からWSDLをロードしようとします

http://localhost/wsdl/SOAService.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と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

役立つことを願っています

111
user507484

成功したもう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>

generatedコードで、これを見つけます:

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

}

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

17
mark

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

  1. Wsdlのローカルロケーション参照をwsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"として作成します
  2. Srcの直下にMETA-INFフォルダーを作成します。 META-INF/wsdlなどの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
Hemus7

Springを使用している人は、classpath-protocolを使用してクラスパスリソースを簡単に参照できます。したがって、wsdlLocationの場合、これは次のようになります。

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

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

1

exactここで説明したのと同じ問題がありました。上記の例に従って、WSDLファイルの場所を(Webサーバーの場合)変更するために何をしたとしても、サーバープロセスのソースツリーに埋め込まれた元の場所を引き続き参照していました。

MANYこれをデバッグしようとすると、例外が常にまったく同じ行からスローされていることに気付きました(私の場合は41)。最後に今朝、ソースコードをトレードパートナーに送信することで、少なくともコードがどのように見えるかを理解できるようにしましたが、独自のコードを作成することもできました。私のショックおよびhorrorに、クライアントソースツリー内で.Javaファイルと混合したクラスファイルの束を見つけました。なんて奇妙な!!これらはJAX-WSクライアントビルダーツールの副産物であると思われます。

これらの愚かな.classファイルを圧縮し、クライアントコードの完全なクリーンアップと再構築を実行すると、すべてが完全に機能します!!すごい!!

YMMV、アンドリュー

0
Piko