![]() ![]() ![]() ![]() ![]() ![]() | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
第4章
ほとんどの場合、Composerに本来備わっている展開機能およびパッケージオプションは、ビジネスアプリケーションのアーキテクチャ要件を満たすには十分です。 ただし、Composerに組み込まれているサービスをプログラムレベルで操作できることが開発要件で必須の場合、低レベルのJava統合のためにComposerのフレームワークAPIを活用したコードの作成方法について知っておく必要があります。
Composerフレームワークは、Composerランタイムオブジェクトを操作したり、あるいは拡張したりする(ソースコード形式の)クラスの集まりです。 機能の詳細については、この章の後半で説明します。
多くの場合、どのような「セットアップ」コードも手作業で作成することなく、独自のカスタムサービストリガオブジェクトを作成することができます。 Novell exteNd Directorでは、サーブレット、EJB、JSP、およびJavaスタブファイルを作成し、カスタマイズするためのコード生成ウィザードが用意されています (これらのウィザードの使用法についての詳細は、メインの『Composerユーザガイド』の展開に関する章を参照してください)。 ただし、生成されたスケルトンコードを完全に理解するためには、Composerランタイム層の基本的な前提条件およびAPI要件に精通している必要があります。 この章では、Composerランタイムオブジェクトと通信するクラスを作成するために必要となる基本的な情報について説明します。
注記: この章は、コードレベルでComposerランタイムオブジェクトにアクセスするアプリケーションプログラミングインタフェースについて理解することを目的とする中級(または上級)のJavaプログラマを対象としています。 この章を十分に理解するためには、サーブレットおよびBeanプログラミングとJ2EEアプリケーションサーバランタイムの使用方法全般について精通している必要があります。
この章は、次のことを実行する場合に役立ちます。
トランスポート、プロトコル、およびデータ形式に関して、Composerでネイティブにサポートされているものを使用するのではなく、独自にこれらをサポートすることによってComposerの既存の「データ入力」機能を拡張する
データのカスタム後処理や、ある種のデータのカスタムディスパッチングなどを実行できるように、サービスの「出力」アートランタイムに直接アクセスする
注記: これ以降は、ランタイムについてのみ説明します。 Composerでプラグ可能な設計時のテスト結果を作成するためのソフトウェア開発キット(SDK)は、Novell exteNdマーケティング部門に注文して入手できます。
Composer Enterprise Serverの重要な機能は、xcs-all.jarのクラス(アプリケーションサーバインストールパスの下の、Composerの\libディレクトリ)、および\libディレクトリの付属している多数のテクノロジ固有のJARファイルによって提供されます。 xcs-all.jarのクラスには、サーバ上で実行するために必要な、Composerアプリケーションに展開されている重要なすべての「コアサービス」が提供されています。次のものがあります。
サービスオブジェクトのインスタンス化および実行は、展開アーカイブに保存されているメタデータのデコードと非シリアル化を介して行われます。 Composerでサービスまたはコンポーネントを作成すると(設計時)、実際にはサービスまたはコンポーネントのアクションモデル内のアクションをラッパするXMLファイルを作成することになります。 Composerで作成された展開アーカイブのには、コンパイル済みのクラスは含まれていません(展開でEJBを含む場合以外)。
各コンポーネントのアクションモデル内のアクションは、バイトコードの代わりに、メタデータの記述から構成されます。 Composer Enterprise Serverは、ランタイム時にその記述子を実行可能コードに変換する方法が分かっています。 これを行うクラスは表示されません。 これらは、GXSServiceComponentのメインのexecute( )メソッドを除いて、フレームワークAPIでは表示されません(次を参照)。
Composerサービスは、通常サーブレットを介して呼び出されます。 ただし、(ここでも)展開WARまたはEARにはサーブレットがありません。 呼び出しは、すでにサーバ上に常駐している「マスターサーブレット」によって処理されます。 展開アーカイブには、サーバ常駐の「トリガサーブレット」の呼び出し方法についてのメタデータの記述だけが含まれます (この記述は、WARのweb.xml ファイルにあります)。 メタデータの記述には、サーブレット用の「初期化パラメータ」が含まれます。 これらのパラメータには、実行する必要のあるサービスの名前、着信データを前処理するために使用される「コンバータクラス」、サービスをEJBとしてインスタンス化するかどうか、などが含まれています。
Composer Enterprise Serverの観点から見ると、通常Composerサービスとともに呼び出されるイベントは、次のとおりです。
アプリケーションサーバに到着する要求: たとえば、XMLはHTTP POST経由で到着します。 サーバは適切なサーブレットに通知します。この場合は、GXSServiceRunnerEx (Composerサービスに対するほとんどのサーブレットベースの要求を処理する、事前にインストール済みの、常に存在するComposer Enterprise Serverクラス)。
サービス実行サーブレットは、Composer Enterprise ServerのGXSServiceFactoryクラスを使用して目的のサービスの種類のインスタンスを取得します(上の図のように、GXSServiceComponentによって表されます)。
サービス実行側は、該当する「コンバータクラス」(主要ないくつかのComposer Serverユーティリティクラスの1つ)を呼び出して、受信データを取得し、データを文字列または文字列アレイ形式に置き変えます。 コンバータクラスについては、次に詳しく説明します。
最後に、サービス実行側はサービスコンポーネントのexecute( )メソッドを呼び出します。 通常の場合、このメソッドはサービスのXML出力を含むJava文字列を返します (オーバーロードしたさまざまなバージョンのメソッドが存在し、それぞれが独自の戻りタイプを持ちます)。
サービスの実行が終わると、サーブレットはprocessResponse( )メソッドを使用して、出力データに必要な後処理を実行します(たとえば、最終的なXSL変換など)。
先ほど説明したスキーマにはさまざまな種類があります。 前の図は、サーブレットおよびHTTP要求を含む、「1つ」の共通シナリオを示しています。 これは、次のような重要なComposerアーキテクチャの一般的な使用法について説明することが目的です。
インスタンス化されたサービスを取得するための「ファクトリ」の使用。 ファクトリのオブジェクトを委任することによって、Composerではサービスを実行する側には見えるように(キャッシュ管理などの)処理を背後で行うことができます。 また、サービスファクトリは、要求パラメータに基づいてサービスを通常のJavaオブジェクトあるいはEJBとして取得できるため、EJB展開の操作が簡素化されます。
(さまざまな種類のHTTPペイロードからXML入力を集める処理の詳細を管理する)「コンバータクラス」を使用した、サービス呼び出しロジックからのデータ事前取り込みロジックの分離
明らかに、すべてのデータがHTTPによって移動されるわけではなく、また必ずしもサーバからサービスを呼び出すのに便利というわけではありません。 これ以外のシナリオも考慮に入れておく必要があります。
GXSServiceComponentBeanクラスでは、BeanがIGXSServiceRunnerインタフェースを実装している、上記の呼び出しスキーマの便利なバリエーションが1つ提供されています。 GXSServiceComponentBean は、クライアント/要求レイヤと呼び出しターゲットレイヤとの間にさらに分離を提供します。これによって、シングルタイプのJavaオブジェクト(Bean)はさまざまなタイプのクライアントオブジェクト(サーブレット、JSP、任意のJavaオブジェクト)からの要求を適切に配置できます。 熟練した開発者は、よく知られているプロキシおよびファサードの設計パターンはこの方法であることを認識しているはずです。
Composerサービスへのリモートアクセスは、EJBを介して行われます。 GXSEJBServiceComponentクラスは、javax.ejb.EnterpriseBean, IGXSServiceRunner, java.io.Serializable、およびjavax.ejb.SessionBeanを実装します。 同様に、GXSEJBServiceと呼ばれるGXSServiceComponentと同等のEJBがあります。 Enterprise Java Beanによって、既知の設計パターンをいくつでも使用できることができます。
もちろん、一般的な「要求 -応答」パラダイムのほかに、それ以外の操作フローにComposerのサービスを登録することもできます。 たとえば、ある種のスケジューリングデーモンに応答して起動され、定期的に一定間隔で実行されるComposerサービスがあるとします。 このサービスで入力データをまったく使用しなかったり、出力データがある場合もない場合もあります。 定期的にメンテナンス機能を実行する場合もあります。 このようなタイプの特別な呼び出しシナリオは、IGXSServiceRunner インタフェースを実装する(独自の、あるいはフレームワークオブジェクトから派生した)カスタムトリガオブジェクトの使用を通してサポートされます。
先に説明した多数のクラスおよびインタフェースのソースコードは、Composer Enterprise Serverフレームワークの配布アーカイブ、xcs-src.jar にあります(次の節を参照)。 重要なクラスについては後で詳しく説明されていますが、的確な情報に関してはソースコードまたはJavadocを参照してください。
Composerの展開およびランタイムオブジェクトの操作を効率化するため、NovellではComposerサービス用のカスタムサービストリガの作成、Composer JSPタグライブラリの変更、データ受け渡し方法の変更などのために使用される一連の「フレームワーククラス」が提供されています。このフレームワークは、Composerサービスを操作するためのランタイムAPIから構成されています。
フレームワークファイルは、メインの\exteNdインストールディレクトリのAppServer\Composer\libパスにあります。 この2つのファイルを検索します。
api-xs.zip: このアーカイブには、フレームワークAPI用のJavaDoc files (HTML)が含まれています。
xcs-src.jar: このアーカイブには、フレームワークを構成する約130のクラス用のJavaソースコードが含まれています (このファイルのセットに含まれているのは、Composerに付属しているカスタムJSPタグライブラリ用のソースです) タグライブラリの詳細については、メインの『Composerユーザガイド』の付録を参照してください)。
実現が困難なほど複雑な要件がない限り、xcs-src.jar.で130を超えるクラスを使用することはありません。 ただし、サーブレットテクノロジ、EJBテクノロジ、SOAP、JSP taglib、トランザクションマネージャなどを使用したComposerサービスを操作するための多数の役に立つコードのサンプルが用意されています。
いくつかの役に立つパッケージは、次のとおりです。
com.sssw.b2b.xs.deploy.wl70:DeployerRuntimeMBeanクラスの機能を利用した、J2EEコンポーネントをWebLogic Server 7.0にインストールするためのヘルパクラス
com.sssw.b2b.xs.deploy.ws50: AppManager機能を利用して、WebSphereに展開するためのサポートクラス
com.sssw.b2b.xs.bean: このパッケージには、展開済みのComposerサービスをインスタンス化したり利用したりできるJava Beanが含まれています。 クラスは、入力変換とコンポーネントの実行で分かれています。
com.sssw.b2b.xs.ejb: このパッケージには、ホームおよびリモートインタフェースと同様に、Composerサービスコンポーネントへのリモートアクセスを取得するためのEJBセッションBeanクラスが提供されています。
com.sssw.b2b.xs.service.conversion: さまざまなトランスポートおよびパッケージ化によってXMLデータを取得するためのヘルパクラスが含まれています (これらのクラスの詳細については、次の章を参照してください)。
com.sssw.b2b.xs.mail:SMTP/MIME/POP3から展開済みのサービスへの開始点を作成するクラスが含まれています。
com.sssw.b2b.xs.soap: Novell exteNd WSSDKテクノロジを利用して、SOAP要求に応答するサービストリガの実装が提供されています。
com.sssw.b2b.xs.util:JARを操作するためのクラス、着信ファイルの特定のディレクトリを監視するバルチャクラス、Javaアーカイブにあるmanifest.mfを表すクラス、およびその他の便利なスタティックメソッドを持つクラスなど、各種のユーティリティクラスが含まれています。
フレームワーククラスで使用される定数の一覧は、xcs-src.jarにあるconstant-values.htmlという名前のファイルを参照してください。
フレームワークでは、独自のオブジェクトを使用してComposerサービスをインスタンス化したり実行したりできます。 この機能は、多くの開発シナリオにとって重要なことです。 たとえば次のとおりです。
データをComposerサービスに受け渡す前に、独自のオブジェクトを使用してデータのカスタム「前処理」(非XMLデータからXMLへの変換など)を実行できます。
何らかのカスタム方式によって、サービスの出力を、おそらくMIMEタイプに変換することによって「後処理」 を行うことができます。
フレームワークは、Composerの呼び出す層の拡張を容易にします。 たとえば、Composerサービスを直接呼び出す必要のあるレガシーCGIスクリプト(PythonまたはPHPなど)があるとします。
開発作業の中にオペレーティングシステムレベルでのコールが含まれている場合、C++/JavaでComposerサービスへの直接アクセスを必要とするポイントをクロスオーバさせることができます。
また、フレームワークを使用して特別なアプリケーションサーバサービスを利用する展開を容易にカスタマイズできます。 これは、現在Novellでサポートされていないプラットフォームに展開する場合、あるいは非J2EEサーバへブリッジする必要がある場合などに重要なことがあります。
パフォーマンスプロファイルのために、Composerサービスを直接呼び出すことのできるテストルーチンを作成します(サーブレットエンジンおよびネットワークオーバーヘッドを除外します)。これは異なるキャッシュ構成、たとえば、キャッシュとは関係のない項目(ブラウザ/ルータ/プロキシ待ち時間など)を指定した場合の結果をあいまいにすることなく、ベンチマークテストできるようにするためです。
J2EEプロジェクトで特定の設計パターンを実装する必要がある場合、さまざまなフレームワーククラスを拡張する必要(あるいは便利な場合)があります。
フレームワークでは、サービス呼び出しの方法を選択するのに非常に柔軟性があります。 可能な選択肢のいくつかは、次の図に示すとおりです。
呼び出す層のセットアップ方法の選択は、次の項目に関するアーキテクチャ上の問題によって決まります。
前の図で示されている呼び出しパターンは、DirectorおよびComposerの設計時展開オプションによって、1つあるいは別の方法で、すべてサポートされています。 フレームワークを使用している場合、呼び出す層のいくつかの部分をカスタマイズする必要があるため(示されている1つまたは複数のクラスを拡張して)、これらは想定上のものです。 これが、この説明の中心となります。
ほとんど(ただし全てではない)のComposerサービスは、何らかの入力データを使用します。 Composerサービスは、次の形式のいずれかの方法によって入力データ(ある場合)を受信することが予想されます。
入力データがHTTP経由で着信する場合、ほとんどの共通HTTP転送シナリオを処理するよう設計されているフレームワークの既存のコンバータクラスの1つを使用または拡張すると便利なことがあります (com.sssw.b2b.xs.service.conversionフレームワークパッケージのJavadocまたはソースコード、あるいはその両方を参照してください)。
入力データがHTTP経由で着信してもしなくても、そしてフレームワークコンバータクラスを使用するよう選択してもしなくても、入力データを前に説明されているいずれかの形式でサービスに渡すようコードを準備する必要があります。
フレームワークオブジェクト(サービス実行サーブレットなど)内でサービ名を参照する場合、サービスのフルコンテキスト名だけを使用する必要があります。 つまり、展開コンテキストをサービスコンポーネント名と結合させる必要があります。
完全修飾サービス名の例は、次のとおりです。
com.yourcompany.composer.ProductInquiry
ここで、
注記: Novellでは、Composerで作成されたすべての生成物の展開コンテキストに「composer」を、そしてDirectorで作成されたすべての生成物の展開コンテキストに「director」を含めることをお勧めします。 これは、単にリモートで作業している異なる開発チームメンバーによって作成された生成物のネームスペースを区切るためだけではなく、デバッグが容易になります (スタックトレースの際、どの製品で作成されたものか一目でわかると大変便利です)。
いわゆるサービスコンポーネントへの参照を取得するには、通常GXSServiceFactoryオブジェクトのスタティックcreateService( )メソッドを使用します。このオーバーロードしたメソッドは、次のシグネチャを持つ3通りの方法があります。
IGXSServiceComponent createService(java.lang.String fullServiceName) IGXSServiceComponent createService(IGXSServiceRunner aOriginator) IGXSServiceComponent createService(javax.naming.InitialContext aContext, java.lang.String aJNDIName)
1番目のケースは、もっとも単純です。 名前によって(非EJB)サービスを取得できます。 2番目のケースでは、呼び出し側(IGXSServiceRunner)は参照をそれ自身に渡し、ファクトリは初期化パラメータを取得するため呼び出し側のプロパティを検証してから、サービスをインスタンス化して設定します。
3番目のメソッドでは、EJBとしてサービスコンポーネントを生成します(サービスは一番最初に展開されたものと仮定します)。 ファクトリは、EJB (あるいはアクセッサオブジェクト)への参照を取得するためサービスのホームインタフェースの最初のJNDIコンテキストおよびJNDI名を知る必要があります。 その後で、ファクトリはEJBコンテナとの通信をすべて処理します。
サービスを直接実行するためのコードは、ごく単純なものです。 まず初めに、サービスファクトリオブジェクトによって目的のサービスのインスタンスを取得します。 次に、サービスオブジェクトのexecute( )メソッドを呼び出します。 「実行」メソッドは、サービスの出力ドキュメントをネイティブのXMLとして文字列形式で返します。
サービスを呼び出すコードは、次のように単純なものです。
String inputDoc =
\xd2 <?xml version=\"1.0\" encoding=\"UTF-8\"?><root/>\xd3 ;
String outputDoc = \xd2 \xd2 ;
String serviceName = "com.acme.composer.ProductInquiry";
try {
// Obtain an instance of the desired service:
IGXSServiceComponent myService =
GXSServiceFactory.createService( serviceName );
// Execute the service:
outputDoc = myService.execute( inputDoc );
}
catch( GXSException gxsEx )
{
// Do something with exception
}
この種類のコードを使用して、任意のカスタムJavaオブジェクト(サーブレットだけでなく)からComposerサービスを呼び出すことができます。 もちろん、サービスの入力データを取得するのは呼び出し側のジョブであるため、直接実行メソッドにデータを渡すことができます。 前に示されている最小限のコードでは、1つの入力ドキュメントをネイティブXML文字列として渡しています。 複数のドキュメントを、おそらくDOMオブジェクトとして(たとえば、タイプがorg.w3c.dom.Documentのオブジェクト)渡す必要がある場合、execute( )または executeEx( )の他の変形の1つを呼び出すことができます。次の「データ受け渡しオプション」の説明を参照してください。
ファクトリで取得されたサービスインスタンスでexecute( )を呼び出す代わりに、より柔軟でアーキテクチャ的に強力なこれを行うための方法は、アクセッサオブジェクトを通してサービスオペレーションを委任することです。 すなわち、これはBeanと呼ばれます (EJBではなく、通常のJava Beanです)。 この方法では、Beanのセッタメソッドを使用して目的のサービス名、入力ドキュメント、およびその他のパラメータを指定し、次にBeanでexecute( )を呼び出して、汎用的なBeanを直接インスタンス化します (Beanは次にコールをサービスに委任します)。
フレームワークでは、GXSServiceComponentBeanと呼ばれるクラスに、この目的用のユーティリティBeanが提供されています。 このBeanを使用しているコードは通常、次のようになります。
private static final String SERVICE_NAME = "com.composer.MyService"; // Legal values here are \x81 gNormal\x81 h or \x81 gEJB\x81 h: private static final String SERVICE_TYPE = "Normal"; // Instantiate the bean GXSServiceComponentBean lService = new GXSServiceComponentBean(); // Configure it lService.setInputXMLDoc( aXML ); lService.setServiceName( SERVICE_NAME ); lService.setServiceType( SERVICE_TYPE ); // Now execute the service: try { lService.execute(); } catch ( GXSException e ) { System.out.println( e ); } // Obtain the service\xd5 s output: String myOutput = lService.getOutputXMLDoc();
Beanのメカニズムは非常に柔軟性があります。 Bean自体は、汎用的なものです。 任意のサービスをバインドするためダイナミックにBeanを設定することができます。 BeanはIGXSServiceRunnerインタフェースを実装しており、これはさまざまなsetterメソッドを通して、呼び出す前にXSLリソース情報、コンバータクラス名、およびその他のサービス用の設定パラメータを指定できるということです。 同様に、実行後にサービスから情報を取得するためにさまざまな「getter」を使用できます。 さらに、GXSServiceComponentBeanクラスには、出力データを操作するのに役立つ、getXPath( ) およびfindDocByPartName( )などのユーティリティメソッドがあります。
サービス実行Bean (GXSServiceComponentBean)を使用すると、setServiceType( )によって、ターゲットサービス(EJB方式で展開されていると想定します)を取得して実行するために、EJBアクセスまたは非EJB (「通常」)アクセスを使用するかどうかを指定できます。 これによって、EJBとして展開されているサービスを操作する際の複雑さがなくなります。
Directorで生成された(およびComposerで生成された)JSPコードで使用されているカスタムタグライブラリは、GXSServiceComponentBeanオブジェクに基づき作成されています (タグライブラリ自体のソースコードは、フレームワークの一部です)。
注記: GXSServiceComponentBeanクラスは、GXSServiceComponentBaseと呼ばれるユーティリティクラスから継承されます(これにより、サービス実行インタフェースが実装されます)。 提供されている多数のsetter、getter、およびユーティリティメソッドの詳細については、これら2つのクラスのソースコードまたはJavadoc、あるいはその両方を参照してください。
GXSServiceComponentのexecute( ) メソッドは、XMLデータをさまざまな方法で渡したり受信したりできるようにするためオーバーロードされます。 このメソッドの変形は、複数の入力ドキュメントを(文字列アレイまたはDOMオブジェクトのアレイいずれかとして)渡すことができるように、あるいは入力をjava.io.Readerとして渡すことができるようにするためにあります。いずれの場合も、リターンタイプは入力タイプと同じになります。
また、executeEx( )と呼ばれるオーバーロードしたメソッドもあり、これは1つまたは複数の出力パートまたはヘッダーパート、あるいはその両方を含むSOAPサービスに応答するため、軽量のラッパオブジェクトであるGXSExResponseオブジェクトを返すという点でexecute( )とは異なります。
execute( )およびexecuteEx( ) のさまざまなシグネチャおよび使用法についての簡単な説明は、次のとおりです。
java.lang.String execute()
入力ドキュメントを使用しないComposerサービスを実行します。
org.w3c.dom.Document execute(org.w3c.dom.Document aInputDoc)
指定されたDOMを使用してComposerサービスを実行します。
org.w3c.dom.Document execute(org.w3c.dom.Document[] aInputDocs)
指定された複数のDOMを使用してComposerサービスを実行します。
java.io.Reader execute(java.io.Reader xmlIn)
指定されたXMLリーダを使用してComposerサービスを実行します。
java.lang.String execute(java.lang.String xmlIn)
指定されたXML文字列を使用してComposerサービスを実行します。
java.lang.String execute(java.lang.String[] aInpDocs)
指定されたXML文字列を使用してComposerサービスを実行します。
GXSExResponse executeEx(java.lang.String[] aInpDocs)
指定されたXML文字列を使用してComposerサービスを実行します。
GXSExResponse executeEx(java.lang.String[] aInpDocs, java.lang.String[] aInpHdrDocs)
指定された複数のXML文字列を使用してComposerサービスを実行します。
広い意味では、「サービストリガ」とはサービスインスタンスの取得およびその実行に責任を持つオブジェクトのことを指します。 フレームワークでは、主となるトリガオブジェクトは、GXSServiceRunnerとGXSServiceComponentBeanです。 前者はサーブレットで、後者は汎用目的のBeanです。
GXSServiceRunnerクラスはjavax.servlet.http.HttpServletから継承され、IGXSServiceRunnerインタフェースを実装します(java.io.Serializableと同様)。 GXSServiceRunnerEx クラスは、1つまたは「複数」の入力ドキュメントを処理するという点でGXSServiceRunnerと異なります。
GXSServiceComponentBeanはGXSServiceComponentBaseから継承されます。 両方とも、java.io.SerializableだけでなくIGXSServiceRunnerも実装します。 親クラスであるGXSServiceComponentBaseには多くのgetterおよびsetterメソッドが用意されており、ダイナミックに機能を調整することができます。 HTTP要求の処理だけに限定されません。
HTTP経由で着信するデータを処理するトリガを実装している場合、便利な開始点はGXSServiceRunnerまたはGXSServiceRunnerExです。
もちろん、厳密に言うと、サービスを実行するためにフレームワークの既存のサービス実行クラスを拡張する必要はありません。 事実、カスタムトリガオブジェクトでIGXSServiceRunnerを実装する必要さえありません (フレームワーククラスを拡張したり実装したりしていないコードのサンプルは、「サービスの実行」を参照してください)。 それでも、これらのクラスおよびインタフェースの動作方法については理解しておく必要があります。
フレームワークのすべてのサービス実行オブジェクトが実装しているインタフェースは、IGXSServiceRunnerです。 このインタフェースには、getServiceProperty( ) およびgetClassLoader( )と呼ばれる2つのメソッドと、ランタイム時にパラメータを探すために使用される多数の事前定義されたパブリック/スタティックプロパティ(文字列)があります。 getServiceProperty( )メソッドは引数として文字列を取得します。文字列は、IGXSServiceRunnerで定義されているスタティックプロパティ文字列の1つと合致する必要があります。 getServiceProperty( )メソッドは、渡された文字列をサービス環境に関する情報を参照するキーとして使用します。
たとえば、そのプロパティの1つはSERVICE_NAMEと呼ばれるものです。 IGXSServiceRunner.SERVICE_NAMEのハードコーディングされた(最終的な)値は、「servicename」です。 サービス実行オブジェクトがgetServiceProperty( )へのコールでこの値を受け取った場合、メソッドは呼び出されるサービスの名前を返す必要があります。
getServiceProperty( )メソッドは、しばしば、サービス実行に対する参照を受け取る可能性のあるオブジェクトおよび実行側が実行しようとしているサービスに関する情報を検索する必要のあるオブジェクトなど、さまざまなオブジェクトによって呼び出されます。 たとえば、GXSServiceFactoryオブジェクトには、createService( )と呼ばれるオーバーロードしたメソッドがあります。 createService( ) メソッドの1つは、引数としてIGXSServiceRunnerを使用します。 渡されたサービス実行参照を使用して、ファクトリオブジェクトは呼び出し側のプロパティを検査し、呼び出し側に返す前にサービスインスタンスの設定方法を判別します。 これと同じメカニズムがフレームワーク内のさまざまなデータコンバータオブジェクトで使用されています。
このように、サービス実行側はIGXSServiceRunnerインタフェース内のすべての文字列プロパティのルックアップ値(または「get」メソッド)を定義する必要はありません。 いくつかのプロパティは、たとえば SOAPトランザクションにおける電子署名されたXMLなど、特別なシナリオに含まれているプロパティのみに関連します。 もっとも一般的なシナリオの場合、サービスファクトリのcreateService( )メソッドに対するすべてのコールの前に使用可能にしておく必要のある「ディスカバリ」プロパティは、SERVICE_NAMEとSERVICE_TYPEプロパティです (後者のプロパティを使用して、ファクトリまたはコンバータオブジェクトは呼び出し側がEJBまたは非EJBサービスのどちらを必要としているのか判別できます)。
IGXSServiceRunnerの最小限の実装は、次のとおりです。
class MyServiceRunner implements IGXSServiceRunner { private String mFullServiceName; MyServiceRunner(String fullServiceName) { mFullServiceName = fullServiceName; } public String getServiceProperty(String aName) { if( aName == IGXSServiceRunner.SERVICE_NAME ) return mFullServiceName else if( aName == IGXSServiceRunner.SERVICE_TYPE ) return IGXSServiceRunner.SERVICE_TYPE_NORMAL; else return null; } public ClassLoader getClassLoader() { return Thread.currentThread().getContextClassLoader(); } }
getServiceProperty( )がSERVICE_NAME あるいはSERVICE_TYPEではなく引数を指定して呼び出された場合、メソッドはNULLを返します。 getServiceProperty( )を呼び出すComposerオブジェクトは、見つかったNULL戻り値に基づいてさまざまなデフォルト動作を実装するため、ここでNULLを返すのは重要なことです。 ダミー値(たとえば、「サポートされていません」など)を返すと、どのようなことが発生するかは予測不能です。
getServiceProperty( )の他に、サービス実行側はファクトリオブジェクトで使用できるようにするためにgetClassLoader( )を実装する必要があります。 前に示された実装は、ほとんどのケースに当てはまります。
コードでHTTP要求を処理する場合、GXSServiceRunnerExを拡張する可能性があります。 これがComposerサービスをトリガするフレームワークの汎用目的のサーブレットです。
GXSServiceRunnerExを拡張するコードの例は、次のとおりです。 これはMyComposerServiceRunnerと呼ばれるカスタムJavaクラスを実装しています。
package com.composer; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; import com.sssw.b2b.xs.*; import com.sssw.b2b.xs.service.GXSServiceRunnerEx; public class MyComposerServiceRunner extends GXSServiceRunnerEx { static final String CONTENT_TYPE = "text/html" ; // Overload the following method if you want to // override the default converter class architecture protected String[] processRequestEx(HttpServletRequest aReq) throws ServletException { return super.processRequestEx( aReq ); } // Overload the following method if you want to // override default response architecture public void processResponse( String xmlOut, HttpServletRequest req, HttpServletResponse res ) throws GXSException { super.processResponse( xmlOut, req, res ); } }
processRequestEx( ) およびprocessResponse( ) メソッドは、独自の特別なデータ前処理および後処理のロジックを実装するための便利なフックを提供しています。 前のコードは、ただ単にこれらのメソッドの親のデフォルト実装に実行を委任しただけです。 前処理および後処理の制御を取得するには、「super」の呼び出し部分を削除して、独自のコードを挿入します。
GXSServiceRunnerから継承されている、前に示されているクラスのサンプルの場合、代わりにHttpServletから継承します。 通常のサーブレット制御フローが適用されます。 GXSServiceRunnerでは、フローは次のようになります。
doPost( ) メソッドはinitService( )を呼び出します。これによってGXSServiceFactory.createService(this)経由で目的のサービスを取得します。
performProcessRequest( )はprocessRequest( )を呼びし、サービスの入力データを取得します (データを取得するため、GXSInputConverterBeanがインスタンス化されます。 次に、Beanはサービス実行側のCONVERTER_CLASS_NAMEプロパティを検査して使用するコンバータクラスを判別します)。 次に、サービスのexecute( )メソッドが呼び出されます。
processRequest( ) が返されると、メソッドprocessResponse( ) が実行されます。 ここでデータの後処理が実行されます。 また、HttpServletResponseから開かれたOutputStreamsもすべて閉じられます。
注記: デフォルトのprocessResponse( )の実装には、サービス実行によって設定されたHTML_INDICATORプロパティの値に基づいて、XMLからHTMLに変換するためのコードが含まれています(サーバ側のXSL 変換を使用)。 この種のデータ後処理の実行方法について調べる場合は、GXSServiceRunnerのソースコードを参照してください。
GXSServiceRunnerのデフォルト実装は、フレームワークのメソッド(具体的には、GXSServiceFactoryおよびGXSInputConverterBeanに属するメソッド)によって異なり、サービス実行それ自体はメソッドの引数であることを理解することは重要なことです。 サービス実行への参照がこのような方法で渡されるのは、ファクトリオブジェクトが呼び出し側のプロパティにアクセスする必要があるからです。 問題となるプロパティには、通常何らかの設定パラメータが含まれています。
たとえば、GXSServiceRunnerでGXSServiceFactory メソッドcreateService( )を呼び出すと、「これ」は引数として渡され、ファクトリはサーブレット参照を使用して取得するサービスの「名前」とサービスの「タイプ」(EJBまたは非EJB)を見つけ出します。 これらの情報は、最終的にはサーブレットの初期化パラメータ(特に、「servicename」および「xcs_servicetype」と呼ばれるパラメータ)から取得します。 次に、初期化パラメータはサーブレットのWARモジュールのweb.xmlファイルで指定されます。
次のリストは、MyComposerServiceRunnerクラスのweb.xmlサーブレットエントリがどのように表示されるのかを示しています。 このサンプルでは、ターゲットのComposerサービスはHelloWorldと呼ばれ、フレームワークで指定されているGXSInputFromHttpParamsコンバータクラスは、HTTP要求からのデータを取得するために使用されます。
<servlet> <servlet-name> MyComposerServiceRunner </servlet-name> <display-name /> <servlet-class> com.composer.MyComposerServiceRunner </servlet-class> <init-param> <param-name>servicename</param-name> <param-value>com.composer.HelloWorld</param-value> </init-param> <init-param> <param-name>xcs_servicetype</param-name> <param-value>NORMAL</param-value> </init-param> <init-param> <param-name>transform_into_html</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>rootname</param-name> <param-value>greeting</param-value> </init-param> <init-param> <param-name>converterclassname</param-name> <param-value> com.sssw.b2b.xs.service.conversion.GXSInputFromHttpParams </param-value> </init-param> </servlet>
「servicename」の初期化パラメータは、ターゲットサービスの完全な名前(フルテキスト)、この場合はcom.composer.HelloWorldを指定することに注意してください。
「rootname」(サービスの入力としてコンバータクラスで作成するXMLドキュメントのルート要素名を指定します)、processResponse( )で出力データのXSL変換を行うかどうかをGXSServiceRunnerに示すための「transform_into_html」フラグなど、その他のパラメータも指定します。
GXSServiceRunnerまたはGXSServiceRunnerExを拡張する場合、前に示されているように、サーブレットクラスのweb.xmlファイルで、必ず最低でも、初期化パラメータ「servicename」、「xcs_servicetype」、および「converterclassname」(そしてこれらの有効な値)を指定する必要があることに注意してください。 その他の初期化パラメータはすべてオプションです。
フレームワークファクトリは、指定可能な多数の初期化パラメータタイプを理解します。 完全なリストについては、IGXSServiceRunnerインタフェースで定義されているプロパティを参照してください。 一般的に使用されるパラメータのいくつかは、次の表のとおりです (必須パラメータは太字になっています)。
サーブレットクラスが、web.xml初期化パラメータメカニズムを使用できない環境で使用される場合は、次のメソッドに対してカスタム実装を提供する必要があります。
getServiceName()
サーブレットをComposerサービスコンポーネントにバインドします(すべてのケースで必須)。
getRootName()
コンバータクラスがGXSInputFromHttpParamsの場合、使用されるルートエレメントの名前を返します(それ以外の場合は、デフォルトによって「ルート」が使用されます)。
getServiceType()
「NORMAL」または「EJB」の文字列値を返し、呼び出されるサービスコンポーネントのタイプを示します(すべてのケースで必須)。
getConverterClassName() IGXSInputConversion
インタフェースを実装するクラスの名前を返します(すべてのケースで必須なわけではありませんが、指定するようお勧めします)。
getOutputHTMLIndicator()
サービスの出力がprocessResponse( )のデフォルト実装を使用してHTMLに変換される場合、trueを返します。XMLの場合はfalseを返します (ここでも、すべての場合に必須ではありませんが、指定することをお勧めします)。
フレームワークのサーブレットベースのサービス実行クラス(GXSServiceRunnerEx)は、いわゆる「コンバータクラス」を利用してHTTP経由で着信したデータを取得します。 これらのクラスは、サービス呼び出しロジックと「データマーシャリングおよびアンマーシャリング」ロジックを切り離すために提供されます。
フレームワークのコンバータクラスは、IGXSExInputConversionインタフェースを実装します(これは次にIGXSInputConversionを拡張します)。 このインタフェースには1つのメソッドしかありません。
String[] processMultipleRequests(HttpServletRequest aReq)
このメソッドは基本的にサーブレット要求をXML文字列のアレイに変換します。
注記: カスタムサービス実行クラスでHttpServletRequestオブジェクトを使用していない(または指定できない)場合は、IGXSExInputConversionインタフェースを実装できないため、この説明はGXSServiceRunnerEx を拡張している場合(あるいは最終的にファクトリオブジェクトに渡されるカスタムサーブレットを実装している場合)だけに適用されます。 トリガクラスがHttpServletから継承されていない場合、データをフェッチし、そして単純にデータをサービスのexecute( )メソッドに渡すだけの独自のスキーマを実装できます。
フレームワークのほとんどのコンバータクラスは、引数IGXSServiceRunner を使用するコンストラクタを実装しているため、コンバータは呼び出し側から初期化パラメータ(あるいはその他の情報)を取得できます。 使用中のこの技法のサンプルを参照する場合は、フレームワークコンバータクラスのソースコードを調べてください。
フレームワークには、事前定義された多数のコンバータクラス(つまり、IGXSExInputConversionインタフェースを実装している)が含まれています。 これらのクラスの名前は、サーブレットの初期設定パラメータで指定するか、またはGXSServiceComponentBaseのsetConverterClassName( )メソッドで指定できます。
フレームワークで使用できるコンバータクラスは、次のとおりです。
GXSConvertHttpMPReqNonBuff - 上と同じですが、バッファに入っていないMultipartRequestを使用します。(注記: MultipartRequestクラスはフレームワーク内で定義されます。 詳細については関連するJavadocまたはソースコード、あるいはその両方を参照してください)。
GXSInputFromHttpParams - HTTP GETのURLの最後のクエリパラメータを解析することによってXMLを取得します。 これらのパラメータは即時にXMLドキュメントにアセンブルされます。
GXSInputFromHttpSpecificParam - 形式は、XMLを含む「xmlfile」と呼ばれるフィールドによって、ポストされていることを前提としています。
GXSInputFromJavaObject - これは実際にComposer JSP taglibメソッドによって使用される便利なオブジェクトです。 これは、GXSServiceComponentBeanへの参照を使用して作成されます。 Beanは、「xmldoc」と呼ばれる初期設定パラメータに変数名が配置されているXML文字列を指すことが可能である必要があります。 詳細については、ソースコードを参照してください。
GXSInputFromSoapContent - SOAP要求のBODY要素の下の要素からXML文字列を取得します。 すべての要素はString[ ]に累積されます。
これらのクラスがもっとも小さなカスタムコンバータクラスを除いて、実装される前の動作方法についてはソースコードを学ぶ必要があります。 実行するデータ変換の種類によっては、既存のコンバータクラスを拡張(そして多数のコーディングを保存)できる場合があります。
カスタムコンバータクラスは、次のようになります。
public class MyConverterClass implements IGXSInputConversion { // Attribute that holds the service // runner for querying parameters. IGXSServiceRunner mRunner = null; // Constructor to take the IGXSServiceRunner // so that the class can retrieve params public MyConverterClass( IGXSServiceRunner aRunner ) { mRunner = aRunner; } // the processRequest method should take // an HttpServletRequest as // a parameter and return an XML doc as a String: public String processRequest( HttpServletRequest aReq ) throws GXSConversionException { String lsExpandedDoc = null; // ( create or obtain XML . . . ) return lsExpandedDoc; } }
Enterprise Java Bean (EJB) APIは、ロジック、データアクセス、およびプレゼンテーション層を切り離し、一方では接続プール、トランザクション管理、持続性、アクセスコントロール(役割を介して)、「ネーミングサービス」(JNDI)、および呼び出しメカニズムなどを提供することによって、アプリケーションでこれらの機能を個別に実装、管理する必要がないように設計されたコンテナアーキテクチャを実装しています。
Composerサービスは、EJBとして展開できます。 Composer Enterprise Editionでは、設計時にEJB関連付けを設計するための単純なドラッグアンドドロップのUIが用意されています(『Composerユーザガイド』を参照)。これによってEJBセッションBeanとして展開されるサービスを選択する際、これがステートフルまたはステートレスのどちらであるのか、トランザクション参加レベル(Mandatory、Never、Supports、その他)、およびサービスのJNDI名を指定できます。
EJBは、コンストラクタを使用して直接インスタンス化できないため、GXSServiceFactoryのスタティックcreateService( )メソッドを使用してサービスへの参照を取得する必要があります。 問題となっているメソッドのシグネチャは、次のとおりです。
public static IGXSServiceComponent createService(javax.naming.InitialContext aContext, java.lang.String aJNDIName) throws GXSException
返されるサービスオブジェクトのタイプはIGXSServiceComponentで、これはすでに説明されているさまざまなexecute( ) オーバーロードしたシグネチャをすべてサポートすることを意味します。
GXSServiceFactoryを使用するほかに、Composerサービスと通信するため一種の「プロキシオブジェクト」として動作可能なGXSServiceComponentBeanクラスを利用する方法があります。 このJavaBeanを使用したコードのサンプルは前に示したとおりです(「GXSServiceComponentBeanを使用したサービスコールの委任」)。 このBeanをEJBサービスアクセッサとして使用するには、前に説明した手順に従います。ただし、setServiceType( )で「EJB」を指定し、展開されたサービスの名前を指定してsetServiceName( ) を呼び出すのに加えて、setJndiServiceName( )を使用して、展開時にサービスに対して指定したJNDI名を指定します。 自分自身でIGXSServiceRunnerインタフェースを実装する場合、サービス実行でgetJndiServiceName( ) の実装を提供し、後者がJNDI_NAME用の要求を受け取ったときにgetServiceProperty( ) から実装を誘導する必要があります。
EJBリモートインタフェースIGXSEJBServiceComponentは、com.sssw.b2b.xs.ejb
パッケージにあります。 ComposerサービスをEJBとして展開する場合、 JNDI名をEJBに割り当てます。EJBのホームインタフェースに対するリファレンスを取得するために使用するのは、修飾Composerサービス名ではなく、この名前です。IGXSEJBServiceComponentを作成するためのEJBホームインタフェースの名前は、IGXSEJBServiceHome
です。
EJBホームインタフェースのJNDI名を指定する場合、Novell Extend Application Serverでは、「sssw://host/RMI/」という文字列を名前の前に追加する必要があることに注意してください。 たとえば、EJBをmain.server
という名前のApplication Serverに展開し、このEJBのJNDI名がcom/acme/inventory/ProductInquiry
の場合、完全な修飾JNDI名は、sssw://main.server/RMI/com/acme/inventory/ProductInquiry
になります。
GXSServiceFactoryのcreateService()
メソッドのようなホームインタフェースが取得されると、create()
というメソッドが呼び出され、その後、EJBのリモートインタフェースが返されます。 (これはEJBの世界にあるEJBをインスタンス化することと非常に似ています)。 リモートインタフェースには、次に示すように2つの「実行」メソッドが含まれます。
java.lang.String execute()
入力ドキュメントを使用しないComposerサービスを実行するメソッド。
java.lang.String execute(java.lang.String inXML)
単一のXMLドキュメントに対してComposerサービスを実行するメソッド。
java.lang.String execute(java.lang.String[] asInputStrs)
複数の入力ドキュメントを使用してComposerサービスコンポーネントを実行するメソッド。
GXSExResponse executeEx(java.lang.String[] asInputStrs)
指定された複数のXML文字列を使用してComposerサービスを実行します。
GXSExResponse executeEx(java.lang.String[] aInpDocs, java.lang.String[] aInpHdrDocs)
指定されたXML文字列を入力およびヘッダとして使用してComposerサービスコンポーネントを実行します。
IGXSServiceComponent
で使用できるリーダまたはexecute( ) のドキュメントバージョンは、EJBリモートインタフェースでは使用できないので注意してください。 これは、リーダまたはドキュメントのいずれもシリアル化できないため、どちらもリモートメソッドで表示できないためです。
EJBアクセスに対して低レベルのコントロールが必要な場合、com.sssw.b2b.xs.sssw
パッケージにある、GXSEJBAccessorというファクトリクラスに関して知る必要があります。 このクラスには、Novell exteNd Application ServerからEJBのホームインタフェースを取得する2つのメソッドがあります。
1つは、認証の必要がないサーバ内で使用できるメソッドで、もう1つは、ユーザ名およびパスワードの2つの追加パラメーダを提供するメソッドです。
このファクトリを使用する場合、EJBに割り当てられているJNDI名を完全に修飾する必要はありません。このファクトリは、指定したパラメータを使用して完全修飾ホスト名を作成します。 次の例では、EJBのJNDI名は、com/acme/inventory/ProductInquiry
で、Novell exteNd Application Server名は、main.server
で、ポートは、デフォルトのインストール80(HTTP)または54890(RMI)にあります。
import com.sssw.b2b.xs.ejb; import com.sssw.b2b.xs.sssw.GXSEJBAccessor; public void doSomeEJBStuff() throws java.rmi.RemoteException { IGXSEJBServiceHome srvcHome = GXSEJBAccessor.getHomeBean( \xd2 com.sssw.b2b.xs.ejb.IGXSEJBServiceHome\xd3 , \xd2 com/acme/inventory/ProductInquiry\xd3 , \xd2 main.server\xd3 , 80, 54890 ); IGXSEJBServiceComponent ejbSrvc = srvcHome.create(); // Do something with the service component }
Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved. more ...