この章では、JavaコードのセクションをSOAコンポジット・アプリケーションのBPELプロセス・サービス・コンポーネントに組み込む方法について説明します。
項目は次のとおりです。
この項では、JavaコードのセクションをBPELプロセスに組み込む方法について説明します。 この方法は、必要な関数を実行できるEnterprise JavaBeansのJavaコードが存在していて、BPELで最初から始めずにその既存のコードを使用する場合に特に役立ちます。
JavaおよびJava EEコードをBPELプロセスに組み込む方法は数種類あります。
Simple Object Access Protocol(SOAP)サービスとしてラップする方法
bpelx:execタグを使用してBPELプロセスにJavaコード・スニペットを埋め込む方法
XML Facadeを使用してDOM操作を単純化する方法
bpelx:exec組込みメソッドを使用する方法
サービス・インタフェースにラップされたJavaコードを使用する方法
Javaコードは、Simple Object Access Protocol(SOAP)サービスとしてラップできます。この方法では、JavaアプリケーションにBPEL互換のインタフェースが必要です。SOAPサービスとしてラップされたJavaアプリケーションは、他のWebサービスと同じように表示され、多様なアプリケーションで使用できます。また、SOAPラッパーの記述に使用できるツールもあります。
SOAPサービスとしてラップされたJavaアプリケーションには、次の短所があります。
JavaとSOAP間での変換の性質により、パフォーマンスが低下する場合があります。
SOAPはトランザクションを本質的にはサポートしていないため、この方法ではアトミック・トランザクション性が失われます。つまり、複数の操作を、すべて実行するか、まったく実行しないという機能(ある銀行口座で借方記入し、別の口座で貸方記入するなど、両方のトランザクションを完了するか、どちらも完了しないかのどちらかなど)がありません。
Javaコード・スニペットは、Java BPEL exec拡張要素bpelx:execを使用してBPELプロセスに直接埋め込むことができます。この方法の利点は、パフォーマンスに優れていることとトランザクション性が維持されることです。 小さいコード・セグメントのみを組み込むことをお薦めします。 BPELは、ビジネス・ロジックを実装から切り離します。 プロセスの多数のJavaコードを削除すると、この切離しを維持できなくなります。 Java埋込みは、ビジネス・コードではなく、短いユーティリティ系の操作を対象としています。 ビジネス・ロジックは別の場所に配置し、配置したロジックをBPELからコールします。
サーバーは、bpelx:execアクティビティ内のJavaコード・スニペットをそのJava Transaction API(JTA)トランザクション・コンテキスト内で実行します。このBPELタグbpelx:execは、Java例外をBPELフォルトに変換し、BPELプロセスに追加します。Javaスニペットは、コールするセッションBeanとエンティティBeanに、そのJTAトランザクションを伝播できます。
たとえば、SessionBeanSample.bpelファイルは、例13-1に示すbpelx:execタグを使用して、invokeSessionBean Java Beanを埋め込みます。
例13-1 bpelx:execタグ
 <bpelx:exec name="invokeSessionBean" language="java" version="1.5">
    <![CDATA[
        try {
            Object homeObj = lookup("ejb/session/CreditRating");
            Class cls = Class.forName(
                "com.otn.samples.sessionbean.CreditRatingServiceHome");
            CreditRatingServiceHome ratingHome = (CreditRatingServiceHome)
                        PortableRemoteObject.narrow(homeObj,cls);
            if (ratingHome == null) {
                addAuditTrailEntry("Failed to lookup 'ejb.session.CreditRating'"
                                   + ". Ensure that the bean has been"
                                   + " successfully deployed");
                return;
            }
            CreditRatingService ratingService = ratingHome.create();
            // Retrieve ssn from scope
            Element ssn =
                (Element)getVariableData("input","payload","/ssn");
            int rating = ratingService.getRating( ssn.getNodeValue() );
            addAuditTrailEntry("Rating is: " + rating);
            setVariableData("output", "payload",
                "/tns:rating", new Integer(rating));
        } catch (NamingException ne) {
            addAuditTrailEntry(ne);
        } catch (ClassNotFoundException cnfe) {
            addAuditTrailEntry(cnfe);
        } catch (CreateException ce) {
            addAuditTrailEntry(ce);
        } catch (RemoteException re) {
            addAuditTrailEntry(re);
        }
    ]]>
    </bpelx:exec>
 DOM操作は、XML Facadeを使用して単純化できます。Oracle BPEL Process Managerには、XMLの他に、Java Architecture for XML Binding(JAXB)に類似した軽量のJavaオブジェクト・モデル(Facadeと呼ばれます)が用意されています。XML Facadeは、スキーマを備えたXML文書またはXML要素に対して、Java Beanのようなフロント・エンドを提供します。Facadeクラスを使用すると、Javaプログラム内でXML文書またはXML要素を簡単に操作できます。
XML Facadeを追加するには、.bpelファイルのbpelx:exec文内でcreateFacadeメソッドを使用します。 図13-2に例を示します。
表13-1に、スコープ変数、インスタンス・メタデータおよび監査証跡の読取りと更新に使用できる一連のbpelx:exec組込みメソッドを示します。
表13-1 bpelx:exec用の組込みメソッド
| メソッド名 | 説明 | 
|---|---|
| 
 
  | 
 JNDIアクセス  | 
| 
 
  | 
 Oracle BPEL Process Managerのロケータ  | 
| 
 
  | 
 各インスタンスに関連付けられている一意のID  | 
| 
 
  | 
 このインスタンスのタイトル  | 
| 
 
  | 
 このインスタンスのステータス  | 
| 
 
  | 
 コンポジット・インスタンス・タイトルの設定  | 
| 
 
  | 
 検索には6つの索引を使用可能  | 
| 
 
  | 
 優先度  | 
| 
 
  | 
 このインスタンスの開始ユーザー  | 
| 
 
  | 
 2番目の主キー  | 
| 
 
  | 
 リストを生成するためのメタデータ  | 
| 
 
  | 
 アクセス・プリファレンス  | 
| 
 
  | 
 監査証跡へのエントリの追加  | 
| 
 
  | 
 スーツケースに格納されたファイルへのアクセス  | 
| 
 
  | 
 スコープ内に格納された変数へのアクセスおよび更新  | 
| 
 
  | 
 変数のアクセスおよび更新  | 
| 
 
  | 
 変数のアクセスおよび更新  | 
| 
 
  | 
 変数データの設定  | 
| 
 
  | 
 変数データの設定  | 
| 
 
  | 
 変数データの設定  | 
すべてのアプリケーションがサービス・インタフェースを公開するわけではありません。ビジネス・プロセスでカスタムJavaコードが必要なシナリオもあります。このシナリオの場合は、次の操作を実行できます。
カスタムJavaコードを記述します。
コードを埋め込むサービス・インタフェースを作成します。
SOAP経由で、JavaコードをWebサービスとして起動します。
たとえば、SOAP参照バインディング・コンポーネントでサービス・インタフェースを起動するSOAコンポジット・アプリケーションに、BPELプロセス・サービス・コンポーネントを作成すると仮定します。この例の場合、使用されるサービス・インタフェースは、Oracle Application Development Framework(ADF)Business Componentです。
このシナリオの高レベルな手順を次に示します。
サービス・インタフェースにラップされたJavaコードを使用する手順は、次のとおりです。
Oracle JDeveloperでOracle ADF Business Componentサービスを作成します。
この操作により、このサービスに対するWSDLファイルとXSDファイルが生成されます。
BPELプロセス・サービス・コンポーネントを含むSOAアプリケーションを作成します。そのBPELプロセス・サービス・コンポーネントはコンポジット・サービスとして公開されている必要があります。これにより、BPELプロセスがインバウンドSOAPサービス・バインディング・コンポーネントに自動的に接続されます。
Oracle ADF Business ComponentサービスWSDLをSOAコンポジット・アプリケーションにインポートします。
Oracle ADF Business Componentサービス・インタフェースにバインディングするWebサービスを作成します。
次のタスクを実行するBPELプロセスを設計します。
パートナ・リンク参照をコンポジット参照バインディング・コンポーネントに接続(ワイヤ)します。この参照は、Webサービス・バインディングを使用して、Oracle ADF Business Componentサービスをリモートでデプロイできるようにします。
SOAアプリケーションをデプロイします。
Oracle Enterprise Manager Fusion Middleware Controlコンソールの「Webサービスのテスト」ページから、このSOAアプリケーションを起動します。
Oracle ADF Business Componentsの作成方法の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』を参照してください。
SOAコンポジット・アプリケーションの起動方法の詳細は、『Oracle Fusion Middleware Oracle SOA Suite管理者ガイド』を参照してください。
SOAコンポジット・アプリケーションには、カスタム・クラスおよびJARファイルを追加できます。 拡張クラスおよびJARをSOAコンポジット・アプリケーションに追加するためのSOA拡張ライブラリは、$ORACLE_HOME/soa/modules/oracle.soa.ext_11.1.1ディレクトリにあります。 Oracle JDeveloperでは、カスタム・クラスおよびJARはapplication_name/project/sca-inf/libディレクトリに追加されます。
bpelx:execにクラスが使用されている場合は、bpel-config.xmlのbpelcClasspathにもJARを追加する必要があります。 また、JARはSOAコンポジット・アプリケーションによってロードされていることも必要です。
カスタム・クラスを追加する手順は、次のとおりです。
classesディレクトリにクラスをコピーします。
Oracle WebLogic Serverを再起動します。
カスタムJARを追加する手順は、次のとおりです。
このディレクトリまたはそのサブディレクトリにJARファイルをコピーします。
antを実行します。
Oracle WebLogic Serverを再起動します。
Oracle JDeveloperでは、bpelx:execアクティビティを追加して、コード・スニペットをダイアログ・ボックスにコピーできます。
| 
 注意: カスタム・クラスの場合は、埋込みJavaコードに必要なJARファイルをORACLE_HOME/domains/user_domain_name/config/soa-infra/configuration/bpel-config.xmlファイルのbpelcClasspath変数に設定する必要があります。 これにより、JARファイルがBPELローダーのクラスパスに追加されます。 複数のJARファイルを設定する場合は、UNIXではコロン(:)、Windowsではセミコロン(;)を使用して区切る必要があります。 | 
Oracle JDeveloperのBPELプロセスでJava埋込みを使用する手順は、次のとおりです。
「コンポーネント・パレット」から、デザイナにJava Embeddingアクティビティをドラッグします。
Java Embeddingアクティビティをダブルクリックして「Java Embedding」ダイアログを表示します。
「名前」フィールドに、名前を入力します。
「コード・スニペット」フィールドに、Javaコードを入力(またはカット・アンド・ペースト)します。
| 
 注意: Java EmbeddingアクティビティにJavaコードを記述するかわりに、Javaコードを配置したJARファイルをクラスパスに設定し、Java Embeddingアクティビティ内からメソッドをコールすることもできます。 | 
サービス・データ・オブジェクト(SDO)コードは、bpelx:execタグを使用して.bpelファイルに埋め込むことができます。 例13-3の構文では、mytest.apps.SDOHelperがSDOを変更するJavaクラスです。
例13-3 bpelx:execタグを使用したSDOオブジェクトの埋込み
</bpelx:exec> <bpelx:exec name="ModifyInternalSDO" version="1.5" language="java"> <![CDATA[try{ Object o = getVariableData("VarSDO"); Object out = getVariableData("ExtSDO"); System.out.println("BPEL:Modify VarSDO... " + o + " ExtSDO: " + out); mytest.apps.SDOHelper.print(o); mytest.apps.SDOHelper.print(out); mytest.apps.SDOHelper.modifySDO(o); System.out.println("BPEL:After Modify VarSDO... " + o + " ExtSDO: " + out); mytest.apps.SDOHelper.print(o); mytest.apps.SDOHelper.print(out); }catch(Exception e) { e.printStackTrace(); }]]> </bpelx:exec>
例13-4に、BPELファイルに埋め込まれているmodifySDO(o)およびprint(o)というJavaクラスの例を示します。
例13-4 Javaクラス
public static  void modifySDO(Object o){
       if(o instanceof commonj.sdo.DataObject)
       {
           ((DataObject)o).getChangeSummary().beginLogging();
          SDOType type = (SDOType)((DataObject)o).getType();
          HelperContext hCtx = type.getHelperContext();
           List<DataObject>  lines =
            (List<DataObject>)((DataObject)o).get("line");
           for (DataObject  line: lines) {
               line.set("eligibilityStatus", "Y");
           }
       } else {
           System.out.println("SDOHelper.modifySDO(): " + o + " is not a
           DataObject!");
       }
   }
. . .
. . .
   public static  void print(Object o)    {
       try{
         if(o instanceof commonj.sdo.DataObject)
        {
           DataObject sdo = (commonj.sdo.DataObject)o;
            SDOType type = (SDOType) sdo.getType();
            HelperContext hCtx = type.getHelperContext();
            System.out.println(hCtx.getXMLHelper().save(sdo, type.getURI(),
             type.getName()));
         } else {
             System.out.println("SDOHelper.print(): Not a sdo " + o);
         }
       }catch(Exception e)
       {
       e.printStackTrace();
       }          }