BPELプロセスには、Javaコード・セクションを埋め込むことができます。
この章の内容は次のとおりです。
この章では、BPELプロセスにJavaコード・セクションを埋め込む方法について説明します。これは、必要な機能を実行できるJavaコードがすでに存在し、最初から始めるのではなくその既存のコードを使用する場合に特に役立ちます。
Javaコードは、次のいずれかの方法で組み込むことができます。
JavaアプリケーションにBPEL対応のインタフェースがある場合、Web Services Inspection Language(WSIF)バインディングを使用するか、JavaコードをSOAPサービスとしてラップしてBPELプロセスで使用します。
WSIFバインディングは、BPELプロセスでJavaコードを使用するための最も一般的な方法です。この方法を使用すると、BPELプロセスはネイティブJ2EEプロトコル(ローカル・メソッド起動またはRemote Method Invocation(RMI))を介してEnterprise JavaBeanを起動できます。WSIFバインディングを使用して、WSDLファイル・セクションはJavaとXMLの間で通信するためのプロトコルを定義します。この方法は、Javaのトランザクション性を維持し、かつパフォーマンスを低下させません。また、既存のJavaアプリケーションにWSIFバインディングを追加するほうが、Oracle BPEL Process Managerで最初から始めるよりも、必要な時間が短くなります。ただし、WSIFバインディングには次の短所があります。
SOAPサービスに比べてサポート対象ツールが少ない。
各アプリケーション・サーバーが特定のバインディングを必要とするため、相互運用性の点で劣る。
現在、バインディングは手作業で記述する必要があります。
Oracle BPEL Process ManagerのJavaバインディング実装は、Apache WSIFパッケージのJavaバインディングに基づいています。 Javaバインディングにより、BPELプロセスはユーザー定義Javaクラスを起動できます。
BPELプロセス内部で使用されるデータは、すべてW3C DOM要素です。 したがって、BPELプロセスとユーザー定義Javaクラス間でデータ・マーシャリングを実行する必要があります。 Oracle BPEL Process ManagerのJavaバインディング実装は、現在、次のデータ型を使用するJavaクラスをサポートしています。
XML単純型
Oracle BPEL Process ManagerのFacadeデータ型を使用するXML複合型
DOM要素
ほとんどのXML単純型は、Java型との間でマップできます。 データ・マッピングは、format拡張機能を使用してWSDLファイル内で定義できます。 たとえば、Javaメソッドの定義は次のようになります。
public float getQuote (String symbol) throws Exception;
format:typeMap定義は、次のようになります。
<binding name="JavaBinding" type="tns:StockquotePT"> <java:binding/> <format:typeMapping encoding="Java" style="Java"> <format:typeMap typeName="xsd:string" formatType="java.lang.String" /> <format:typeMap typeName="xsd:float" formatType="java.lang.float" /> </format:typeMapping> <operation name="getQuote"> <java:operation methodName="getQuote"/> <input/> <output/> </operation> </binding>
|
関連項目: XML単純型を使用するサンプルは、SOA_Oracle_Home¥samples¥demos¥IBMSamples¥simpleを参照してください。
|
XML Facadeは、XML DOM要素の最上部にJavaBeanに似たインタフェースを提供するOracle BPEL Process Managerのテクノロジです。 XMLスキーマの場合、Oracle BPEL Process Managerのschemacツールを使用してFacadeクラスを生成できます。 次の例では、各クラスでメソッドにXML Facadeクラスが使用されています。
public CommentsType addComment(CommentsType payload, CommentType comment)
throws JavaBindingException;
WSDL Javaバインディングの定義は次のとおりです。
<binding name="JavaBinding" type="tns:HelperService">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="tns:commentType"
formatType="com.otn.services.CommentType" />
<format:typeMap typeName="tns:commentsType"
formatType="com.otn.services.CommentsType" />
</format:typeMapping>
<operation name="addComment">
<java:operation methodName="addComment"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
<operation name="testFault">
<java:operation methodName="testFault"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
</binding>
JavaのCommentType型とCommentsType型はXML Facadeクラスです。
Oracle BPEL Process Managerでは、XML DOM要素が内部的に使用されます。 Javaバインディング・クラスでXML DOM要素が使用される場合、データ・マーシャリングは不要です。 たとえば、次の例ではaddComment()メソッドが定義されています。
public Element addComment(Element payload, Element comment)
throws JavaBindingException;
WSDLファイルのJavaバインディングの定義は次のとおりです。
<binding name="JavaBinding2" type="tns:HelperService2">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
format:typeMap typeName="tns:commentType"
formatType="org.w3c.dom.Element"/>
<format:typeMap typeName="tns:commentsType"
formatType="org.w3c.dom.Element"/>
</format:typeMapping>
<operation name="addComment">
<java:operation methodName="addComment"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
<operation name="testFault">
<java:operation methodName="testFault"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
</binding>
DOM要素タイプを使用するJavaクラスを使用すると、JavaバインディングですべてのXMLデータ型をサポートできます。
JavaバインディングはWebサービスとしてフォルトをスローできます。 フォルトは、WSDLファイル内でWebサービスとして定義できます。
<message name="CommentFaultMessage"> <part name="payload" type="tns:commentType"/> </message> <portType name="HelperService2"> <operation name="testFault"> <input message="tns:TestFaultRequestMessage"/> <output message="tns:TestFaultResponseMessage"/> <fault name="CommentException" message="tns:CommentFaultMessage" /> </operation> </portType> <binding name="JavaBinding2" type="tns:HelperService2"> ... <operation name="testFault"> <java:operation methodName="testFault"/> <input/> <output/> <fault name="CommentException"/> </operation> </binding>
Webサービス・フォルトをスローするには、事前定義済のフォルト・タイプcom.collaxa.cube.ws.wsif.providers.java.JavaBindingExceptionまたはサブクラスをスローするようにJavaクラスで宣言する必要があります。
次の例のJavaファイルには、この例外をスローするファンクションがあります。
public CommentType testFault(CommentType payload)
throws JavaBindingException
{
System.out.println("testFault : " + payload);
if (payload != null) {
JavaBindingException ex = new JavaBindingException();
ex.setFaultName("CommentException");
ex.setPart("payload", payload);
System.out.println(" throwing exception " + ex);
throw ex; } else {
return payload;
}
}
別のJavaファイルには、次のように類似のファンクションがあります。
public Element testFault(Element payload)
throws JavaBindingException
{
System.out.println("testFault2: " + payload);
if (payload != null) {
JavaBindingException ex = new JavaBindingException();
ex.setFaultName("CommentException");
ex.setPart("payload", payload);
System.out.println(" throwing exception " + ex);
throw ex;
} else {
return payload;
}
}
このような例外がJavaバインディング・クラスからスローされると、BPEL WSIFレイヤーにより次のようにBPELソースで捕捉できるWebサービス例外に変換されます。
<variables>
......
<variable name="fault" messageType="services:CommentFaultMessage"/>
</variables>
......
<faultHandlers>
<catch faultName="services:CommentException" faultVariable="fault">
<assign>
<copy>
<from expression="string('CommentException')"/>
<to variable="output" part="payload"
query="/types:comments/types:item[1]/types:message"/>
</copy>
</assign>
</catch>
<catchAll>
<empty/>
</catchAll>
</faultHandlers>
|
関連項目:
|
WSIFバインディングのかわりに、JavaコードをSOAPサービスとしてラップできます。WSIFバインディングの場合と同様に、この方法では、JavaアプリケーションにBPEL対応のインタフェースが必要です。SOAPサービスとしてラップされたJavaアプリケーションはその他のWebサービスと同じように表示されるため、多くの様々なアプリケーションで使用できます。また、SOAPラッパーの記述に使用できるツールもあります。
ただし、SOAPサービスとしてラップされたJavaアプリケーションには次の短所があります。
JavaコードとSOAPラッパーの間で相互作用が絶えずマップされるので、パフォーマンスが低下します。
相互運用性に欠けます。つまり操作が複数あるときに、すべて実行するかあるいはまったく実行しないという方法(ある銀行口座の借方に記入し、別の口座で貸方に記入するなど、両方のトランザクションを完了するか、どちらも完了しないかのいずれかなど)を使用できません。
BPELプロセスでJavaを利用する別の方法として、Java BPEL exec拡張機能bpelx:execを使用して、コードを直接BPELプロセスに埋め込む方法があります。この方法の利点は、パフォーマンスに優れていることとトランザクション性が維持されることです。ただし、組み込めるのは非常に小さなコード・セグメントのみです。これより大きいコード・セグメントを組み込む場合、またはプロジェクトで作成中のすべてのBPELプロセスでJavaコードのルック・アンド・フィールを同じにする必要がある場合は、WSIFバインディングを使用するか、SOAPサービスとしてラップすることを検討してください。
BPELタグbpelx:execを使用すると、BPELプロセス内にJavaコードSnippetを埋め込むことができます。サーバーはbpelx:execアクティビティ内に含まれるJavaコードSnippetをそのJava Transaction API(JTA)トランザクション・コンテキストで実行します。BPELタグbpelx:execは、Java例外をBPELフォルトに変換してBPELプロセスに追加します。Java Snippetは、コールするSession BeanおよびEntity BeanにそのJTAトランザクションを伝播できます。
たとえば、SessionBeanSample.bpelファイルは次のbpelx:execタグを使用してinvokeSessionBean JavaBeanを埋め込みます。
<bpelx:exec name="invokeSessionBean" language="java" version="1.4">
<![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'"
+ ". Please make sure 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>
XML Facadeを使用すると、DOM操作を単純化できます。Oracle BPEL Process Managerには、Facadeという軽量Java Architecture for XML Binding(JAXB)のようなJavaオブジェクト・モデルがXMLに対して用意されています。XML Facadeは、スキーマを持つXML文書またはXML要素に対して、JavaBeanのようなフロント・エンドを提供します。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);
...
Facadeクラスを生成するには、schemacツール(Oracle BPEL Process Managerに付属)を使用します。schemacツールは次の場所にあります。
SOA_Oracle_Home¥bpel¥bin
schemacを使用するには、次のようなコマンドを実行します。これにより、FacadeがWSDLファイルまたはXSDファイルから生成されます。
C:¥BPEL_project_dir¥> schemac *.wsdl /*.xsd
schemacを実行すると、HelperService.javaサービス用のsrcフォルダと、生成されたJavaクラス用のcomフォルダが作成されます。JavaバインディングにおけるFacadeクラスの使用方法を示すサンプルが次のディレクトリに用意されています。
SOA_Oracle_Home¥bpel¥samples¥tutorials¥702.Bindings¥JavaBinding
Facadeの生成時に、schemacは次のファイルを使用します。
build.xmlを使用して、schemacはFacadeクラスのソースを生成します。
schemacツールは、Javaバインディング・プロバイダ・クラスHelperService.javaを作成します。このクラスは、702.Bindingsの例に含まれていて、702.Bindings¥JavaBinding¥src¥com¥otn¥servicesにあります。このクラスにはメソッドが1つあり、このメソッドではFacadeクラスCommentsTypeおよびCommentTypeを使用します。
public CommentsType addComment(CommentsType payload, CommentType comment)
XML型を対応するFacadeクラスにマップするために、Javaバインディング・サービスがHelperService.wsdlファイルに定義されています。Javaバインディングのformat:typeMappingセクションを参照してください。
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="tns:commentType"
formatType="com.otn.services.CommentType" />
<format:typeMap typeName="tns:commentsType"
formatType="com.otn.services.CommentsType" />
</format:typeMapping>
表9-1に、スコープ変数、インスタンス・メタデータおよび監査証跡の読取りと更新に使用できる一連のbpelx:exec組込みメソッドを示します。
表9-1 bpelx:exec用の組込みメソッド
| メソッド名 | 説明 |
|---|---|
Object lookup( String name )
|
JNDIアクセス |
Locator getLocator( )
|
BPEL Process Managerのロケータ |
long getInstanceId( )
|
各インスタンスに関連付けられた一意のID |
String setTitle( String title ) / String getTitle()
|
このインスタンスのタイトル |
String setStatus( String status ) / String getStatus()
|
このインスタンスのステータス |
void setIndex( int i, String value ) / String getIndex( int i )
|
検索は6つの索引を使用可能 |
void setPriority( int priority ) / int getPriority()
|
優先度 |
void setCreator( String creator ) / String getCreator()
|
このインスタンスの開始ユーザー |
void setCustomKey( String customKey ) / String getCustomKey()
|
2番目の主キー |
void setMetadata( String metadata ) / String getMetadata ()
|
リストを生成するためのメタデータ |
String getPreference( String key )
|
bpel.xmlで定義されたアクセス・プリファレンス
|
void addAuditTrailEntry(String message, Object detail)
|
監査証跡へのエントリの追加 |
void addAuditTrailEntry(Throwable t)
|
スーツケースに格納されたファイルへのアクセス |
Object getVariableData(String name) throws BPELFault
|
スコープ内に格納された変数へのアクセスおよび更新 |
Object getVariableData(String name, String partOrQuery) throws BPELFault
|
|
Object getVariableData(String name, String part, String query)
|
|
void setVariableData(String name, Object value)
|
|
void setVariableData(String name, String part, Object value)
|
|
void setVariableData(String name, String part, String query, Object value)
|
|
Oracle JDeveloperを使用すると、次のように、bpelx:execアクティビティを追加して、コードSnippetをダイアログ・ボックスにコピーできます。
コンポーネント・パレットのJava Embeddingアクティビティ(コーヒー・カップのアイコン)をドラッグ・アンド・ドロップします。
Java Embeddingアクティビティをダブルクリックして「Java埋込み」ウィンドウを表示します。
Java Embeddingアクティビティに名前を付けます。
「コードSnippet」フィールドにJavaコードを入力(またはカット&ペースト)します。
たとえば、「bpelx:execタグによるBPELプロセスへのJavaコードSnippetの埋込み」で説明したbpel:execコード例を次のようにカット&ペーストします。
この章では、次のいずれかの技法により、BPELプロセスにJavaコード・セクションを埋め込む方法について説明しました。
JavaアプリケーションにBPEL対応のインタフェースがある場合、WSIFバインディングを使用するか、JavaコードをSOAPサービスにラップします。
bpelx:execを使用してインライン・コードSnippetを含めることで、Javaコードを直接埋め込みます。このSnippetは、Oracle BPEL Serverのトランザクション・コンテキスト内で実行されます。この方法を使用すると、そのトランザクションを自分のSession BeanおよびEntity Beanに伝播できます。一連の組込みメソッドを使用すると、bpelx:exec Snippetは、変数の読込みと更新、インスタンス・メタデータの変更、フォルトのスローができます。DOM操作を単純化するには、XML Facadeを使用します。