2

2 つの別個のアプリケーション サーバーに 2 つの Java EE アプリケーションがあります。それらの 1 つには、動作中の EJB がすでに含まれています。JAX-WS Web サービスを使用して、他のアプリケーションからこの EJB と通信できるようにしたいと考えています (通信は、異なるアプリケーション サーバーと異なるサーバー バージョン間で機能する必要があるため、リモート EJB 呼び出しはオプションではありません)。サーバー API をクライアント アプリケーションに公開することは問題ありません。サーバー側は非常に明確で、 @Webservice アノテーションを追加するとうまくいくようです。しかし、クライアントを構築するための最良の方法は何だろうと思います.wsdlからクライアントスタブを生成したくはありません(私の場合、コンテナによってejbコードから生成されました)、これらの生成されたすべてのクラスをパックしますクライアントの耳に - しかし、これが @WebServiceRef アノテーションを利用できる唯一の方法のようです。

javax.xml.ws.Service (service=Service.create() や service.getPort() など) の静的メソッドを使用して自分で動的プロキシを作成する代替手段は、仕様では推奨されておらず、「コンテナプロバイダーは、これらのメソッドを使用して作成されたマネージド サービス インスタンスをサポートする必要はありません。」しかし、それはまさにsthです。私が使いたい:

アプリケーション サーバーによって管理される動的プロキシをコードに挿入する方法はありますか? または、生成されたクライアント スタブ クラスを使用して、マネージド Web サービス クライアント インスタンスを取得する唯一の方法はありますか?

4

1 に答える 1

2

JAX-WS 2.2 仕様の第 4 章: クライアント API を参照してください。

1. 静的クライアントの生成

JAX-WS を操作する最も簡単な方法です。Web サービスの観点から見ると、WSDL はインターフェースであり、接続プロパティでもあります。物理的に操作しないことを選択した場合でも、意味のある SOAP 呼び出しを行うには、論理的な意味でそれを知る必要があります。

JAX-WS 仕様からの注意: SOAP 1.1/HTTP バインディングを使用するエンドポイントは、そのコントラクトを WSDL 1.1 ドキュメントとしてサフィックス?WSDLまたは?wsdl

2. 動的クライアント プログラミング

アプリケーション サーバーによって管理される動的プロキシをコードに挿入する方法はありますか?

このアプローチには、JAX-WS API に対する動的プログラミングが含まれ、WSDL を使用して、または使用せずに Web サービスに接続します。動的プロキシをどこからともなく「注入」する方法はありません。SEI のポート URL を使用して構成および構成する必要があります。WSDL ドキュメントは、このような構成情報を格納する標準的な場所ですが、これを避けてプログラムで情報を挿入することもできます。

  • 2A) WSDL を使用した動的プログラミング:

     javax.xml.ws.Service service = Service.create(
         new URL("http://example.org/stocks.wsdl"),
         new QName("http://example.org/stocks", "StockQuoteService"));
     com.example.StockQuoteProvider proxy = service.getPort(portName,
     com.example.StockQuoteProvider.class)
     javax.xml.ws.BindingProvider bp = (javax.xml.ws.BindingProvider)proxy;
     Map<String,Object> context = bp.getRequestContext();
     context.setProperty("javax.xml.ws.session.maintain", Boolean.TRUE);
     proxy.getLastTradePrice("ACME");
    

    (1) に対する利点:アプリのデプロイ後に WSDL ドキュメントを動的に動的に変更できます。ただし、そのような変更がクライアントへの Java インターフェースに影響を与えない場合に限ります。

    つまり、あなたにはほとんどメリットがありません。WSDL は静的です。クライアントに動的ルックアップを指示することもできますが、これは手動でAND を<service endpoint URL>?wsdl構成する必要があることを意味し、クライアント ロジックに影響を与えずに SEI/WSDL で変更できるものはほとんどありません。<service endpoint URL>

  • 2B) WSDL を使用しない動的プログラミング:

    String endpointUrl = ...;           
    QName serviceName = new QName("http://example.org/wssample/echo/", "EchoService");
    QName portName = new QName("http://example.org/wssample/echo/", "EchoServicePort");
    
    /** Create a service and add at least one port to it. **/ 
    Service service = Service.create(serviceName);
    service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
    
    /** Create a Dispatch instance from a service.**/ 
    Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, 
    SOAPMessage.class, Service.Mode.MESSAGE);
    
    /** Create SOAPMessage request. **/
    // compose a request message
    MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
    
    // Create a message.  This example works with the SOAPPART.
    SOAPMessage request = mf.createMessage();
    SOAPPart part = request.getSOAPPart();
    
    // Obtain the SOAPEnvelope and header and body elements.
    SOAPEnvelope env = part.getEnvelope();
    SOAPHeader header = env.getHeader();
    SOAPBody body = env.getBody();
    
    // Construct the message payload.
    SOAPElement operation = body.addChildElement("invoke", "ns1",
    "http://com/ibm/was/wssample/echo/");
    SOAPElement value = operation.addChildElement("arg0");
    value.addTextNode("ping");
    request.saveChanges();
    
    /** Invoke the service endpoint. **/
    SOAPMessage response = dispatch.invoke(request);
    

    利点(実際にはそうではありません):最終的に上記と同じ動作を実行させることができます。

    短所:複雑なプログラミング。非標準の構成 (WSDL の外部)。ハードコーディング設定を避ける必要があります。インターフェイスの変更に弱い。サーバーとクライアントの間で設定を手動で同期する - 何かを省略しやすく、デバッグが非常に難しい。

答え:

(1)に戻ります。WSDL からクライアント スタブを生成します。これをインターフェイス コントラクトとして使用します。適切に設計し、変更しないようにする必要があります。

次に、節約した時間を実際の問題の解決に費やします... ;) ;)

于 2013-05-08T05:53:43.137 に答える