BPEL WLIユーザーのためのOracle SOA Suite基礎講座

Oracle WebLogic Integrationのカスタム・コントロールとOracle SOA SuiteのSpringコンポーネントの比較

Clemens Utschig-UtschigおよびSimone Geib著

WLIユーザーのためのOracle SOA Suite基礎講座シリーズの今回の記事では、Oracle WebLogic Integrationのカスタム・コントロール機能とOracle SOA Suiteにおける相当機能であるSpringコンポーネントを比較します。

2009年12月公開

関連するダウンロード・リンク
 Oracle SOA Suite

はじめに

カスタムJavaコードは、Oracle WebLogic Integration(Oracle WLI)のあらゆるビジネス・プロセス(JPD)にとって不可欠な要素です。 ほとんどのOracle SOA SuiteコンポーネントはXMLを主体としていますが、完全なJavaサポートと強力なIOCコンテナ機能を提供するため、Springコンポーネントのサポートが追加されています。 SpringコンポーネントはSOA Suite 11g PS1のTechnology Previewから利用できるようになり、SOA Suite 11g PS2で正式に提供される予定です。

この記事では、どのようにしてSOA SuiteのSpringコンポーネントを使用して、Oracle WLIのカスタム・コントロールと同じ機能を実現するかについて説明します。 ここでは、ログ出力コンポーネントの例を使用して、Springコンポーネントの実装およびデプロイ方法の詳しい手順を説明します。

この記事の対象読者は、SOA Suite 11gの使用を望むOracle WLIの開発者およびアーキテクトです。

Oracle WLIのカスタム・コントロール

Oracle WLIでは、Javaコード(リソースまたはアプリケーション機能へのアクセスなど)をカプセル化するためにカスタム・コントロールが使用されます。カスタム・コントロールは、コントロール・メソッドをプロセスにドラッグ・アンド・ドロップする方法で、WLIプロセス(JPD)に組み込まれます。

ユーザーは、システム・コントロールと同じフレームワークに基づく独自のカスタム・コントロールを構築できます。 ユーザーはカスタム・コントロールをゼロから設計し、インタフェースおよび実装を設計し、必要に応じてその他のコントロールを追加します。

SOA SuiteのSpringコンポーネント

Oracle SOA Suiteでは、XMLについて案じることなく特定のビジネス・ロジックをJavaで実装するために、Spring Javaコンポーネントが使用されます。

Spring( SpringSourceを参照)は、構成を介した依存性の注入を実現するIOCコンテナ(Inversion of Control、Martin Fowlerによる『 Inversion of Control Containers and the Dependency Injection』を参照)です。 依存性のないJavaBeanを公開するとわずかにオーバーヘッドがかかりますが、必要な外部コンポーネントが増えれば増えるほど、使用は簡単になります。

Oracle SOA Suiteのおもなコンポーネントはデータ交換形式としてXMLを使用していますが、Springコンポーネントの目標は、シームレスなJava統合に向けたJavaコンポーネントおよびスキルの再利用にあります。 一度実装されたコンポーネントは、続いてサービスとして公開され、BPELなどの別のコンポーネントから起動されます。

次に示す簡単な手順で、Javaクラスをコンポジット内で使用できるようになります。

a)Javaインタフェースを作成し、パブリック・メソッドとして提供するメソッドを公開します。

public interface IInternalPartnerSupplier
{
    /**
     * 注文品目リストの価格の取得
     * @パラメータ pOrderItems 注文品目のリスト
     * @戻り値 価格
     */
    public double getPriceForOrderItemList(List<Orderitem> pOrderItems)
        throws InternalSupplierException;
}

b)このインタフェースの実装を作成します。

public class InternalSupplierMediator implements IInternalPartnerSupplier
{
    /**
     * 注文品目リストの価格の取得と、
     * 注入された参照を介した見積りの書込み
     * @パラメータ pOrderItems 注文品目のリスト
     * @戻り値 注文品目リストの価格
     */
    @Override
    public double getPriceForOrderItemList(List<Orderitem> pOrderItems)
        throws InternalSupplierException
    {
        // just return a default price - or do something else ..
        return 0.0;
    }
}

c)Springコンポーネント(Springコンテキストを含む)とBean(ステップbで作成したクラスを表す)を作成します。 名前を付け(参照できるように)、クラスを宣言します。

<!--
     コンテキスト内のSpring Bean、宣言、実装に使用したクラス 
         およびスコープ(シングルトンまたはBeanFactory.getBean()ごとに新規インスタンスを生成)
-->

<bean id="InternalPartnerSupplierMediator"
        class="com.otn.sample.fod.soa.internalsupplier.InternalSupplierMediator"
        scope="prototype">
</beans>

d)サービスとしてBeanを公開するため、<sca:service>を作成します。 別のコンポーネントの参照から利用できるようにするには、コンポーネントに宣言済みのサービスが含まれる必要があります。

<!-- 
    公開されたBean 'InternalPartnerSupplierMediator' 
    タイプがJavaインタフェースを表していることに注意 
-->

<sca:service name="IInternalPartnerSupplier"
    target="InternalPartnerSupplierMediator"
    type="com.otn.sample.fod.soa.internalsupplier.IInternalPartnerSupplier"/>

サービスを含むSpringコンポーネントを作成したら、その他のコンポーネントに接続します。図1を参照してください。

図1
図1

ユースケース例: 簡単なログ出力コンポーネント

非常に一般的なOracle WLIカスタム・コントロールの例として、プロセスの特定箇所で使用されるカスタム・ログ出力があります。 この例では、プロセス名、インスタンスID、ログ・メッセージを記録します。

Oracle WLIを使用したユースケースの実装

Oracle WLIでカスタム・コントロールを作成および使用する方法について、読者が理解しているという前提に立っているため、このユースケースについてここでは詳しく説明しません。 ここで焦点となるのは、SOA SuiteにおけるSpringコンポーネントです。

Oracle WLIのログ出力コントロールは、次の2つのJavaファイルで構成されています。

インタフェース・クラスであるLoggerControl.java

package sample.oracle.otn.soaessentials.javainteg.controls;
/**
 * 簡単なログ出力インタフェース
 * @作者 simone.geib@oracle.com
 * @作者 clemens.utschig@oracle.com
 */
import org.apache.beehive.controls.api.bean.ControlInterface;

@ControlInterface
public interface LoggerControl {

    /**
     * logメソッドの実装
     * @パラメータ pProcessName 開始プロセスの名前
     * @パラメータ pInstanceId インスタンスID
     * @パラメータ pMessage 標準出力に書き出すメッセージ
     * @参照 sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log
     */
    public void log (String pProcessName, String pInstanceId, String pMessage);

}

実装クラスであるLoggerControlImpl.java

package sample.oracle.otn.soaessentials.javainteg.controls;
import org.apache.beehive.controls.api.bean.ControlImplementation;
import java.io.Serializable;
/**
 * 簡単なログ出力コンポーネントの実装
 * @参照 sample.oracle.otn.soaessentials.javainteg.ILoggerComponent
 * @作者 simone.geib@oracle.com
 * @作者 clemens.utschig@oracle.com
 */
@ControlImplementation
public class LoggerControlImpl implements LoggerControl, Serializable {
 private static final long serialVersionUID = 1L;
 
    /**
     * logメソッドの実装
     * @パラメータ pProcessName 開始プロセスの名前
     * @パラメータ pInstanceId インスタンスID
     * @パラメータ pMessage 標準出力に書き出すメッセージ
     * @参照 sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log
     */
    public void log(String pProcessName, String pInstanceId, String pMessage)
    {  
       StringBuffer logBuffer = new StringBuffer ();
       logBuffer.append("[").append(pProcessName).append("] [Instance: ").
        append(pInstanceId).append("] ").append(pMessage);
 
       System.out.println(logBuffer.toString());
    }
}

図2に、JPD Data Paletteに表示されたログ出力コントロールを示します。

図2

図3に、JPDで使用されたログ出力コントロールを示します。

図3

SOA Suiteを使用したユースケースの実装


注:
SOA Suite 11g PS1でプレビュー機能を使用するには、はじめにプレビュー・モードを有効化する必要があります。 $JDeveloper_HOME/integration/seed/soa/configurationへ移動し、soa-config.xmlを開きます。 ${SPRING_COMPONENT_NAME_L}を探し、前後にあるXMLコメント(<!-- -->)を外します。 ファイルを保存し、Oracle JDeveloperを再起動します。

このセクションでは、Oracle BPEL Process ManagerやOracle Mediatorなどの別のコンポーネントから使用できる、簡単なログ出力コンポーネントを作成します。このコンポーネントは、開始インスタンスIDを含むメッセージを標準出力に書き出します。

Springコンポーネントの作成

はじめにOracle JDeveloperで新規アプリケーションを作成し、"SOASuiteWLIEssentials"という名前を付けます。

図4

"JavaIntegration"という名前の新規プロジェクトを作成します。

図5

Finish」をクリックします。

"sample.oracle.otn.soaessentials.javainteg"という名前のJavaパッケージを作成します(いくつかのステップが必要です)。

図6

"sample.oracle.otn.soaessentials.javainteg"パッケージ内に、"ILoggerComponent"という名前の新規Javaインタフェースを作成します。

図7
図8

インタフェースに"log"という名前の新規メソッドを追加し、パラメータとして開始コンポーネント、インスタンスID、メッセージを指定します。

package sample.oracle.otn.soaessentials.javainteg;

/**
 * 簡単なログ出力インタフェース
 * @作者 simone.geib@oracle.com
 * @作者 clemens.utschig@oracle.com
 */
public interface ILoggerComponent
{
   
    /**
     * 開始コンポーネント、そのインスタンスID、およびメッセージを含むメッセージの書出し
     * 
     * @パラメータ pComponentName このログ・メッセージを送信するコンポーネントの名前
     * @パラメータ pInstanceId コンポーネント・インスタンスのインスタンスID 
     * @パラメータ pMessage 書き出すメッセージ
     */
    public void log (String pComponentName,
                     String pInstanceId, String pMessage);
}
図9

"ILoggerComponent"インタフェースから、Javaクラス("LoggerComponentImpl")を作成します。

図10

クラスに名前を付けたら、プラス記号をクリックして、クラスのベースとなるインタフェースを探します。

図11
図12
図13

次に、ログ出力コンポーネントの実装を示します。

package sample.oracle.otn.soaessentials.javainteg.impl;

import sample.oracle.otn.soaessentials.javainteg.ILoggerComponent;

package sample.oracle.otn.soaessentials.javainteg.impl;

import sample.oracle.otn.soaessentials.javainteg.ILoggerComponent;

/**
 * 簡単なログ出力コンポーネントの実装
 * @参照 sample.oracle.otn.soaessentials.javainteg.ILoggerComponent
 * @作者 simone.geib@oracle.com
 * @作者 clemens.utschig@oracle.com
 */
public class LoggerComponentImpl implements ILoggerComponent
{

    /**
     * logメソッドの実装
     * @パラメータ pComponentName 開始コンポーネントの名前
     * @パラメータ pInstanceId インスタンスID
     * @パラメータ pMessage 標準出力に書き出すメッセージ
     * @参照 sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log
     */
    @Override
    public void log(String pComponentName, String pInstanceId,
                    String pMessage)
    {
        StringBuffer logBuffer = new StringBuffer ();
        logBuffer.append("[").append(pComponentName).append("] [Instance: ").
            append(pInstanceId).append("] ").append(pMessage);
        
        System.out.println(logBuffer.toString());
    }
}

次に、新しいSpringコンテキスト("logger-context.xml")を作成し、Spring Bean("logger")を定義し、このBeanをサービス("logService")として公開します。

図14
図15

コンポーネント・パレットから「 bean」をドラッグし、

図16

Springコンテキストのキャンバスにドロップします。

図17

"logger"という名前を付け、実装を指すクラス属性を宣言します。

図18

次に、BeanをSCAサービスとして公開します。

コンポーネント・パレットのドロップダウン・リストを「" Spring 2.5 SCA"」に変更し、「" Service"」をキャンバスにドラッグします。

図19

サービス名として"logService"を指定し、 ターゲットとして"logger"Beanを指定します。

図20

最後に、タイプとしてLoggerComponentクラス("sample.oracle.otn.soaessentials.javainteg.ILoggerComponent")のインタフェースを選択します。

図21
図22

完成したSpringコンテキストは、次のようになります。

<?xml version="1.0" encoding="windows-1252" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca">
  <!-- logger Beanをサービスとして公開 -->
  <sca:service name="logService" target="logger"
               type="sample.oracle.otn.soaessentials.javainteg.ILoggerComponent"/>
  <!-- logger Beanの宣言 -->
  <bean name="logger"
    class="sample.oracle.otn.soaessentials.javainteg.impl.LoggerComponentImpl"/>
</beans>

"JavaIntegration"という名前の新規コンポジットを作成します。

図23

"create with BPEL Process"オプションを使用し、プロセス名として"BPELProcessWithLogger"を指定します。 その他は、デフォルト設定のままにします。

図24
図25

図26に、新たに作成されたBPELプロセスを示します。ReceiveアクティビティとCallbackアクティビティが含まれています。

図26

コンポジット・ビューに戻り、「" Spring Context"」をコンポジット・キャンバスにドラッグします。 "logger-context"という名前を指定し、先ほど作成したSpringコンテキストを選択します。

図27
図28

Javaクラスをコンパイルして、BPELプロセス内で使用できるWSDL定義を作成します。

図29

SpringコンポーネントのサービスをBPELプロセスの上にドラッグします。 プロセス内に、WSDLとパートナー・リンクが作成されます。

図30
図31

次に、コンポーネント・パレットからBPELキャンバスへ、「 Invoke」アクティビティをドラッグします。 これは、先ほど作成したログ・サービスのlog()メソッドを起動するために使用されます。

図32

Invoke」をログ出力サービスのパートナー・リンクへ接続します。

図33

入力変数と出力変数を作成します。 これらの変数は、コンポーネント名、コンポーネント・インスタンスID、およびログ・メッセージを割り当てるために後で使用されます。

図34

完成したInvokeアクティビティは次の図35のようになります。

図35

作成した変数の値を生成するには、パレットから「 Assign」アクティビティをドラッグし、BPELプロセスへドロップします。

図36

次の3つのステップで、入力変数値の生成に必要なコピー・ルールを作成します。

Assign」アクティビティをダブルクリックしてコピー操作を追加し、最初のパラメータにコンポーネント名を割り当てます。

図37

もう1つコピー操作を追加し、2番目のパラメータにプロセス・インスタンスIDを割り当てます。

図38

3つ目のコピー操作を追加し、3番目のパラメータにメッセージを割り当てます。

図39

Assignアクティビティに3つのコピー・ルールがすべて含まれていることを確認します。

図40

すべてのコピー・ルールが作成されたら、プロセスは図41のようになります。Receiveから始まり、ログ・メッセージ値のAssign、ログ・サービスのlogメソッドのInvoke、最後にInvoke経由で実装されたCallbackと続きます。

図41

SOAコンポジットのデプロイ

次のステップでは、Oracle JDeveloperを使用してコンポジットをデプロイします。 SOAサーバーが実行中であることを確認してください。

Oracle JDeveloperおよびスクリプト・ツールを使用したSOA複合アプリケーションのデプロイと、開発、テスト、本番環境間でのSOA複合アプリケーションの移動を可能にする構成プランの作成については、 43章SOAコンポジット・アプリケーションのデプロイを参照してください。

また、Oracle Enterprise Manager Fusion Middleware Control Consoleを使用してSOA複合アプリケーションをデプロイ、再デプロイ、アンデプロイする方法についても、 第5章SOAコンポジット・アプリケーションのデプロイを参照してください。

JDeveloper内でコンポジットをデプロイすると、ログは次のようになります。

[06:15:55 AM] ----  Deployment started.  ----
[06:15:55 AM] Target platform is  (Weblogic 10.3).
[06:15:55 AM] Running dependency analysis...
[06:15:55 AM] Building...
[06:16:11 AM] Deploying profile...
[06:16:11 AM] Updating revision id for the SOA Project 'JavaIntegration.jpr' to '1.0'..
[06:16:12 AM] Wrote Archive Module to C:\JDeveloper\mywork\SDOStuff\JavaIntegration\
              deploy\sca_JavaIntegration_rev1.0.jar
[06:16:12 AM] Deploying sca_JavaIntegration_rev1.0.jar to soa_server1 
              [sta00251.us.oracle.com:8001] 
[06:16:12 AM] Processing sar=/C:/JDeveloper/mywork/SDOStuff/JavaIntegration/deploy/
              sca_JavaIntegration_rev1.0.jar
[06:16:12 AM] Adding sar file - C:\JDeveloper\mywork\SDOStuff\JavaIntegration\deploy\
              sca_JavaIntegration_rev1.0.jar
[06:16:12 AM] Preparing to send HTTP request for deployment
[06:16:12 AM] Creating HTTP connection to host:sta00251.us.oracle.com, port:8001
[06:16:13 AM] Sending internal deployment descriptor
[06:16:13 AM] Sending archive - sca_JavaIntegration_rev1.0.jar
[06:16:41 AM] Received HTTP response from the server, response code=200
[06:16:41 AM] Successfully deployed archive sca_JavaIntegration_rev1.0.jar to 
              soa_server1 [sta00251.us.oracle.com:8001] 
[06:16:41 AM] Elapsed time for deployment:  46 seconds
[06:16:41 AM] ----  Deployment finished.  ----

BPELプロセスのテスト

デプロイに成功したら、Oracle Enterprise Manager Fusion Middleware Control Console(Enterprise Manager)からコンポジット・サービスを開始します。

Enterprise Managerにログインするには、Internet Explorer 7、Mozilla Firefox 2.0.0.2またはFirefox 3.0.xを使用して、http://host_name:port/emへアクセスします ( ここで、host_nameはEnterprise Managerがインストールされているホストの名前であり、portはインストール時に動的に設定された番号です)。

weblogic/passwordと入力し、「 Login」をクリックします。

(詳しくは、 Oracle SOA Suiteの管理の開始を参照してください。)

図42

EMダッシュボードでJavaIntegrationコンポジットを探し、これをクリックします。 コンポジットのホームページが表示されます。

図43

ページが表示されたら、コンポジット・サービスをテストできます。

図44

入力として"clemens"と入力したら、「 Test Web Service」をクリックします。

図45

インスタンスが作成されたら「 Launch Message Flow Trace」をクリックします。コンポジット・インスタンスが表示されます。

図46

BPELインスタンス・フローを確認すると、Springコンポーネントに渡された実際のメッセージを参照できます。

図47

SOA Suiteをホストしているサーバーの標準出力を確認します。 次のようなメッセージが表示されます。

==> CubeEngine deploy BPELProcessWithLogger took 4 seconds
INFO: DeploymentEventPublisher.invoke Publishing deploy event for 
default/JavaIntegration!1.0*c39dc7a2-5031-424e-9ae0-aeec949769b3
[BPELProcessWithLogger] [Instance: 20009] Got input: clemens

プロジェクト一式のダウンロード

Javaソースやコンポジットを含むプロジェクト一式を格納したZIPファイルをダウンロードできます。 wli-soaessentials-JavaIntegration-source.zip.

JDeveloperでプロジェクトを開くには、新規アプリケーションを作成してからプロジェクト・ファイル(JavaIntegration.jpr)を開きます。

重要なポイントと推奨事項

  • コンポジットまたはXMLベースの環境に対して、シームレスにJavaを組み込むことができます。
  • 宣言し、後から接続することで、複数のJava Beanをサービスとして公開することや、外部参照を注入することができます。
  • POJOを使用するため、XML関連やSpringコンポーネント内部でのコーディングは必要ありません。

再利用可能なエンティティおよびBeanを作成するには、Springコンテキストをコンポジットなしでパッケージ化して、それ自体をWebLogic Serverにデプロイし、EJBまたはWebサービスとしてBeanを公開します。

こうすることで、再利用可能なJavaコンポーネントを非常に簡単に作成できます。これらのJavaコンポーネントは、Oracle WLIのJPDからカスタム・コントロールを使用するのと同様に、BPELプロセスまたはメディエータ・コンポーネント内部から使用できます。

参考資料


Clemens Utschig-Utschig Clemens Utschig-Utschigは、 Oracle CorporationのSr. Principal Product Manager兼SOA Architectです。 SOA Manifestoの立案者の1人であるClemensは、Thomas Erlの著書SOA Design Patternsへも寄稿しています。また、SOAの改善と成功に向けた情報共有に取り組むSOAアーキテクトによる国際的企業間グループであるMasons of SOAの一員でもあります。
[ Oracle Mix / Blog / LinkedIn]
Simone Geib Simone Geibは、Oracle CorporationのSOAテクノロジー担当Product Managerです。 オラクルがBEA Systemsを買収する前は、同社のWebLogic Integration担当Product Managerでした。 SimoneはSOAの戦略および実装に関して、さまざまな業種や地理の枠を越えた幅広い経験を有しています。
[ Oracle Mix / Blog / LinkedIn]