18 ADF Webサービス・プロキシの使用
静的または動的アプローチを使用するプロキシを構築することにより、Oracle Sales Cloudおよび他のOracle SaaSアプリケーションのSOAP Webサービスと対話できます。これらのプロキシにより、SOAPによって公開されるJava API for XML Web Services (JAX-WS)オブジェクトがJavaクラスに変換され、これらのクラスがアプリケーションで使用できるようになります。各アプローチには長所と短所があります。
前提条件
このドキュメントに示される開発の例を実行する前に、以下の点に注意してください。
-
必ずJavaバージョン6 (SEまたはEE)を実行してください。
-
正しいバージョンのOracle JDeveloper IDEがインストールされていることを確認してください。
注意:
Oracle JDeveloper IDEを使用してOracle Cloudで開発するには、Oracle JDeveloper Studio Editionバージョン11.1.1.7.1を使用する必要があります。これより新しいバージョンを含む他のOracle JDeveloperのバージョンの場合、Oracle Cloudの統合機能をサポートしていません。Oracle JDeveloper Studio Edition 11.1.1.7.1をOracle Technology Network (http://www.oracle.com/technetwork/developer-tools/jdev/downloads/jdeveloer111171-2183166.html)からダウンロードしてください。
静的プロキシについて
設計時または開発時にWebサービス・クライアントをコンパイルおよびバインディングする場合、静的プロキシを使用します。これにより、サービスWSDLによって公開される(Javaクラスに便利にマップされる)データ・オブジェクト・タイプのスナップショットがIDEに抽出されます。
このインポートの一部として、IDEにより、使用可能なWebサービス・クライアント・プロキシ用の静的スタブが生成されます。生成された静的スタブ・クライアントのソース・コードは、個別の特定時点(つまり、インポートを実行した時点)における特定のサービス実装を表しています。
プロキシの専用プロジェクトの使用
Webサービス・プロキシを設計および実装する場合、Oracleでは、採り入れるべき特定のベスト・プラクティスに関するアドバイスを提供しています。
プロキシ(静的と動的の両方)は、独自の専用プロジェクトまたはJARファイル内に作成する必要があります。専用プロジェクトまたはJARファイルを使用することにより、必要に応じて、メイン・プロジェクトに影響を及ぼさずに静的プロキシを再生成できます。ウィザード・ベースのツール(Oracle JDeveloperに用意されているものなど)を使用するか、コマンド・ライン・ユーティリティを使用することにより、静的プロキシを生成できます。
同じソース(Oracle Sales Cloudなど)から複数のWebサービスを使用する場合、異なるWSDLから作成されるJavaおよびXMLアーティファクトに関するネームスペースの競合または重複が生じる可能性があります。Webサービスごとに異なるプロキシ・プロジェクトを使用すると、使用対象の各サービスを隔てる明確な境界を維持し、別の方法では一意のパッケージ構造を使用することによって回避される偶発的な重複や競合を防止しやすくなります。プロキシごとに専用のプロジェクトを使用することによって得られるもう1つのメリットは、分散開発環境で、複数の異なる開発チームが他のチームに干渉することなく、個々のプロキシ・クラスに対して同時に作業できる点です。
静的プロキシを使用したアプリケーションの構築(作業例)
この例では、JDeveloperに静的プロキシを実装することにより、JAX-WSオブジェクトを受け入れ、これらをJavaアプリケーションで使用します。
「終了」をクリックした後、プロキシが生成されます。プロキシを右クリックすると、いつでもプロパティを変更できます。また、プロキシをいつでも再生成できます。「Webサービス・プロキシの再生成」を参照してください。
プロキシ・プロジェクトのリストには、「Add your code to call the desired methods
」というテキストが記載されたファイル<port name>Client.java
(SalesPartyServiceSoapHttpPortClient.java
など)も表示されています。
注意:
プロキシが再生成される場合、クライアントの変更が上書きされるため、プロキシ・クライアント・クラスにカスタム・コードを埋め込むことはお薦めできません。また、生成されたプロキシに含まれる、操作に便利なパラメータが多すぎる場合もあります。かわりに、ファサードのJavaクラスを作成し、独自のメソッドを作成する必要があります。ファサードを使用すると、ペイロード全体を操作する必要なく、操作対象の入力フィールドと出力フィールドを制御できます。作成するメソッドは、実際のプロキシ・クラスの周辺のラッパーであり、ユースケースに最も関連のあるメソッドとパラメータのみが公開されています。
単純な静的プロキシ・ファサードの作成方法は、「Webサービス・プロキシのファサードの作成(SalesPartyサービスの例)」を参照してください。
Webサービス・プロキシのファサードの作成(SalesPartyサービスの例)
プロキシを操作する場合はたいてい、ファサードを作成して、操作するフィールドの数を制限する方が有益です。
https://
<<Your_Oracle_Sales_Cloud_URL>
/>/crmCommonSalesParties/SalesPartyService?WSDL
に定義されているSalesParty Webサービスを操作する場合、メッセージ・ペイロード全体を操作する必要はありません。作業対象を特定のフィールドのみに制限できます。これらのメソッドは、実際のプロキシ・クラスの周辺のラッパーであり、ユースケースに最も関連のあるメソッドとパラメータのみが公開されています。find
操作を使用する方法を示しています。- ワークスペース内で2番目のプロジェクトを作成します。この例では、「Facade」という名前を付けます。
- プロジェクトのプロパティを編集します。依存性セクションで、「ビルド出力」が選択されていることを確認します。
- SalesPartyFacadeという名前のJavaクラスを追加します。
- この高度な問合せサンプルにコードを追加します。
次の例では、findCriteria
を使用してXMLリクエスト・ペイロードを構築します。getSalesPartyList
メソッドは、ユーザーから入力としてstartsWith
のみを受け入れ、findCriteria
を構築し、サービスを実行し、販売パーティ・レコードのリストを返します。
// Copyright 2015, Oracle and/or its affiliates.All rights reserved package oracle.cloud.sampleapps.salesmerchtracker.model.proxy.facade; import com.sun.xml.ws.developer.WSBindingProvider; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.SalesPartyService; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.SalesPartyService_Service; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.ServiceException; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.ChildFindCriteria; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.Conjunction; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.FindCriteria; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.FindSalesParty; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.SalesParty; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.ViewCriteria; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.ViewCriteriaItem; import oracle.cloud.sampleapps.salesmerchtracker.model.proxy.types.ViewCriteriaRow; import weblogic.wsee.jws.jaxws.owsm.SecurityPolicyFeature; public class SalesPartyServiceFacade { private SalesPartyService_Service salesPartyService_Service; private List<SimplifiedSalesParty> SimplifiedSalesParties = new ArrayList<SimplifiedSalesParty>(); private long partyId; private String partyName; public List<SimplifiedSalesParty> getSalesPartyList(String startsWith) throws ServiceException { List<SalesParty> SalesParties; FindCriteria findCriteria = createFindCriteria(startsWith); // You can change your security policy here SecurityPolicyFeature[] securityFeatures = // new SecurityPolicyFeature[] { new SecurityPolicyFeature("oracle/wss_username_token_over_ssl_client_policy") }; new SecurityPolicyFeature[] { new SecurityPolicyFeature("oracle/wss_saml_token_bearer_over_ssl_client_policy") }; //salesPartyService_Service = new SalesPartyService_Service(); //to accomodate for new URL everytime, you will chanage the URL here salesPartyService_Service = new SalesPartyService_Service(); SalesPartyService salesPartyService = salesPartyService_Service.getSalesPartyServiceSoapHttpPort(securityFeatures); // SalesPartyService salesPartyService = salesPartyService_Service.getSalesPartyServiceSoapHttpPort(); // If using wss_username_token_over_ssl_client_policy uncomment the three lines below to provide the username/password // WSBindingProvider wsbp = (WSBindingProvider)salesPartyService; // wsbp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY,"your user name"); // wsbp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,"your password"); FindSalesParty fSalesParty= new FindSalesParty(); fSalesParty.setFindCriteria(findCriteria); try{ SalesParties = salesPartyService.findSalesParty(fSalesParty).getResult(); if (!SalesParties.isEmpty()) { for (SalesParty sp: SalesParties) { partyName = sp.getPartyName().getValue(); partyId = sp.getPartyId(); SimplifiedSalesParty s1 = new SimplifiedSalesParty(partyId, partyName); SimplifiedSalesParties.add(s1); } } } catch (Exception e) { e.printStackTrace(); } return SimplifiedSalesParties; } private static FindCriteria createFindCriteria(String startsWith) { FindCriteria findCriteria = new FindCriteria(); ChildFindCriteria childFindCriteria = new ChildFindCriteria(); findCriteria.setFetchStart(0); findCriteria.setFetchSize(10); ViewCriteria filter = new ViewCriteria(); ViewCriteriaRow group1 = new ViewCriteriaRow(); ViewCriteriaItem item1 = new ViewCriteriaItem(); item1.setUpperCaseCompare(true); item1.setAttribute("PartyName"); item1.setOperator("STARTSWITH"); item1.getValue().add(startsWith); ViewCriteriaItem item2 = new ViewCriteriaItem(); item2.setAttribute("PartyType"); item2.setOperator("="); item2.getValue().add("ORGANIZATION"); group1.getItem().add(item1); group1.getItem().add(item2); group1.setConjunction(Conjunction.AND); filter.getGroup().add(group1); findCriteria.setFilter(filter); findCriteria.getFindAttribute().add("PartyId"); findCriteria.getFindAttribute().add("PartyName"); // findCriteria.getFindAttribute().add("OrganizationParty"); /* childFindCriteria.setChildAttrName("OrganizationParty"); childFindCriteria.getFindAttribute().add("Address1"); childFindCriteria.getFindAttribute().add("City"); childFindCriteria.getFindAttribute().add("Country"); findCriteria.getChildFindCriteria().add(childFindCriteria); */ return findCriteria; } }
このプロキシはSAMLクライアント・ポリシーを使用するよう構成されているため、このファサードはSAMLポリシーを自動的に使用します。ただし、(テストのため、または関連付けられていないサービスを操作する場合など) SAMLポリシーのかわりにユーザー名トークンを使用する場合、上記のように、SAMLポリシー行をコメント・アウトし、ユーザー名トークン・ポリシー行のコメント・アウトを解除します。
ユーザー名トークン・ポリシーが機能するには、ファサードにユーザー名とパスワードを指定する必要があります。これを行うには、上記のコメント付きコードに示すように、WSBindingProvider
を使用して、USERNAME_PROPERTY
とPASSWORD_PROPERTY
をそれぞれ使用してユーザー名とパスワードをオーバーライドできます。
IDE内でユーザー名トークン・ポリシーをテストする場合、単純なテスト・クラスを使用してこのファサードをテストできます。次に例を示します。
String filter = "Art"; SalesPartyFacade spf = new SalesPartyFacade(); List<SalesParty> salesparties = spf.getSalesPartyList(filter); for (SalesParty sp: salesparties) {System.out.print("Party Name = " + sp.getPartyName().getValue()+"\n"); System.out.print("Address1 = " + sp.getOrganizationParty().get(0).getAddress1().getValue()+"\n"); System.out.print("City = " + sp.getOrganizationParty().get(0).getCity().getValue()+"\n"); System.out.print("Country = " + sp.getOrganizationParty().get(0).getCountry().getValue()+"\n"); System.out.println("\n\n"); }プロキシのセキュリティ・ポリシーの詳細は、「Oracle Sales Cloud SOAP Webサービスのクライアントのセキュリティ・ポリシーの選択」を参照してください。
Webサービス・プロキシの再生成
動的プロキシについて
通常、動的プロキシは、開発がより複雑ですが、静的プロキシと比較して一定のメリットを備えています。
動的プロキシの場合、開発(つまり、clientgen
の使用)時にWSDLコンテンツはコンパイルされません。かわりに、実行時に、アプリケーションがWSDLペイロードを動的に取得および解釈してから、検出されたデータ構造を操作するコールの構築に進みます。標準オブジェクトに追加されたカスタム・オブジェクトまたはカスタム属性の作成を通じてサーバー側のインタフェースが変更される場合、動的プロキシ・クライアントはより強固になります。
Java仕様によると、動的プロキシ・クラスは、クラスのインスタンス上のインタフェースの1つを介したメソッドの起動が一意のインスタンスを介して別のオブジェクトにエンコードおよびディスパッチされるように、実行時に指定されるインタフェースのリストを実装するクラスです。このため、動的プロキシ・クラスを使用すると、コンパイル時ツールなどを使用してプロキシ・クラスを事前に生成する必要なく、インタフェースのリスト用のタイプセーフのプロキシ・オブジェクトを作成できます。動的プロキシ・クラスのインスタンス上のメソッドの起動は、インスタンスの起動ハンドラ内の単一のメソッドにディスパッチされ、これらは、起動されたメソッド、および引数を含むオブジェクト・タイプの配列を識別するjava.lang.reflect.Methodオブジェクトを使用してエンコードされます。動的プロキシ・クラスは、インタフェースAPIを表すオブジェクトにおける起動のタイプセーフの反映型ディスパッチを提供する必要がある、アプリケーションまたはライブラリにとって有効です。
動的プロキシは、設計および実装がより複雑になる可能性があります。ただし、これらは、接続管理、パフォーマンス監視、トランザクション管理などの複雑な要件に対応し、高度な制御を行うことができます。
動的プロキシの作成
動的プロキシは、javax.xml.ws.Service
オブジェクトとともにService.create
メソッドを使用して実装できます。