Expression Manager 構築ブロックのカスタマイズ

Expression Manager 構築ブロックの機能は、一連の Spring Bean と Flex コンポーネント経由で公開されます。サービスは Spring Bean として公開されるので、サービスを独自のカスタム実装に置き換えることができます。

デフォルトのクライアント側 ExpressionEvaluator サービスのカスタマイズ

新しいカスタム実装と置き換えずに、ExpressionEvaluator サービスを変更する場合は、デフォルト実装をカスタマイズできます。ExpressionEvaluator サービスのデフォルト実装は、Variable Resolver と Function Mapper のインスタンスを必要とします。式の評価時には、これらのインスタンスを使用して変数の値を取得したり関数の参照を解決したりします。デフォルトの ExpressionEvaluator サービスの以下のプロパティを使用してこれらを設定できます。
  • variableResolver:クライアント側の Variable Resolver は com.adobe.solutions.exm.runtime.IVariableResolver インターフェイスを表現したものです。このインターフェイスは、サーバー側よりもクライアントの方が複雑になります。変数の値を返す標準の API とは別に、Expression Manager 用の変数の値を設定するための API を持ちます。マネージャーに対し、式と共にターゲット変数が渡された場合、ターゲット変数の値を設定する目的でこの API が使用されます。また、variableChangeEvent 型のイベント(com.adobe.solutions.exm.runtime.VariableChangeEvent のインスタンス)も、リゾルバーインターフェイスの実装によって送出されます。リゾルバーによって管理されたいずれかの変数の値が変化するたびに、このイベントが送出されます。式に含まれている変数に変化が生じた場合、Expression Manager は、このイベントを使用して、式の再計算を行います。このイベントは、値に変更の生じた変数の完全修飾名と、変更前および変更後の値を保持している必要があります。

    Expression Manager には、ディクショナリを利用した単純なリゾルバー実装(com.adobe.solutions.exm.runtime.impl.SimpleVariableResolver)が用意されており、このディクショナリのキーとして完全修飾の変数名が使用されます。この実装は、ごく単純なユースケースを除くと、あまり実用性がありません。

  • functionMapper:クライアント側 Function Mapper には、com.adobe.solutions.exm.runtime.IFunctionMapper インターフェイスが使用されます。このインターフェイスは、サーバー側と同じコントラクトを持ちます。関数のプレフィックスとローカル名を渡すと、Expression Manager から呼び出すことのできる Function のインスタンスが返されます。クライアント側の Expression Manager は、リモート関数とローカル関数の両方をサポートします。マッパーから返される関数インスタンスは、次に示したように、関数の種類に応じて動作が異なります。
    • リモート関数:REMOTE_<svc> 形式のプレフィックスとローカル名を渡します。マッパーは、<svc> という ID を持つ Flex のリモート宛先のローカル名と同じ名前の操作に対応する Function インスタンスを返します。必要なリモート設定は、適切な services-config.xml をコンパイル時に指定することで、アプリケーションに実装します。

    • ローカル関数:プレフィックスとローカル名を渡すと、マッパーは、内部のマッピングを問い合わせることによって、ActionScript クラスに定義されているメソッドへの解決を試みます。アプリケーションは、解決後の ActionScript クラスが現在の ApplicationDomain 内で利用できること、また、引数のないコンストラクターを持っていることを確認する必要があります。この内部マッピングのエントリは、次のいずれかの方法で登録できます(両方の方法を組み合わせることも可能)。

      • 内部マッピングのエントリを追加する際に Expression Manager が使用する SimpleFunctionMapper インスタンスの addFunction() は、アプリケーションから呼び出すことができます。このメソッドの第 1 パラメータは、式に存在する関数の参照です(「<prefix>:<local_name>」形式の文字列)。第 2 パラメーターは、関数のマッピング先となる ActionScript メソッドです(「<fully_qualified_ActionScript_class_name>:<method_name>」形式の文字列)。

      • アプリケーションで SimpleFunctionMapper インスタンスを使用して、これらのマッピングをサーバーから初期化することもできます。そのためには、initFromServer パラメーターを true にして SimpleFunctionMapper コンストラクターを呼び出します。サーバー呼び出しは非同期で実行されるので、アプリケーションは、serverInitializationSuccess 型の Event が SimpleFunctionMapper インスタンスから送出されるのを待って、このインスタンスを使用する必要があります。サーバー呼び出しが失敗した場合、SimpleFunctionMapper インスタンスは、「serverInitializationError」型のイベントを送出することによって、アプリケーションに通知します。また、サーバー呼び出しには、「lc.exm.functionService」という ID を持った Flex のリモート宛先の読み込みが伴います。アプリケーションでは、この宛先(とそのチャンネル)に使用する設定が、適切な services-config.xml をコンパイル時に指定することによって構成されていることを確認する必要があります。

カスタムリモート関数の追加

式の中で使用する独自のリモート関数は、カスタムバンドルを作成してエクスポートすることができます。独自のリモート関数をエクスポートするカスタムバンドルを作成するには、次のタスクを実行します。
  1. Expression Manager クラス、具体的には com.adobe.exm.expeval パッケージがバンドルのマニフェストに読み込まれていることを確認します。

  2. Expression Manager 用にエクスポートするメソッドを含んだ OSGi サービスのインターフェイスを定義します。

  3. インターフェイスにメソッドを定義し、@ServiceMethod(com.adobe.exm.expeval.ServiceMethod)で注釈を設定します。注釈の設定されていないメソッドは、Expression Manager によってすべて無視されます。

    ServiceMethod 注釈には次のオプション属性があり、必要に応じて指定することができます。
    • enabled:このメソッドを有効化するかどうかを決定します。無効化されたメソッドは、Expression Manager によって無視されます。指定しなかった場合、この属性のデフォルト値は true です。

    • familyId:メソッドのファミリー(グループ)を指定します。空の場合、Expression Manager では、メソッドがデフォルトのファミリーに属するものと見なします。関数が選択されたファミリーのレジストリはありません(デフォルトのファミリーを除く)。レジストリは、各種バンドルによってエクスポートされたすべての関数について、指定されているすべてのファミリー ID の和集合に基づき Expression Manager が動的に作成します。ここで指定した ID は式のオーサリングユーザーインターフェイスにも表示されるので、ある程度人間が判読できることが必要です。

    • displayName:人間が判読できる関数の名前です。この名前は、オーサリングユーザーインターフェイスに表示されます。空の場合、Expression Manager では、関数のプレフィックスとローカル名を使用してデフォルトの名前が作成されます。

    • description:関数の詳細な説明。この説明は、オーサリングユーザーインターフェイスに表示されます。空の場合は、関数のプレフィックスとローカル名に基づくデフォルトの説明が Expression Manager によって構築されます。

    メソッドのパラメーターには、必要に応じて @ServiceMethodParameter 注釈(com.adobe.exm.expeval.ServiceMethodParameter)を使用し、注釈を設定することもできます。この注釈は、オーサリングユーザーインターフェイスに表示されるメソッドパラメーターの名前と説明を人間が判読できる形で指定する目的でのみ使用されます。

  4. インターフェイスメソッドのパラメーターと戻り値が、サポートされているいずれかの型に属していることを確認します。サポートされている型の一覧については、「一般的な JSP EL の例」を参照してください。

  5. インターフェイスの実装を定義して、Spring Bean として設定し、OSGi サービスとしてエクスポートします。この作業は、次の特別なプロパティを使用し、BluePrint を介して行います。
    <bp:service interface="A" ref="<bean_id_of_AImpl> "> 
        <bp:service-properties> 
            <entry key="connectors.httpinvoker" value="true" /> 
            <entry key="connectors.httpinvoker.alias" value="/<service_id> " /> 
            <entry key="connectors.remoting" value="true" /> 
            <entry key="connectors.remoting.id" value="<service_id>" /> 
            <entry key="exm.service" value="true" /> 
        </bp:service-properties> 
    </bp:service>

    exm.service=true は、式の中で使用するのに適したリモート関数がサービスに含まれていることを Expression Manager に伝えるエントリです。<service_id> の値は、有効な Java 識別子である必要があります。英数字/$/_ は使用できますが、他の特殊文字は使用できません。この値の先頭に REMOTE_ というキーワードを付けると、式の中で使用されるプレフィックスとなります。例えば、注釈の設定されたメソッド bar() がインターフェイスに定義されており、BluePrint サービスプロパティ内のサービス ID が foo である場合、このメソッドを式の中で参照するには、REMOTE_foo:bar() を使用します。

カスタムローカル関数の追加

式の中で使用する独自のローカル関数は、カスタムバンドルを作成してエクスポートすることができます。独自のローカル関数をエクスポートするカスタムバンドルを作成するには、次のタスクを実行します。
  1. バンドルのマニフェストで、Expression Manager のクラス(具体的には com.adobe.exm.expeval パッケージ)をインポートします。

  2. 論理上のローカル関数ごとに、Java クラスに静的メソッドが定義され、それに対応する通常のメソッドが特定の ActionScript クラスに定義されていることを確認します。例えば、ローカル関数 f について、Java 実装が com.foo.SomeJavaClass.fn() で、ActionScript 実装が com.foo.SomeASClass.flexFn() であるとします。

  3. ローカル関数をエクスポートするバンドルに Java クラスをパッケージ化し、バンドルのマニフェストでエクスポート対象としてマークします。そのようにしないと、Expression Manager バンドルがクラスを読み込めません。Expression Manager ライブラリが使用される ApplicationDomain 内で ActionScript クラスが利用できることをクライアント側で確認します。

  4. ローカル関数の Java 実装に、@LocalFunction(com.adobe.exm.expeval.LocalFunction)で注釈を設定します。注釈の設定されていないメソッドは、Expression Manager によって無視されます。

    LocalFunction 注釈には次のオプション属性があり、必要に応じて指定することができます。
    • FlexClassName:ローカル関数の Flex 実装をホストしている ActionScript クラスの完全修飾名です。

    • FlexMethodName:ローカル関数の Flex 実装に対応する ActionScript メソッドの名前です。

    • enabled:このメソッドを有効化するかどうかを決定します。Expression Manager では、無効なメソッドは無視されます。

    • familyId:メソッドのファミリー(グループ)を指定します。空の場合、Expression Manager では、メソッドがデフォルトのファミリーに属するものと見なします。関数の選択元となるファミリーのレジストリは存在しません(デフォルトを除く)。レジストリは、各種バンドルによってエクスポートされたすべての関数について、指定されているすべてのファミリー ID の和集合に基づき Expression Manager が動的に作成します。ここで指定した ID は式のオーサリングユーザーインターフェイスにも表示されるので、ある程度人間が判読できることが必要です。

    • displayName:人間が判読できる関数の名前です。この名前は、オーサリングユーザーインターフェイスに表示されます。空の場合、Expression Manager では、関数のプレフィックスとローカル名を使用してデフォルトの名前が作成されます。

    • description:関数の詳細な説明。この説明は、オーサリングユーザーインターフェイスに表示されます。空の場合は、関数のプレフィックスとローカル名に基づくデフォルトの説明が Expression Manager によって構築されます。

    メソッドのパラメーターには、@LocalFunctionParameter 注釈(com.adobe.exm.expeval.LocalFunctionParameter)を使用し、必要に応じて注釈を設定することもできます。この注釈は、オーサリングユーザーインターフェイスに表示されるメソッドパラメーターの名前と説明を人間が判読できる形で指定する目的でのみ使用されます。

  5. インターフェイスメソッドのパラメーターと戻り値が、サポートされているいずれかの型に属していることを確認します。サポートされている型の一覧については、「一般的な JSP EL の例」を参照してください。

  6. com.adobe.exm.expeval.LocalFunctionProviderImpl 型の空の Bean を Spring コンテキストに定義し、ID を割り当てます。

  7. その Bean を、次の特別なプロパティを使用し、OSGi サービスとしてエクスポートします。
    <bp:service interface="com.adobe.exm.expeval.LocalFunctionProvider" ref="lfp_id "> 
        <bp:service-properties> 
            <entry key="exm.local.function.entry.<prefix> " value="<fully_qualified_name_of_Java_class_hosting_local_function> " /> 
            [Repeat entries of the form "exm.local.function.entry.*" for other classes hosting local functions, if any] 
        </bp:service-properties> 
    </bp:service>

exm.local.function.entry.* キーの値として指定する Java クラスを、ホストバンドルのマニフェストでエクスポートする必要があります。そのようにしないと、Expression Manager バンドルがそれらのクラスを読み込めません。指定したプレフィックスは、関数プレフィックスとして式の中でそのまま使用されるので、有効な Java 識別子を指定する必要があります。例えば、localFoocom.foo.SomeJavaClass クラスのプレフィックスである場合、式内のローカル関数には、localFoo:fn() という表記が使用されます。式内のローカル名は、Java のメソッド名と同じです。

カスタム関数を含む式の評価

カスタム関数を含む式を呼び出す方法を以下のコード例に示します。

HashMap<String, Serializable> variables = new HashMap<String, Serializable>(); 
variables.put("number1", 25); 
variables.put("number2", 26); 
EXPEvaluator expressionEvaluationService = null; 
// Retrieve instance of expressionEvaluationService from spring // context as per example given in section 4. 
Object result = expressionEvaluationService.evaluateExpression( "${fm1:add(number1, number2)}", variables);

式の評価時、関数名にはキー(fm1)がプレフィックスとして付加されます。「add」関数を呼び出す際は、EL によって fm1 というプレフィックスが付加されます(例:${fm1:add(number1, number2)})。