Apache Geronimo および POJO を使用して SOA フレームワークを構築する

POJO プログラミング、GBean、および Geronimo カーネルを使用してタスクを単純化する

ライブラリーおよびフレームワークで強制されるアプリケーション・プログラミング・インターフェース (API) の制約を意識せずにソフトウェアを開発できるということは、魅力的なことです。この魅力により、数多くの人が Plain Old Java™ Object (POJO) プログラミングのパラダイムを受け入れるようになりました。これは、余分なインターフェースやサード・パーティーの API を使用せずに、Java プラットフォームでソフトウェアを開発できなければならないという考え方です。ApacheGeronimo フレームワークは、高度なアプリケーションおよびサービスを構築するために、POJO 開発用の強固なインフラストラクチャーを提供します。POJO の戦術を使用してサービス指向の開発を成功させるために使用できる Geronimo フレームワークのコンポーネントと技法の一部を探索しましょう。

J. Jeffrey Hanson, Chief Architect, eReinsure.com, Inc.

Jeff HansonJeff Hansonはソフトウェア業界で20年以上の経験を持っており、シニア・エンジニアとしてOpenDocのMicrosoft® Windows®への移植プロジェクトや、中心アーキテクトとしてNovellのRoute 66フレームワークなどに従事してきました。現在はeReinsure.com, Inc.の中心アーキテクトであり、Java EEベースの再保険システム用のWebサービス・フレームワークやプラットフォームの構築を行っています。彼は数多くの記事や本を執筆しており、その一部には『.NET versus J2EE Web Services』や『A Comparison of Approaches, Pro JMX』、『Java Management Extensions, and Web Services Business Strategies and Architectures』などがあります。



2006年 7月 11日

サービス指向アーキテクチャー (SOA) およびサービス指向プログラミングは、ビジネス・ロジックをモジュラー・サービスとしてカプセル化するソフトウェア・エンジニアリングのスタイルを示す用語です。これらのサービスは、サービス・プロバイダーとサービス・コンシューマー間の関連性が緩やかな動的ランタイム環境をターゲットにしています。疎結合されたサービスは一般的にコンパイル時間の関連性を持たないため、実行時に動的に結び付けることができ、デプロイメント担当者は、必要に応じてデプロイメントに関する決定を柔軟に行うことができます。疎結合に加えて、サービス指向の環境には以下の共通の概念があります。

  • 粗い細分度: サービスにおける細分度とは、サービスが公的に提供する機能の範囲を示します。きめの細かいサービスは、専門的な機能を定義するパブリック・インターフェースを提供します。きめの粗いサービスは、通常は特定のビジネス・ドメインに合わせたより一般的なレベルの機能を提供します。
  • 場所の透過性: 場所の透過性は、クライアントがネットワーク上の場所を意識せずにサービスにアクセスできるという考え方を指します。
  • プロトコルの独立性: プロトコルの独立性は、クライアントが通信/ネットワーク・プロトコルを意識せずにサービスにアクセスできるという考え方を指します。

これらの概念を念頭においてサービスを作成するのは、困難な作業です。POJO プログラミングは、この作業を単純化することを目指しています。

POJO を導入する

POJO は、特定の外部インターフェースまたはサード・パーティーの API に従う必要のない Java クラスです。この機能自体は、基本的に外部関連からコードを分離します。このように分離することの主な利点の 1 つは、ソフトウェア開発者が、パーシスタンス、トランザクション・サポート、およびリモート処理などの補助的な作業を自由に行えるという点です。多数の手法によって、コンポーネント/クラスの分離がなくなり、次のような POJO プログラミングが簡単になります。

JMX

JMX 仕様は、システム管理、アプリケーション管理、およびリソース管理の Java 標準となりました。JMX は、Java クラス、インターフェース、およびランタイム・オブジェクトを管理目的で使用される属性および操作で動的に拡張するための標準を定義します。この拡張の手法は、インスツルメンテーションとして知られています。

JMX は、Java プログラミング言語を使用して抽象できるすべてのリソース (アプリケーション、デバイス、またはサービスなど) を管理できます。それぞれの管理対象リソースは MBean と呼ばれます。JMX は、次の 4 つのタイプの MBean を定義します。

  • スタンダード MBean は、Java インターフェースを使用して管理属性と操作を定義します。
  • ダイナミック MBean は、実行時に発見するという方法を使用して管理属性と操作を定義します。
  • モデル MBean は、管理可能な操作および属性を公開する必要があるオブジェクトのプロキシーとしての機能を果たします。
  • オープン MBean は、定義済みのメタデータ用語集を使用してクラスとオブジェクトの管理可能な属性と操作を公開します。

MBean と相互作用する主なインターフェースは javax.management.MBeanServer です。MBeanServer は MBean の中央リポジトリーとしての役割を果たし、MBean クライアントから MBean との通信を促進します。

MBean は、ObjectName オブジェクトによって一意的に識別されます。ObjectName インスタンスは、次のもので構成されます。

  • ドメイン。特定のドメインの任意の名前です。規則では、Java パッケージ・ネーミングと同じ方法でドメインに逆引きドメイン・ネーム・システム (DNS) ネーミングを使用することを推奨しています。
  • キー・プロパティー・リスト。これは、任意の順序なしのキー・セットと関連する値です。

次のコードは、標準的な ObjectName オブジェクトの構成を示します。

String domain = "com.jeffhanson.test";
String keyPropertyList =
"domain:Name=TestBean,Type=GenericService";
ObjectName objName =
new ObjectName(domain + ":" + keyPropertyList);

ObjectName オブジェクトは、属性を検索して、MBean で操作を起動するために、数多くの MBeanServer メソッドに対するパラメーターとして使用されます。

  • アノテーションは、開発ツールがクラスまたはクラスの一部を「飾る」コードを生成するために使用するメタデータです。これは、リモート処理、パーシスタンス、およびフレームワーク・サポートなどの特定のタイプの機能をサポートするために行われます。
  • 依存性注入は、オブジェクト作成および関連がコンポーネントから除去され、コンテナーまたはアセンブラー・コンポーネントによって実行されるプラグ可能なコンポーネントを構築するための手法です。
  • リフレクションは、特定のクラスやインターフェースに関するメソッド、フィールド、およびコンストラクターなどの情報を実行時に発見することです。

それぞれの分離手法には、利点と欠点があります。この資料では、リフレクションおよび Geronimo の GBean 依存性注入を使用してコンポーネントの分離を可能にする、POJO プログラミングによる単純な SOA フレームワークを紹介します。

JMX および Geronimo

Geronimo は、Java Management Extensions (JMX) および GBean という管理対象コンポーネントの依存性注入フレームワークを使用する汎用カーネルの上に構築されています。事実上、Geronimo のすべて (アダプター、アプリケーション、コンテナーなど) が GBean であるか、GBean に基づいているかのいずれかです。GBean は、数多くの類似点および基礎となるインフラストラクチャーを JMX および JMX Managed Bean (MBean) と共有しています。

Geronimo の GBean フレームワーク

GBean は、GBeanInfo という名前のクラスに従って属性および操作を公開する点など、数多くの類似点および関係を JMX MBean と共有する Geronimo の管理対象コンポーネントです。これは、JMX で同等の MBeanInfo クラスと著しく似ていているクラスです。Geronimo は、MX4J ライブラリー (リンクについては、この資料の最後にある参考文献を参照してください) を JMX の実装として使用します。

GBean は、状態と関連の依存関係を維持して、ライフ・サイクル・イベントを処理します。GBean は、他の GBean の状況について興味のある対象として登録することができます。興味のある GBean が開始されると、関心を持った GBean は、依存性注入によって興味のある GBean への参照を受け取ります。GBean は、常に以下の 7 つのライフ・サイクル状態のいずれかになります。

  1. ロード済み
  2. アンロード済み
  3. 開始中
  4. 実行中
  5. 停止中
  6. 停止済み
  7. 失敗

リスト 1 は、1 つの属性 (メッセージ) を含む単純な GBean を示します。

リスト 1. 標準的な GBean
public class TestGBean
   implements GBeanLifecycle
{
   private static GBeanInfo GBEAN_INFO = null;

   static
   {
      GBeanInfoBuilder infoFactory =
         GBeanInfoBuilder.createStatic(TestGBean.class);
      infoFactory.addAttribute("message", String.class, true);
      infoFactory.addOperation("getMessage");
      GBEAN_INFO = infoFactory.getBeanInfo();
   }

   private String message;

   public String getMessage()
   {
      return message;
   }

   ...
}

リスト 2 に示すコードを使用して、GBean を開始 (アクティブ化) および停止することができます。

リスト 2. 標準的な GBean を開始する
ObjectName testGBeanOName =
   ObjectName.newInstance("jeffhanson.test:ID=test");
GBeanData gBeanData =
   new GBeanData(testGBeanOName, TestBean.GBEAN_INFO);
gBeanData.setAttribute("message", "Hello world");
geronimoKernel.loadGBean(gBeanData,
                         Thread.currentThread().
                            getContextClassLoader());
geronimoKernel.startGBean(testGBeanOName);
...
geronimoKernel.stopGBean(testGBeanOName);
geronimoKernel.unloadGBean(testGBeanOName);

Geronimo カーネル全体で GBeans を広範囲に使用することができます。


Geronimo カーネル

Geronimo カーネルは GBeans のフレームワークです。このフレームワークを使用すると、状態、関係、およびイベント処理を管理するために、高度なシステムを GBean コンテナーおよび GBean コンポーネントのセットとしてモデル化および構築することができます。

プログラマチックな Geronimo カーネルの作成は、KernelFactory クラスを使用すると簡単に行うことができます。リスト 3 は、TestGeronimo という名前の新しい Geronimo カーネルの作成方法を示しています。ここでは、カーネルのブート、ブート時間のロギング、およびサーブレット GBean のロードと開始を行います。

リスト 3. 単純な Geronimo カーネルを作成する
try
{
   Kernel geronimoKernel =
      BasicKernelFactory.newInstance().
         createKernel("TestGeronimo");

   geronimoKernel.boot();
 
   log.debug("Geronimo BootTime: "
             + geronimoKernel.getBootTime());

   // add the servlet GBean
   ObjectName servletObjName =
      new ObjectName("jeffhanson.test:ID=MyGBean");
   GBeanData servletGBeanData = new GBeanData(servletObjName,
                                              GBEAN_INFO);
   ClassLoader classLoader = getClass().getClassLoader();
   geronimoKernel.loadGBean(servletGBeanData, classLoader);
   geronimoKernel.startGBean(servletObjName);
}
catch (Exception e)
{
   log.error(e);
}

カーネルを作成して実行した後は、POJO サービスでメソッドを呼び出して、リスト 4 に示すように、Geronimo カーネル・サーバーおよびリフレクション機能を使用する練習をします。

リスト 4. カーネルに登録されたサービスで呼び出しを行う
private static
Object invokePOJOService(ObjectName serviceObjName,
                         String operationName,
                         String[] params)
   throws Exception
{
   String[] paramTypes = null;
   if (params != null && params.length > 0)
   {
      paramTypes = new String[params.length];
      for (int i = 0; i < params.length; i++)
      {
         paramTypes[i] = params[i].getClass().getName();
      }
   }

   Kernel geronimoKernel =
      KernelManager.getInstance().getGeronimoKernel();

   Object retVal = 
      geronimoKernel.invoke(serviceObjName,
                            operationName,
                            (Object[])params,
                            paramTypes);

   return retVal;
}

Geronimo におけるサービス指向 POJO の柔軟性のあるフレームワーク

この資料で言及されている SOA フレームワークでの POJO は、Geronimo カーネルのインスタンスを使用して、興味のあるクライアントが追加のインターフェースまたは API を必要とせずに POJO を照会して呼び出すことができる GBean として POJO を登録します。このフレームワークは、複数層のエンタープライズ・アプリケーション環境のビジネス層にあります。サービス・ロケーター・クラスは、サービスとして使用される POJO を見つけて、必要に応じて登録するために、カーネルと相互作用します。その後、POJO を呼び出すビジネス処理代理コンポーネントに POJO を戻します。図 1 は、フレームワークでのコンポーネントの関係を示しています。

図 1. SOA フレームワークでの POJO
SOA フレームワークでの POJO

フレームワークは、クライアントから HTTP 要求を受け取ってから、ディスパッチャー・コンポーネントにその要求をパススルーするように設計されています。このコンポーネントは、要求をビジネス処理代理コンポーネントに伝えてディスパッチします。次に、ビジネス処理代理コンポーネントは、サービス・ロケーターを活用して、特定の要求のサービスを見つけます。ビジネス処理代理コンポーネントはサービスを呼び出して、戻り値をモデル・オブジェクトとしてラップします。適切なビュー・コンポーネントがモデル・オブジェクトを処理して、フォーマット済みの応答としてクライアントに戻します。図 2 のシーケンス図は、これらのステップを示します。

図 2. 一般的な HTTP 要求とサービス呼び出しの双方向シーケンス
一般的な HTTP 要求とサービス呼び出しの双方向シーケンス

図 3 のクラス図は、フレームワークのクラス間の関係を示しています。

図 3. フレームワーク・クラス間の関係
フレームワーク・クラス間の関係

フレームワークをデプロイして実行する

フレームワークは、エンタープライズ・アプリケーション・システムのビジネス層にあります。フレームワークは、HTTP 要求を受け取って、その内容を処理するためにフレームワークにディスパッチする 1 つのサーブレットを公開します。次のセクションでは、簡単なデプロイメント・プロセスについて説明します。

フレームワークをデプロイする

フレームワークおよびエンタープライズ・アプリケーションのクラスを .war ファイルにパッケージして、geronimo_home/deploy ディレクトリー内に入れることができます。このディレクトリーが存在しない場合は、作成してください。

Geronimo は、始動時にこの .war ファイルを自動的にデプロイします。デプロイ・ディレクトリーに入れられたアプリケーションはホットロードされ、変更を行った場合に、Geronimo が実行時にアプリケーションを再ロードすることができます。これによって、アプリケーションのデバッグに便利になります。

フレームワークをテストする

geronimo_home/bin ディレクトリーにある始動スクリプト (startup.bat または startup.sh) を使用して、Geronimo アプリケーション・サーバーを始動します。Geronimo 始動スクリプトを呼び出すと、Geronimo コンソール・ウィンドウが表示されます。フレームワークおよびアプリケーションをデプロイした後、始動時の Geronimo のコンソール・ウィンドウには、リスト 5 に示すような行が含まれています。これらの行は、Web アプリケーションが正常に開始されたことを確認します。

リスト 5. Web アプリケーションが正常に開始されたことの確認
0 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Starting boot
422 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: :role=Kernel State changed from stopped to
starting
422 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: :role=Kernel State changed from starting to
running
422 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Booted
640 [main] DEBUG com.jeffhanson.apptier.FrontController  - Geronimo
BootTime: Sat May 20 18:51:08 MDT 2006
656 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: jeffhanson.test:ID=FrontController State
changed from stopped to starting
656 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: jeffhanson.test:ID=FrontController State
changed from starting to running

次に、以下の URL を Web ブラウザー・ウィンドウに入力して、HelloWorld サービスで setMessage 操作を実行します。

フレームワークが要求を処理すると、コンソール出力はリスト 6 に示すようになります。

リスト 6. setMessage 操作処理の出力
719 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
Adding service [HelloWorld] to kernel...
719 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
Loading GBean: jeffhanson.test:Name=HelloWorld,Type=GenericService
734 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for:
jeffhanson.test:Name=HelloWorld,Type=GenericService State changed
from stopped to starting
734 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for:
jeffhanson.test:Name=HelloWorld,Type=GenericService State changed
from starting to running

以下の URL を Web ブラウザー・ウィンドウに入力して、HelloWorld サービスで sayHello 操作を実行します。

フレームワークが要求を処理すると、コンソール出力はリスト 7 に示すようになります。

リスト 7. sayHello 操作処理の出力
750 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
serviceObjName: jeffhanson.test:Name=HelloWorld,Type=GenericService
750 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
Service  [HelloWorld] already in kernel
1156 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
serviceObjName: jeffhanson.test:Name=HelloWorld,Type=GenericService
1156 [main] INFO com.jeffhanson.businesstier.services.HelloWorld  -
Hello everybody!

サーブレット・エンジンがサーブレットをシャットダウンして、サーブレットで destroy メソッドを呼び出すと、サーブレットは Geronimo カーネルをシャットダウンします。サーブレット・エンジンがサーブレットをシャットダウンすると、コンソール出力はリスト 8 に示すようになります。

リスト 8. サーブレットのシャットダウン後の出力
1156 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Starting kernel shutdown
1156 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Kernel shutdown complete

HelloWorld クラスは、setMessage メソッド、getMessage メソッド、および sayHelloWorld メッセージを持つ単純な POJO です。このクラスのインスタンスを Geronimo カーネルに登録したら、インスタンスを動的に呼び出して、依存性注入を使用して実行時に他のサービスおよびコンポーネントに関連付けることができます。リスト 9 のコードは、単純な HelloWorld POJO クラスを示しています。

リスト 9. 単純な HelloWorld サービス
package com.jeffhanson.businesstier.services;

import org.apache.log4j.Logger;

public class HelloWorld
{
   private static Logger log = Logger.getLogger(HelloWorld.class);

   private String message = "Hello world";

   public void setMessage(String message)
   {
      if (message == null || message.length() <= 0)
      {
         throw new RuntimeException("HelloWorld.setMessage "
                                    + "param is not set");
      }

      this.message = message;
   }

   public String getMessage()
   {
      return message;
   }

   public void sayHello()
   {
      log.info(message);
   }
}

まとめ

ビジネス・ドメインの変更およびイベントにタイミングよく対応できる柔軟かつ効果的な SOA を設計することは、複雑な作業です。しかし、適切に設計された POJO 層を中心に構築された SOA は、この作業を単純化することができます。Geronimo プラットフォームは、POJO を使用して柔軟かつスケーラブルで保守可能な SOA を構築するために使用できるフレームワークおよびツールを提供します。


ダウンロード

内容ファイル名サイズ
SOA with POJOs frameworkGeronimoSOAwithPOJOs.zip14KB

参考文献

学ぶために

製品や技術を入手するために

  • Apache Geronimo バージョン 1.0 をダウンロードしてください。
  • ダウンロードまたは DVD で入手可能な IBM ソフトウェア試用版を次のオープン・ソース開発プロジェクトに取り入れてください。
  • IBM WebSphere Application Server Community Edition のフリー・コピーをダウンロードしてください。これは、Apache Geronimo オープン・ソース・テクノロジーの上に構築された単純な J2EE アプリケーションで、開発およびデプロイメントの作業を促進するために設計されています。

議論するために

  • developerWorks blogs に参加して、developerWorks コミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source, Java technology, SOA and web services, WebSphere
ArticleID=236428
ArticleTitle=Apache Geronimo および POJO を使用して SOA フレームワークを構築する
publish-date=07112006