標準的なSOA実装は多数のサービスに依存しています。こうしたサービスを呼び出すにはサービスのロケーション(すなわち、サービスのエンドポイントアドレス)とバインディング(このエンドポイントに到達するためのトランスポートメカニズム)の知識がなければなりません。最も単純なケースでは、実装時にエンドポイントアドレスをハードコード化することが可能です。このアプローチをとると、ソリューションの実装とサービスのロケーションの間に緊密な結合(ロケーション結合)がもたらされます。エンドポイントアドレスを外に出し、コンフィギュレーションファイル.NET内に置くことにより、実装の状態を改善することができます。こうすればコードを全く修正せずに、アドレスを変更できます。しかし、消費者とサービスの数が増えるにつれて(その結果、コンフィギュレーションファイルも増大)、このオプションもスケーラビリティの問題に直面します。
エンドポイントアドレスと呼び出しポリシーに対するサービスクエリの問題を動的に解決することに特化したコンポーネント「サービスレジストリ」に依存することにより、この問題に対する極めて柔軟かつ維持しやすいソリューションがもたらされます。この場合、サービスレジストリには、各ロケーションでの呼び出しに関連したサービスのデプロイメント、ロケーション、ポリシーに関する全情報が含まれています。
サービスレジストリの概念は当初、Webサービスの全体的な構想の一部として導入されたものであり、UDDI(Universal Description, Discovery and Integration)レジストリをサービス消費者と供給者の間の「仲介者」(ブローカー)として定義しました。UDDIの責務は、消費者が必要とする機能性に基づき、サービス制作者の動的な選択を供給することと考えられました。その役割はイエローページの役割に似ていたのです。多数のベンダーや標準化団体から後押しがあったにもかかわらず、サービス仲介者としてのUDDI利用は決して成功しませんでした。今日のUDDI利用法の大多数はサービスWSDLファイルの参照に限定されており、消費者設計時に使われています。
サービスレジストリのさらに実用的な利用法は、たとえばJ2EE実装で広く使われているサービスロケーター・パターン[1]に類似した、サービス名(およびポリシー)に基づいたサービスエンドポイント/バインディングのランタイム検索です。この場合、(消費者)開発時にサービス定義(インタフェース)を利用可能で、レジストリの使用はサービスエンドポイントアドレスと動的バインディングのランタイム導出に限定されています。
本稿では、SOAソリューションの実装を単純化するために利用できるサービスレジストリの.NET実装を説明します。
アーキテクチャ全体像
この論文で提案しているソリューションのアーキテクチャ全体像を図1で示しました。
図1 サービスレジストリのアーキテクチャ全体像
この実装の基礎をなしているのは、システム内の全サービスに関する情報が入ったサービスデータベースと、このデータベースをカプセル化し、情報にアクセスするために「標準化した」API一式を提供するレジストリサービスです。サービス消費者がデータベースから直接この情報を入手することは理論的には可能ですが、この場合はサービスの導入により、以下の主要目的が果たされることになります。
- 実際のデータベーススキーマからの抽出となるため、サービス消費者に気づかれることなく、提供データベース、データベースレイアウト、アクセス方法を変更できます。
- データベースへの接続量を最小限に抑えるため、データベースの全体的なパフォーマンスとスループットが向上します。
- サービス関連情報の変更を直ちに消費者へパブリッシュできるため(現在は未実装)、変更のためにデータベースをポーリングする必要がありません。
補足記事 Windows Communications Foundation [8]
Communication Foundation(WCF)は、流通している全コンピュータアプローチ(既存、新規の両方)を単一の統一プログラミングモデルにまとめるための機構であり、従って、サービスの構築と消費を簡略化します。図2で示す階層化アーキテクチャにより、この目的を達成します。
図2 WCFのアーキテクチャ
最上レイヤ「コントラクト」は、(通常使用されている)柔軟なサービス定義をサポートします。これには以下が含まれます。
- データもしくはメッセージのコントラクトで、メッセージング(データ)セマンティクスを定義します
- サービスのコントラクトで、サービス呼び出しセマンティクスを定義します
- ポリシーおよびバインディングで、通信トランスポートなどを含めたテクニカルサービス呼び出しセマンティクスを定義します
サービスランタイムレイヤにより、サービス自体の実装がカスタマイズできますが、それには以下が含まれます。
- 調整=サービスが同時処理するメッセージ量を制御します
- エラー動作=内部エラー発生時にサービス消費者に伝達する情報を制御します
- メタデータサポート=サービスに関するクエリ可能な情報を制御します
- インスタンスサポート=リクエスト処理向けにサービスの実装のインスタンス化を制御します
- トランザクション動作=サービス呼び出しのトランザクションセマンティクスを制御します
メッセージングレイヤは、メッセージ配信チャネルを通じて、メッセージ配信のカスタマイズを可能にします。チャネルにはトランスポートチャネルとプロトコルチャネルの2種類があります。
.最後に、アクティブ化とホスティングレイヤは、スタンドアロンの実行ファイルやWindowsのサービス、IIS、Windows Activation Service(WAS)などといった、異なる環境におけるサービス実装の実行をサポートします。
- トランスポートチャネルは、たとえばHTTP、名前付きパイプ、TCP、MSMQなど、物理的なメッセージ配信トランスポートをサポートします。
- プロトコルチャネルは、たとえば基本的なトランスポートチャネル全体のWS-SecurityやWS-Reliabilityなど、Webサービス標準多数の実装をサポートします。
エンドポイントアドレスとバインディングの型だけを記憶する典型的なサービスレジストリの実装に加えて、サービスパラメータのコンテンツを拡張することにより、たとえばタイムアウトの送信/受信、メッセージのサイズなどといった追加のコンフィギュレーション・パラメータを入れられるようにしました。これにより、エンドポイントアドレスとバインディング型の変更(多数のレジストリ実装で見られる機能)が可能になっただけでなく、中央処理のレジストリを使ってバインディング・パラメータの微調整もできるようになりました。
サービス消費者がレジストリを使用すると、サービス消費者の実装アプローチが少々変わります。一般にサービス消費者はサービスプロキシを使って実装されますが、サービスプロキシは既存のサービス実装に基づいて生成されます。こうしたプロキシは追加のアーチファクトとして維持し、サービスインタフェースが変わるたびに修正しなければなりません。
今回の実装ではサービス消費者が.NETのChannelFactoryクラスを活用しており、それにより、サービスのインタフェース、エンドポイント、バインディングに基づいたサービスプロキシの動的な生成が可能になります。このアプローチをとることにより、サービスプロキシ生成の回避はもとより、サービスとクライアント実装の両方に同一インタフェースを使用できるようになります。サービスプロキシの排除により、メンテナンスしなければならないコードが最小限に抑えられ、再生成されたサービスプロキシの配布によって発生するインタフェース変更を同期する必要がなくなります。サービスの消費者と供給者の実装は同一のサービスインタフェース定義プロジェクトを共有しているため、両者の同期保持が保証されるのです。
最後に、レジストリメンテナンス・アプリケーションの役割は、サービス定義データベースの中身を見ることと修正することへのサポートです。このアプリケーションにより、サービス定義の追加と更新の両方もしくは片方を行うためのサポートに加え、サービスの一覧と特定のサービスそれぞれの詳細が見られるようになります。現在このアプリケーションは、サービス消費者が既存サービスを使えるように、消費者が使う可能性のあるサービスに関するバインディング/エンドポイントの情報を入力するために使われています。
データベースの設計
下の図3は、WCFのサービス定義とそれぞれに関連してサポートされているバインディングとパラメータを示しています。
図3 サービス定義
WCFがサポートするWebサービスバインディングに加え、サービスレジストリはローカル(言語)バインディングもサポートします。
サポートされている全てのバインディング型には、それぞれ独自のURLフォーマットがあります。さらに、ローカルバインディング用のURLフォーマットも追加しました。
バインディング | URL |
local | "local://assembly/class" |
basicHTTPBinding | "http://localhost/servicemodelsamples/service.svc" |
wsHTTPBinding | "http://localhost/servicemodelsamples/service" |
wsDualHttpBinding | "http://localhost/servicemodelsamples/service" |
wsFederationHttpBinding | "http://localhost/servicemodelsamples/service" |
netTcpBinding | "net.tcp://localhost:9000/servicemodelsamples/service" |
netPeerTcpBinding | "net.p2p://broadcastMesh/servicemodelsamples/announcements" |
netNamedPipeBinding | "net.pipe://localhost/servicemodelsamples/service" |
netMsmqBinding | "net.msmq://localhost/private/ServiceModelSamplesTransactedBatching" |
表1 バインディングとそれに対応するURL
この情報をサポートするデータベース設計を図4に示しています。
図4 データベース設計
データベーススキーマ全体には、4つの主要テーブルがあります。
- サービステーブルはサービス用の基本情報を示します。サービス名に加えて、サービスカテゴリー(名前衝突を回避し、サービスのより良い整理に役立つ、サービス名向けのネーム空間)、サービスバージョン(同一サービスを異なるバージョンで同時デプロイすることを可能にし、また消費者が希望するバージョンを選択できるようにします)が含まれています。インタフェースは、サービスインタフェースの完全な修飾名であり、消費者がインタフェースを求めれば、サービスが本当に公開されることを保証します。最後に、ConsumerTypeパラメータにより、異なる種類の消費者に異なるサービスエンドポイント/バインディングを割り当てられるようになります。このような実装により、たとえば、プラチナ、ゴールド等々の顧客の種類をサポートし、それぞれに異なったSLA(エンドポイント/バインディング)を提供できるようになります。
- バインディングテーブルはバインディング向けの情報のほとんどをサポートしますが、その中にはバインディング型やそれに対応するパラメータなどが含まれます。このテーブルは、サポートされているバインディングのあらゆる型について、全パラメータのスーパーセットを示しています。信頼性パラメータとセキュリティパラメータという例外が2つだけあり、この2つに関してはテーブルが別に設けられています。
- 信頼性テーブルは、確実なメッセージングに対するサポートを指定する上で必要とされるパラメータをサポートします。
- セキュリティテーブル(現在のところ、実装は不完全)は、安全なサービスコミュニケーションを支援する上で必要なパラメータ一式をサポートします。
理想的にはサービスレジストリの実装は、信頼性/セキュリティのデータをバインディングにより、またバインディングをサービスにより、再利用できるようサポートすべきです。このサポートはまだ行われていません。実装では今のところ、サービスとバインディング、バインディングと信頼性/セキュリティ間の1対1の依存性を使っています。これにより、データベース内でデータ重複が起きますが、実装とメンテナンスはいたって簡単です。
こうしたテーブルに加えてビュー(図5)を用いて、完全なサービス定義を入手できるように、データベースアクセスの単純化を可能にしています。
図5 完全なサービス結合
サービスの実装
サービスの設計については、Web Services Software Factory(WSSF)のモデリング版を使用することにしました。このファクトリを使って、サービス定義に用いた以下のデータ型を設計しました(図6)。
図6 サービスレジストリのデータ型
WSSFを使用して設計したサービスレジストリのコントラクトを図7に示しました。
図7 サービスレジストリのコントラクト
サービスの実際の実装はかなりシンプルかつ簡単です。土台には、Microsoft patterns & practicesのエンタープライズライブラリ(データアクセス・ブロック)とリポジトリ・パターン[2]を使って実装したパーシステンスレイヤがあり、いかなる型のデータに対しても、依存性のないアクセスを提供します。実装は以下のクラスで構成されます(図8)。
図8 パーシステンスレイヤ
- リポジトリ(ジェネリック)。このジェネリックなリポジトリのベースクラスは種々のファクトリクラスを使うことにより、特定のドメインオブジェクトの送信と受信を行います。ファクトリクラスはADO.NET DbCommandオブジェクトを使い、エンタープライズ・ライブラリ・データアクセス・アプリケーション・ブロックを用いてデータベースに対してオブジェクトを実行します。
- ServiceRegistryRepository。サービスレジストリ向けリポジトリクラスに特化した実装であり、データアクセス・レイヤに主なインタフェースを提供します。
- IDomainObjectFactory(ジェネリック)。このインタフェースは、DataReader型をとり、その型からドメインオブジェクトを作成するファクトリ向けのシグネチャを指定します。
- ServiceObjectFactory(エンティティ特定)。IDomainObjectFactoryインタフェースのこの実装は、返された結果をサービスオブジェクトに変えることができます。
- IdentityObject(概念)。IdentityObjectは、検索が探しているのはどの単一エンティティあるいは複数エンティティかを特定します。IdentityObjectの実際の型は検索に応じて変化するため、特定のIdentityObjectクラスあるいはインタフェースは存在しません。
- ISelectionFactory(ジェネリック)。このインタフェースはクラスにシグネチャを提供しますが、このシグネチャがIdentityObject型をDbCommandコマンドに変換し、対応する結果セットの検索を実行します。
- ServiceRegistrySelectFactory。このファクトリは、アイデンティティオブジェクト(サービスクエリ)を受け入れて、適切なDbCommandを返すサービスレジストリに特異的です。DbCommandはサービス結果セットを返すことができます。
- IInsertFactory(ジェネリック)。このファクトリに対するインタフェースのクラスは、DbCommandを生成して新規のドメインオブジェクトをデータベースに挿入します。
- ServiceRegistryInsertFactory(オペレーション特定)。このファクトリはサービスレジストリ挿入オペレーション特有です。DbCommandを生成して新規のサービスオブジェクトをデータベースに挿入します。
- IUpdateFactory(ジェネリック)。このファクトリに対するインタフェースのクラスはDbCommandを生成し、データベース内のドメインオブジェクトを修正します。
- OperationUpdateFactory(オペレーション特定)。このファクトリは単一オペレーション(たとえばUpdateCustomer)特有のものです。適切なDbCommandコマンドを生成し、データベース内のドメインオブジェクトを修正します。
- IDeleteFactory(ジェネリック)。このファクトリに対するインタフェースのクラスはDbCommandを生成し、ドメインオブジェクトをデータベースから削除します。
- ServiceRegistryDeleteFactory(オペレーション特定)。このファクトリはサービスレジストリ削除オペレーション特有のものです。適切なDbCommandコマンドを生成し、データベースからサービスオブジェクトを削除します。
- IDataReader。System.Dataネーム空間で定義されています。このインタフェースは、結果セットのフォワードオンリーのストリーム1個以上を読み取る手段を提供しますが、この結果セットはデータソースでコマンドを実行することによって得られたものであり、リレーショナルデータベースにアクセスする.NET Frameworkデータ供給者によって実装されたものです。
サービス実装クラスは、サービス実行のためにデータアクセス・レイヤを直接使用します(ServiceRegistryRepositoryクラス)。特定のリクエストが受け取られるとすぐに、サービス実装がServiceRegistryRepository上で適切なメソッドを呼び出し、適切なデータベースオペレーションを実行の上、結果を返します。
サービス消費者のサポート
サービスレジストリ・サービスの主なユーザーは、ビジネスサービスにアクセスするサービス消費者です。サービスレジストリの導入により、サービス消費者実装のための依存性注入パターン[3、4]が強化されます。サービス消費者は特定のインタフェースに依存しており(こうしたアプローチにより、サービスのWSDL/XSDは全く消費者の目に触れません。WSDL/XSDはサービス設計においては今までどおり重要な役割を担っていますが、消費者の実装はもっぱらサービスインタフェースに基づいているため、配布とアクセスの全メカニズムは完全に目に見えなくなっています)、そこでは、特定の実装(およびバインディング)がレジストリアクセスを通じてランタイムに注入され、全体的な実装の一部として提供されるプロキシビルダー・クラスにカプセル化されます。
全体的なパフォーマンスを改善するため、サービス消費者はエンドポイント情報をキャッシュします。現在は、構成可能な時間ベースのキャッシュ戦略を使っています。次期バージョンの中には、より進歩したパブリッシュ-サブスクライブ式のキャッシュ戦略が導入されるものもあるでしょう。クライアント実装は、メソッドの使用を通じて所定のインタフェース向けに動的プロキシを作成できます。
public static Interface getProxy
(string sName, string sVersion, string sConsumer, string callBackCl)
このメソッドは、サービス名、バージョン、消費者の型(ジェネリックQoSパラメータ)、コールバック・インタフェース名(オプションパラメータ)をとり、所定のインタフェース型向けにサービスプロキシを作成します。このメソッドはまず、ローカルキャッシュで必要とされるプロキシの決定を試み(上記参照)、プロキシがローカルキャッシュに見つかれば、すぐに呼び出し元に返します。プロキシがローカルには見つからない場合は、レジストリサービスを呼び出し、入力パラメータに基づいてサービス情報を探します。完全に修飾されたインタフェース名を追加の検索パラメータとして使用し、インタフェースをサービス実装するために消費者が必要とする参照を確保します1。
前述したとおり、今回の実装におけるプロキシ作成は.NET 3.0が提供するChannelFactory
WCFサポートを使ったサービスへの接続に加えて、実装は「ローカル」なバインディングもサポートします。このバインディングは、クライアント実装から直接アクセス可能なアッセンブリで見つかるサービス実装です。クライアント実装の一部としてロードされたアッセンブリ、もしくは、GACに位置するアッセンブリのどちらかになります。
ProxyBuilder使用の簡略化
コードからコンフィギュレーションファイルへサービスパラメータを移動することにより(リスティング1の例を参照)、さらにProxyBuilder実装の使用を簡略化することができます。このアプローチはSCAコンフィギュレーション[5]をまねたもので、サービス消費者メンテナンスのさらなる簡略化を可能にします。
<configSections>リスティング1 リファレンス・コンフィギュレーション
<section name="composite" type="ProxyBuilder.CompositeSectionHandler,
ProxyBuilder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<composite>
<reference Name = "Calculator"> <Service Name = "TestService" Version = "02" ConsumerType = ""></Service>
<Callback Name = "Test.test"></Callback>
</reference>
</composite>
.さらに、レジストリ自体のロケーションをコンフィギュレーションへ移動できます(リスティング2)。
<registry>リスティング2 レジストリロケーション・コンフィギュレーション
<runtime Location ="http://localhost:58934/WCFServiceRegistry.Host/ServiceRegistry.svc"/>
</registry>
サービスレジストリのメンテナンスアプリケーション
これは別個のアプリケーションで、サービスレジストリ情報の維持管理を可能にします。以下はサポートされている主な機能です。
- サービス情報の検索とビュー
- サービス情報の更新
- サービス情報の追加
- サービスの削除
このアプリケーションはMaster-Detailパターンを使って構築したもので、そこでは、Masterが基本的なサービス情報とバインディング型であり(サービステーブルに含まれる)、そしてDetailにはサービスが使用するバインディング型のバインディングの詳細が入っています(図9)。こうした詳細ならびにその結果として表示される2番目のスクリーンは、バインディングの型に依存しています。
主要ビューの実装はDataGridViewコントロールに基づいており、同コントロールは必要な機能の大部分をネイティブに提供しますが、その中には既存レコードおよび修正の表示、レコードの追加・削除などが含まれます。バインディングの詳細はカスタムのユーザーコントロールとして実装されます。バインディングの型によって詳細が異なるため、異なるバインディング型には異なるフォームを実装しました。特定のバインディング型向けのバインディング詳細の作成およびポピュレートに関しては、ファクトリパターン(補足記事参照)を使いました。
図9サービスメンテナンスのスクリーン
補足記事:C#ジェネリクスを使ったファクトリパターンの実装
ファクトリパターンは異なる具象型の多様オブジェクトを作成する共有パターンです。C#ジェネリクスを使えば、この実装の著しい単純化が可能になります(リスティング3)。
namespace RegistryMaintanence.controls
{ public interface IControlsFactoryInterface
{ UserControl createControl(Service service, ServiceMaintanence parent, bool update);
}
public class ControlsFactory: IControlsFactoryInterface
where T : UserControl, InitializableControl, new()
{
#region IControlsFactoryInterface Members
public UserControl createControl(Service service, ServiceMaintanence parent, bool update)
{
T t = new T();
t.initialize(service, parent, update);
return t;
}
#endregion
}
public class ControlsFactory{
private static Dictionary factories = null;
private ControlsFactory(){}
private static Dictionary getFactories(){
if(factories == null){
factories = new Dictionary();
factories.Add(BindingTypeEnum.basicHTTPBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.netMsmqBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.netNamedPipeBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.netPeerTcpBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.netTcpBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.wsDualHttpBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.wsFederationHttpBinding,
new ControlsFactory());
factories.Add(BindingTypeEnum.wsHTTPBinding,
new ControlsFactory());
}
return factories;
}
public static UserControl createControl(BindingTypeEnum type ,Service service,
ServiceMaintanence parent, bool update)
{
Dictionary builders = getFactories();
IControlsFactoryInterface builder = builders[type];
return builder.createControl(service, parent, update);
}
}
}リスティング3 ジェネリクスを使ったファクトリ実装
この実装では、IControlsFactoryInterfaceインタフェースは特定のファクトリにサポートされ、インタフェースを定義します。特定のファクトリは全て、ジェネリクスであるControlsFactory
クラスを使って実装されます。このクラスはC#ジェネリクスの制約に対するサポートに依存し[7]、クライアント指定による型がいずれの制約に従う必要があるかを明示できるようにします。制約の使用により、ベースクラス上で定義された特定ファクトリがオペレーションを呼び出せるようにします。 最後に、ジェネリックなファクトリ実装はディクショナリに基づいており、バインディング型に基づいて適切な特定ファクトリの選択が可能になっています。
将来の強化
将来の実装について、現在計画中の主な強化は次のとおりです。
サービス更新向けにパブリッシュ/サブスクライブの実装
現在の実装では、前もって定められた時間間隔が過ぎると、サービスエンドポイント情報は失効になります。つまり、キャッシュされたサービス情報が必ず最新であるように、周期的にサービスレジストリ・アプリケーションをチェックすることを意味します。この戦略は、
- 余分なネットワークを生み出します。変更の有無にかかわらず、サービス情報を読み取ります。
- 実際のサービス情報とキャッシュされたサービス情報が一致しない時間帯を生み出す可能性があります。
結果として、サービスプロキシ・コンフィギュレーションは、キャッシュ更新間隔を長くせよと要求するパフォーマンス最適化(ネットワークトラフィックを最小化)と、キャッシュ更新間隔を短縮せよと要求するサービス情報不一致の最小限化の間で、両天秤策をとることになります。
この問題に対するより良い解決策は、パブリッシュ/サブスクライブの実装です(たとえば[6]を参照)。この場合、プロキシビルダーは特定サービスに関するサービス情報を受け取っていますが、このサービスの情報更新をサブスクライブしているのであり、レジストリサービスがその更新をパブリッシュします。
メンテナンスアプリケーションの拡張
上述したとおり、メンテナンスアプリケーションの役割はサービス情報の作成と修正を簡略化することです。そのため、このアプリケーションはサポート職員向けになっています。ある時点において実行可能なサービスはどれかという質問を、サポート職員から頻繁に寄せられます。全サービスのロケーション情報を中央管理する場所としてサービスレジストリを導入することにより、この質問への回答を単純化できます。既存の全サービスとそのロケーションに関する知識に基づいて、メンテナンスアプリケーションはサービス実装に「ピング」し、現在のステータスを表示できます。このような実装には、メンテナンスアプリケーションに追加機能を組み入れるだけではなく、サービス実装では積み上げ方式で「ピング」のサポートを設計する必要があります。実装の最も単純な方法は、標準の「ピング」インタフェースから全サービスインタフェースを引き出すことであり(リスティング4)、そうすればすべてのサービスにピングの実装が強制されます。
namespace Service.Instrumentation.Management
{
// Define a service contract.
[ServiceContract(Namespace = "http://Service.Instrumentation.Management")]
public interface IPing
{
[OperationContract]
bool Ping();
}
}
リスティング4 ピングインターフェース
これが済めばすぐに、レジストリメンテナンス・アプリケーションへのサービス検証機能の組み入れはかなり簡単になります。
結論
[9]で説明されているように、サービスレジストリとリポジトリはSOA実装の要です。市販の実装では(例外はほんの少数)、純粋にランタイムリポジトリとして使われることはありません。その上、市販製品を小・中規模のプロジェクトに使っては、あまりにも費用がかかりすぎることにもなりかねません(ライセンスやカスタマイゼーション、トレーニング、デプロイメントのコスト)。この論文ではレジストリに関するかなり単純な実装をお見せしており(設計の初めから実装完成までに要した時間は3週間未満)、必要とされるSOAランタイムレジストリ機能の大部分をサポートしています。また、市販の製品では見られない追加の機能もいくつかサポートしています。
謝辞
度重なる討論に参加してくれた同僚、特にPaul RovkahとRobert Sheldonに対し、著者は感謝の意を表します。こうした討論のおかげで、実装と論文の両方を改善することができました。
著者について
Boris Lublinsky博士は、ソフトウェアエンジニアリングとテクニカルアーキテクチャの分野で25年以上の経験があります。過去数年間はエンタープライズ・アーキテクチャ、SOA、プロセス管理に絞って活動しました。博士はその職歴全体を通じて、専門的な講演や著作を介して頻繁に発表を行ってきました。Avtomatika i telemechanica、IEEE Transactions on Automatic Control、Distributed Computing、Nuclear Instruments and Methods、Java Developer's Journal、XML Journal、Web Services Journal、JavaPro Journal、Enterprise Architect Journal and EAI Journalなど様々な雑誌で50を超える専門的な発表を行っています。現在、博士はHerzumSoftwareの主任アーキテクトであり、ソフトウェアファクトリの開発や、顧客によるファクトリ実装の支援などを職務としています。
参考資料
1. コアJ2EEパターン - サービスロケーター(source)
2. Edward HieattおよびRob Mee、リポジトリ(source)
3. January 2004.Martin Fowler、コントロールコンテナの転回と依存性注入パターン(source)、2004年1月
4. Griffin Caprio、設計パターン:依存性注入、2005年9月(source)
5. サービスコンポーネントのアーキテクチャ仕様(source)
6. Juval Lowy、一方向呼び出し、コールバック、イベントについて知っていなければならないこと(source)
7. Juval Lowy、C#ジェネリクス入門(source)
8. .WCFアーキテクチャ(source)
9. Lublinsky、SOAにおけるサービスリポジトリおよびレジストリの役割を探求する、IBMDeveloperWorks(source)、2007年5月