bpelx:exec
を使用したサービス・データ・オブジェクト(SDO)の埋込み方法、およびBPELプロセスと共有されるカスタム接続マネージャ・クラスの実装方法について説明します。
この章の内容は次のとおりです。
Oracle JDeveloperのBPELプロセスでのJava埋込みの使用
Oracle BPEL Process Managerとのクラスのカスタム実装の共有
Springコンポーネントを起動することもできます。詳細は、「Spring Frameworkを使用したSOAコンポジット・アプリケーションへの統合」を参照してください。
この項では、JavaコードのセクションをBPELプロセスに組み込む方法について説明します。この方法は、必要な関数を実行できるEnterprise JavaBeansのコードが存在していて、BPELで最初から始めずにその既存のコードを使用する場合に特に役立ちます。
JavaおよびJava EEコードをBPELプロセスに組み込む方法は数種類あります。
Simple Object Access Protocol (SOAP)サービスとしてラップする方法
bpelx:exec
タグを使用してBPELプロセスにJavaコード・スニペットを埋め込む方法
XML Facadeを使用してDOM操作を単純化する方法
bpelx:exec
組込みメソッドを使用する方法
サービス・インタフェースにラップされたJavaコードを使用する方法
Javaコードは、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
ファイルは、次のコードに示すbpelx:exec
タグを使用して、invokeSessionBean
Java Beanを埋め込みます。
<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>
この章の例では主に、bpelx:exec
拡張要素を使用してJavaコード・スニペットを埋め込む方法に重点を置いています。BPEL仕様のバージョン2.0をサポートするBPELプロジェクトの場合、構文が多少異なります。bpelx:exec
拡張要素とJavaコードは<extensionActivity>
要素にラップされます。次の例に詳細を示します。
<extensionActivity> <bpelx:exec language="java"> <![CDATA[ java code ]]> </bpelx:exec> </extensionActivity>
Java EmbeddingアクティビティをOracle BPELデザイナのBPELプロセスにドラッグすると、<extensionActivity>
要素とbpelx:exec
タグが自動的に追加されます。
次の例は、BPEL 2.0のimport構文を示しています。
<import location="class/package name" importType="http://schemas.oracle.com/bpel/extension/java"/>
注意:
BPEL 2.0のimport構文は、次の構文を使用するBPEL 1.1の場合とは異なります。
<bpelx:exec import="class/package name"/>
次の例は、BPELバージョン2.0をサポートするプロジェクトの2つのJava Embeddingアクティビティを含むBPELファイルを示しています。
<process name="Test" targetNamespace="http://samples.otn.com/bpel2.0/ch10.9" . . . . . . <import location="oracle.xml.parser.v2.XMLElement" importType="http://schemas.oracle.com/bpel/extension/java"/> . . . <sequence> . . . <extensionActivity> <bpelx:exec language="java"> XMLElement elem = (XMLElement) getVariableData("output", "payload"); elem.setTextContent("set by java exec"); </bpelx:exec> </extensionActivity> <extensionActivity> <bpelx:exec language="java"> <![CDATA[XMLElement elem = (XMLElement) getVariableData("output", "payload"); String t = elem.getTextContent(); elem.setTextContent(t + ", set by java exec 2");]]> </bpelx:exec> </extensionActivity> . . . </sequence> </process>
このアクティビティの使用方法の詳細は、「BPELプロセスでのJava埋込みの使用」を参照してください。
XML Facadeを使用してDOM操作を単純化できます。には、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
メソッドを使用します。次に例を示します。
<bpelx:exec name= ... <![CDATA ... Element element = ... (Element)getVariableData("input","payload","/loanApplication/"): //Create an XMLFacade for the Loan Application Document LoanApplication xmlLoanApp= LoanApplicationFactory.createFacade(element); ...
表14-1 に、スコープ変数、インスタンス・メタデータおよび監査証跡の読取りと更新に使用できる一連のbpelx:exec
組込みメソッドを示します。
表14-1 bpelx:exec用の組込みメソッド
メソッド名 | 説明 |
---|---|
|
JNDIアクセス |
|
各インスタンスに関連付けられている一意の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 Componentを作成する方法の詳細は、『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』を参照してください。
SOAコンポジット・アプリケーションを起動する方法の詳細は、『Oracle SOA SuiteおよびOracle Business Process Management 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
にクラスが使用されている場合は、Oracle Enterprise Manager Fusion Middleware ControlのシステムMBeanブラウザで、BpelcClasspathプロパティを使用してJARも追加する必要があります。
Oracle JDeveloperでは、bpelx:exec
アクティビティを追加して、コード・スニペットをダイアログにコピーできます。
注意:
カスタム・クラスの場合は、Oracle Enterprise Manager Fusion Middleware ControlのシステムMBeanブラウザで、BpelcClasspathプロパティに、埋込みJavaコードに必要なJARファイルを指定する必要があります。手順は、「カスタム・クラスおよびJARファイルの追加方法」を参照してください。これにより、JARファイルがBPELローダーのクラスパスに追加されます。複数のJARファイルを設定する場合は、UNIXではコロン(:
)、Windowsではセミコロン(;
)を使用して区切る必要があります。
Oracle JDeveloperのBPELプロセスでJava埋込みを使用する手順は、次のとおりです。
注意:
Java EmbeddingアクティビティにJavaコードを記述するかわりに、Javaコードを配置したJARファイルをクラスパスに設定し、Java Embeddingアクティビティ内からメソッドをコールすることもできます。
Java Embeddingアクティビティでthread.sleep()
を使用するBPELプロセスを作成してデプロイすると、実行スレッドがブロックされ、そのスレッドに関連付けられているトランザクションをコミットできません。その結果、待機の終了後にのみBPELインスタンスが表示されますが、これは想定されている動作です。
かわりに、waitアクティビティを使用します。このアクティビティを使用すると、入力時にリソースが解放され、進行中のトランザクションのコミットと、データ・ストアへのBPELインスタンス・データのハイドレーションが可能になります。
SDOコードは、bpelx:exec
タグを使用して.bpel
ファイルに埋め込むことができます。次の例の構文では、mytest.apps.SDOHelper
がSDOを変更するJavaクラスです。
</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>
次の例は、BPELファイルに埋め込まれているmodifySDO(o)
およびprint(o)
という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(); } }
Oracle BPEL Process Managerで使用されるクラスと同じ名前を持つカスタム接続マネージャ・クラスを実装する場合、カスタム・クラスがOracle BPEL Process Managerで使用されるクラスをオーバーライドしないことを確認する必要があります。
たとえば、次のことを想定します。
BPELプロジェクトで埋込みJavaを使用しています。
接続マネージャ・カスタム・クラスは、BPEL接続マネージャ・クラスをオーバーライドしています。
実行時にjava.lang.NoClassDefFoundError
が発生しています。