Baustein „Expression Manager“ anpassen

Die Funktionen des Bausteins „Expression Manager“ werden mithilfe einer Reihe von Spring-Beans und Flex-Komponenten bereitgestellt. Da die Dienste als Spring-Beans bereitgestellt werden, können Sie sie durch Ihre eigene benutzerdefinierte Implementierung ersetzen.

Clientseitigen Standard-ExpressionEvaluator-Dienst anpassen

Wenn Sie den ExpressionEvaluator-Dienst ändern, ihn aber nicht durch eine neue benutzerdefinierte Implementierung ersetzen möchten, können Sie die Standardimplementierung anpassen. Die Standardimplementierung des ExpressionEvaluator-Diensts erfordert eine Instanz des Variablen-Resolvers und des Function Mapper. Diese Instanzen werden bei der Auswertung von Ausdrücken dazu verwendet, Werte von Variablen abzurufen und Funktionsreferenzen aufzulösen. Sie können sie mithilfe der folgenden Eigenschaften des standardmäßigen ExpressionEvaluator-Diensts konfigurieren:
  • variableResolver: Der clientseitige Variablen-Resolver ist eine Repräsentation der com.adobe.solutions.exm.runtime.IVariableResolver-Schnittstelle. Diese Schnittstelle ist komplexer als die entsprechende serverseitige Schnittstelle. Außer der Standard-API zum Zurückgeben des Werts der jeweiligen Variablen ist hier eine API vorhanden, über die Sie den Wert der von Expression Manager zu verwendenden Variable festlegen können. Diese API dient dazu, Werte für Zielvariablen festzulegen, wenn diese zusammen mit den Ausdrücken an die Manager-Anwendung übergeben werden. Die Implementierung der Auswahl löst außerdem ein Ereignis (eine Instanz von „com.adobe.solutions.exm.runtime.VariableChangeEvent)“ des Typs variableChangeEvent aus. Das Ereignis wird bei jeder Änderung des Werts einer der durch die Auswahlfunktion verwalteten Variablen ausgelöst. Expression Manager verwendet dieses Ereignis zur Neuberechnung von Ausdrücken, die die geänderte Variable enthalten. Dieses Ereignis muss den vollständig qualifizierten Namen der Variablen mit dem geänderten Wert sowie den alten und den neuen Wert enthalten.

    Expression Manager stellt eine einfache Implementierung des Resolvers (com.adobe.solutions.exm.runtime.impl.SimpleVariableResolver) bereit, die auf einem Wörterbuch basiert und vollständig qualifizierte Variablennamen als Schlüssel in diesem Wörterbuch verwendet. Diese Implementierung ist wahrscheinlich nur für die einfachsten denkbaren Verwendungszwecke geeignet.

  • functionMapper: Der clientseitige Function Mapper verwendet die com.adobe.solutions.exm.runtime.IFunctionMapper-Schnittstelle. Diese Schnittstelle hat denselben Kontrakt wie die entsprechende serverseitige Schnittstelle. Wenn ein Funktionspräfix und ein lokaler Name für diese Schnittstelle bereitgestellt werden, gibt sie eine Funktionsinstanz zurück, die von Expression Manager aufgerufen werden kann. Der clientseitige Expression Manager unterstützt sowohl lokale als auch Remote-Funktionen. Die vom Mapper zurückgegebene Funktionsinstanz verhält sich je nach Funktionstyp unterschiedlich:
    • Remote-Funktionen: Wenn der Mapper ein Präfix in der Form „REMOTE_<svc>“ und einen lokalen Namen erhält, gibt er eine dem Vorgang entsprechende Funktionsinstanz zurück, der denselben Namen wie der lokale Name auf dem Flex-Remote-Ziel mit ID „<svc>“ hat. Die erforderliche Remoting-Konfiguration wird in der Anwendung durch Bereitstellen einer geeigneten services-config.xml-Datei während der Kompilierung implementiert.

    • Lokale Funktionen: Wenn der Mapper ein Präfix und einen lokalen Namen erhält, versucht er, diese einer in einer ActionScript-Klasse definierten Methode zuzuordnen, wobei eine interne Zuweisung verwendet wird. Die Anwendung muss sicherstellen, dass die aufgelöste ActionScript-Klasse in der aktuellen ApplicationDomain verfügbar ist und einen NO-Argument-Konstruktor hat. Um die interne Zuweisung mit Werten zu füllen, können die beiden folgenden Verfahren (einzeln oder in Kombination) verwendet werden:

      • Die Anwendung kann in der von Expression Manager verwendeten Instanz von SimpleFunctionMapper addFunction() aufrufen, um der internen Zuweisung Einträge hinzuzufügen. Der erste Parameter der Methode ist die Funktionsreferenz in der Form, wie sie in Ausdrücken erscheint (ein String im Format „<Präfix>:<lokaler Name>“). Der zweite Parameter ist die ActionScript-Methode, der die Funktion zugeordnet wird (ein String im Format „<vollständiger ActionScript-Klassenname>:<Methodenname>“).

      • Die Anwendung kann die SimpleFunctionMapper-Instanz auch anweisen, diese Zuordnungen auf dem Server zu initialisieren. Rufen Sie dazu den SimpleFunctionMapper-Konstruktor mit dem Wert „true“ für den Parameter „initFromServer“ auf. Da der Serveraufruf asynchron ist, muss die Anwendung warten, bis die SimpleFunctionMapper-Instanz ein Ereignis des Typs serverInitializationSuccess auslöst. Erst danach kann die Instanz verwendet werden. Wenn der Serveraufruf fehlschlägt, löst die SimpleFunctionMapper-Instanz ein Ereignis des Typs „serverInitializationError“ aus, um dies der Anwendung zu melden. Für den Serveraufruf muss außerdem ein Flex-Remote-Ziel mit der ID „lc.exm.functionService“ geladen werden. Die Anwendung muss sicherstellen, dass die Konfiguration für dieses Ziel (und die zugehörigen Kanäle) durch Bereitstellung einer geeigneten services-config.xml-Datei bei der Kompilierung konfiguriert wird.

Benutzerdefinierte Remote-Funktionen hinzufügen

Sie können ein benutzerdefiniertes Bundle erstellen, um Ihre eigenen Remote-Funktionen zur Verwendung in Ausdrücken zu exportieren. Um ein benutzerdefiniertes Bundle zum Exportieren Ihrer eigenen Remote-Funktionen zu erstellen, führen Sie folgende Schritte aus:
  1. Stellen Sie sicher, dass die Expression Manager-Klassen, insbesondere das com.adobe.exm.expeval-Paket, in die Manifestdatei des Bundles importiert werden.

  2. Definieren Sie eine Schnittstelle für den OSGi-Dienst, die Methoden enthält, die zur Verwendung in Expression Manager exportiert werden sollen.

  3. Deklarieren Sie Methoden in der Schnittstelle und versehen Sie sie mit der Anmerkung „@ServiceMethod“ (com.adobe.exm.expeval.ServiceMethod). Expression Manager ignoriert alle Methoden, bei denen keine Anmerkungen vorhanden sind.

    Die ServiceMethod-Anmerkung verfügt über die folgenden optionalen Attribute, die ebenfalls festgelegt werden können:
    • enabled: Bestimmt, ob diese Methode aktiviert ist. Expression Manager ignoriert deaktivierte Methoden. Wenn Sie dieses Attribut nicht angeben, nimmt es den Standardwert „true“ an.

    • familyId: Legt die Familie (Gruppe) der Methode fest. Wenn dieses Attribut leer ist, geht Expression Manager davon aus, dass die Methode zur Standardfamilie gehört. Es ist keine Registrierung für Familien (außer der Standardeinstellung) vorhanden, um die Auswahl von Funktionen zu ermöglichen. Expression Manager erstellt die Registrierung dynamisch durch Zusammenführen aller Familien-IDs, die durch sämtliche von den verschiedenen Bundles exportierte Funktionen angegeben werden. Stellen Sie sicher, dass hier eine für Menschen lesbare ID angegeben wird, da diese auch in der Authoring-Benutzeroberfläche für die Ausdrücke angezeigt wird.

    • displayName: Ein für Menschen lesbarer Name für die Funktion. Dieser Name wird für die Anzeige in der Authoring-Benutzeroberfläche verwendet. Wenn dieses Attribut leer bleibt, erstellt Expression Manager einen Standardnamen aus dem Präfix und dem lokalen Namen der Funktion.

    • description: Eine detaillierte Beschreibung der Funktion. Diese Beschreibung wird für die Anzeige in der Authoring-Benutzeroberfläche verwendet. Wenn dieses Attribut leer bleibt, erstellt Expression Manager eine Standardbeschreibung aus dem Präfix und dem lokalen Namen der Funktion.

    Die Parameter der Methoden können ebenfalls mit Anmerkungen versehen werden (optional). Verwenden Sie hierfür die Anmerkung „@ServiceMethodParameter“ (com.adobe.exm.expeval.ServiceMethodParameter). Diese Anmerkung wird nur dazu verwendet, für Menschen lesbare Namen und Beschreibungen von Methodenparametern für die Verwendung in der Authoring-Benutzeroberfläche anzugeben.

  4. Stellen Sie sicher, dass die Parameter und Rückgabewerte der Methoden für die Schnittstelle zu den unterstützten Typen gehören. Eine Liste der unterstützten Typen finden Sie unter Allgemeine JSP-EL-Beispiele.

  5. Definieren Sie die Implementierung der Schnittstelle, konfigurieren Sie sie als Spring-Bean und exportieren Sie sie mithilfe von BluePrint als OSGi-Dienst, wobei Sie die folgenden speziellen Eigenschaften festlegen:
    <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>

    Der Eintrag exm.service=true meldet Expression Manager, dass der Dienst Remote-Funktionen enthält, die für die Verwendung in Ausdrücken geeignet sind. Der Wert für <Dienst-ID> muss ein gültiger Java-Bezeichner sein (alphanumerisch/$/_ ohne weitere Sonderzeichen). Dieser Wert bildet mit vorangestelltem Schlüsselwort REMOTE_ das Präfix für die Verwendung in Ausdrücken. Wenn beispielsweise in einer Schnittstelle die mit einer Anmerkung versehene Methode bar() vorhanden ist und die Dienst-ID in den Eigenschaften für den BluePrint-Dienst foo lautet, kann die Methode in Ausdrücken mithilfe von REMOTE_foo:bar() referenziert werden.

Benutzerdefinierte lokale Funktionen hinzufügen

Sie können ein benutzerdefiniertes Bundle erstellen, um Ihre eigenen lokalen Funktionen zur Verwendung in Ausdrücken zu exportieren. Führen Sie dazu die folgenden Schritte aus:
  1. Stellen Sie sicher, dass die Expression Manager-Klassen, insbesondere das com.adobe.exm.expeval-Paket, in die Manifestdatei des Bundles importiert werden.

  2. Für jede logische Funktion müssen sowohl eine statische Methode für eine Java-Klasse als auch eine entsprechende normale Methode für eine ActionScript-Klasse definiert sein. Für die lokale Funktion „f“ könnte z. B. die Java-Implementierung „com.foo.SomeJavaClass.fn()“ und die ActionScript-Implementierung „com.foo.SomeASClass.flexFn()“ verwendet werden.

  3. Packen Sie die Java-Klasse in das Bundle, das Sie zum Exportieren der lokalen Funktion verwenden, und stellen Sie sicher, dass sie in der Manifestdatei des Bundles als exportiert markiert ist. Andernfalls kann das Expression Manager-Bundle die Klasse nicht laden. Stellen Sie auf dem Client sicher, dass die ActionScript-Klasse in der ApplicationDomain zur Verfügung steht, in der die Expression Manager-Bibliotheken verwendet werden.

  4. Versehen Sie die Java-Implementierung der lokalen Funktion mit der Anmerkung „@LocalFunction“ (com.adobe.exm.expeval.LocalFunction). Expression Manager ignoriert Methoden, bei denen keine Anmerkungen vorhanden sind.

    Die LocalFunction-Anmerkung verfügt über die folgenden optionalen Attribute, die ebenfalls festgelegt werden können:
    • FlexClassName: Der vollständig qualifizierte Name der ActionScript-Klasse, die die Flex-Implementierung der lokalen Funktion hostet.

    • FlexMethodName: Der Name der ActionScript-Methode, die der Flex-Implementierung der lokalen Funktion entspricht.

    • enabled: Bestimmt, ob diese Methode aktiviert ist. Expression Manager ignoriert deaktivierte Methoden.

    • familyId: Legt die Familie (Gruppe) der Methode fest. Wenn dieses Attribut leer ist, geht Expression Manager davon aus, dass die Methode zur Standardfamilie gehört. Es ist keine Registrierung für Familien (außer der Standardeinstellung) vorhanden, um die Auswahl von Funktionen zu ermöglichen. Expression Manager erstellt die Registrierung dynamisch durch Zusammenführen des Satzes aller Familien-IDs, die durch sämtliche von den verschiedenen Bundles exportierte Funktionen angegeben werden. Stellen Sie sicher, dass hier eine für Menschen lesbare ID angegeben wird, da diese auch in der Authoring-Benutzeroberfläche für die Ausdrücke angezeigt wird.

    • displayName: Ein für Menschen lesbarer Name für die Funktion. Dieser Name wird für die Anzeige in der Authoring-Benutzeroberfläche verwendet. Wenn dieses Attribut leer bleibt, erstellt Expression Manager einen Standardnamen aus dem Präfix und dem lokalen Namen der Funktion.

    • description: Eine detaillierte Beschreibung der Funktion. Diese Beschreibung wird für die Anzeige in der Authoring-Benutzeroberfläche verwendet. Wenn dieses Attribut leer bleibt, erstellt Expression Manager eine Standardbeschreibung aus dem Präfix und dem lokalen Namen der Funktion.

    Die Parameter der Methoden können ebenfalls mit Anmerkungen versehen werden (optional). Verwenden Sie hierfür die Anmerkung „@LocalFunctionParameter“ (com.adobe.exm.expeval.LocalFunctionParameter). Diese Anmerkung wird nur dazu verwendet, für Menschen lesbare Namen und Beschreibungen von Methodenparametern für die Verwendung in der Authoring-Benutzeroberfläche anzugeben.

  5. Stellen Sie sicher, dass die Parameter und Rückgabewerte der Methoden für die Schnittstelle zu den unterstützten Typen gehören. Eine Liste der unterstützten Typen finden Sie unter Allgemeine JSP-EL-Beispiele.

  6. Definieren Sie im Spring-Kontext eine leere Bean des Typs „com.adobe.exm.expeval.LocalFunctionProviderImpl“ und weisen Sie ihr eine ID zu.

  7. Exportieren Sie die Bean als OSGi-Dienst mit den folgenden speziellen Eigenschaften:
    <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>

Stellen Sie sicher, dass die als Werte für die exm.local.function.entry.*-Schlüssel angegebenen Java-Klassen in der Manifestdatei des Host-Bundles exportiert werden, da Expression Manager sie andernfalls nicht laden kann. Die angegebenen Präfixe werden unverändert („as-is“) als Funktionspräfixe in Ausdrücken verwendet und müssen daher gültige Java-IDs sein. Wenn z. B. localFoo das Präfix für die Klasse com.foo.SomeJavaClass ist, hat die lokale Funktion in Ausdrücken die Form localFoo:fn(). Der lokale Name im Ausdruck ist mit dem Namen der Java-Methode identisch.

Ausdrücke mit einer benutzerdefinierten Funktion auswerten

Das folgende Codebeispiel veranschaulicht den Aufruf eines Ausdrucks, der eine benutzerdefinierte Funktion enthält:

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);

Bei der Auswertung von Ausdrücken wird dem Namen der Funktion der Schlüssel (fm1) als Präfix vorangestellt. Wenn eine „add“-Funktion aufgerufen wird, erhält diese in EL das Präfix „fm1“, z. B. „${fm1:add(number1, number2)}“.