Personnalisation du bloc de création Expression Manager

La fonctionnalité du bloc de création Expression Manager est exposée à travers un ensemble de beans Spring et de composants Flex. Puisque les services sont exposés en tant que beans Spring, vous pouvez les remplacer par votre propre implémentation personnalisée.

Personnalisation du service ExpressionEvaluator par défaut côté client

Si vous souhaitez modifier le service ExpressionEvaluator sans le remplacer par une nouvelle implémentation personnalisée, vous pouvez personnaliser l’implémentation par défaut. L’implémentation par défaut du service ExpressionEvaluator nécessite une instance du résolveur de variable et du mappeur de fonction. Ces instances sont utilisées pour récupérer les valeurs des variables et résoudre les références aux fonctions lors de l’évaluation des expressions. Vous pouvez les configurer à l’aide des propriétés suivantes du service ExpressionEvaluator par défaut :
  • variableResolver : le résolveur de variable côté client est une représentation de l’interface com.adobe.solutions.exm.runtime.IVariableResolver. Cette interface est plus complexe que son homologue côté serveur. En plus de l’API standard permettant de renvoyer la valeur d’une variable, elle comporte également une API pour la définition de la valeur d’une variable utilisée par Expression Manager. Cette API est utilisée pour la définition de valeurs de variables cible, lorsque les variables cible sont également transmises au gestionnaire avec les expressions. Une implémentation de l’interface du résolveur distribue également un événement (une instance de com.adobe.solutions.exm.runtime.VariableChangeEvent) de type variableChangeEvent. L’événement est distribué à chaque fois que la valeur de l’une des variables gérées par le résolveur change. Expression Manager utilise cet événement pour recalculer les expressions comprenant la variable modifiée. Cet événement est supposé contenir le nom complet de la variable dont la valeur a changé, l’ancienne valeur et la nouvelle valeur.

    Expression Manager fournit une implémentation de résolveur simple (com.adobe.solutions.exm.runtime.impl.SimpleVariableResolver), appuyée par un dictionnaire, et utilise des noms de variables complets en tant que clés dans le dictionnaire. Cette implémentation est probablement utilisable uniquement pour les utilisations les plus triviales.

  • functionMapper : le mappeur de fonction côté client utilise l’interface com.adobe.solutions.exm.runtime.IFunctionMapper. Cette interface présente le même contrat que son homologue côté serveur. A partir d’un préfixe de fonction et d’un nom local, elle renvoie une instance de fonction pouvant être appelée par Expression Manager. Le gestionnaire d’expression côté client prend en charge à la fois les fonctions distantes et locales. L’instance de fonction renvoyée par le mappeur se comporte différemment selon le type de fonction :
    • Fonctions distantes : reçoivent un préfixe de la forme REMOTE_<svc> et un nom local. Le mappeur renvoie une instance de fonction correspondant à l’opération avec le même nom que le nom local que la destination Flex Remoting avec l’ID <svc>. La configuration Remoting requise est implémentée dans l’application en fournissant un fichier services-config.xml adéquat lors de la compilation.

    • Fonctions locales : ayant reçu un préfixe et un nom local, le mappeur essaie de les résoudre en une méthode définie sur une classe ActionScript par consultation d’un mappage interne. L’application doit s’assurer que la classe ActionScript résolue est disponible dans le domaine ApplicationDomain actuel et présente un constructeur sans argument. Ce mappage interne peut être renseigné de l’une des façons suivantes (ou une combinaison des deux) :

      • L’application peut appeler addFunction() sur l’instance SimpleFunctionMapper utilisée par le gestionnaire d’expression pour l’ajout d’entrées au mappage interne. Le premier paramètre de la méthode est la référence à la fonction telle qu’elle figure dans les expressions (une chaîne de la forme « <préfixe>:<nom_local> »). Le second paramètre est la méthode ActionScript vers laquelle la fonction établit une correspondance (une chaîne de la forme « <nom_de_classe_ActionScript_complet>:<méthode1> »).

      • L’application peut également faire initialiser ces mappages par l’instance SimpleFunctionMapper à partir du serveur. Pour ce faire, appelez le constructeur SimpleFunctionMapper avec le paramètre initFromServer = true. L’appel du serveur est asynchrone, par conséquent l’application doit attendre que l’instance SimpleFunctionMapper distribue un objet event de type serverInitializationSuccess avant de pouvoir utiliser l’instance. Si l’appel du serveur échoue, l’instance SimpleFunctionMapper distribue un événement de type « serverInitializationError » pour notifier l’application. Par ailleurs, l’appel du serveur implique le chargement d’une destination Flex Remoting avec l’ID « lc.exm.functionService ». L’application doit vérifier que la configuration pour cette destination (et ses canaux) est définie en fournissant un fichier services-config.xml au moment de la compilation.

Ajout de fonctions distantes personnalisées

Vous pouvez créer un regroupement personnalisé pour exporter vos propres fonctions distantes à utiliser dans les expressions. Pour créer un regroupement personnalisé afin d’exporter vos propres fonctions distantes, effectuez les tâches suivantes :
  1. Assurez-vous que les classes d’Expression Manager, en particulier le package com.adobe.exm.expeval, sont importées dans le manifeste du lot.

  2. Définissez une interface pour le service OSGi, contenant des méthodes à exporter pour l’utilisation par Expression Manager.

  3. Déclarez des méthodes sur l’interface et annotez-les avec l’annotation @ServiceMethod (com.adobe.exm.expeval.ServiceMethod). Expression Manager ne tient pas compte des méthodes sans annotation.

    L’annotation ServiceMethod présente les attributs facultatifs suivants, qui peuvent également être définis :
    • enabled : détermine si cette méthode est activée. Expression Manager ignore les méthodes désactivées. Si elle n’est pas spécifiée, la valeur par défaut de cet attribut est true.

    • familyId : indique la famille (groupe) de la méthode. Si cet attribut n’est pas spécifié, Expression Manager présume que la méthode appartient à la famille par défaut. Il n’y a aucun registre de familles (à l’exception de celui par défaut) d’où sont sélectionnées les fonctions. Expression Manager crée dynamiquement le registre à partir de l’union de tous les ID de famille, spécifiés par l’ensemble des fonctions exportées par les divers regroupements. Assurez-vous que l’ID spécifiée ici est suffisamment intelligible, car elle s’affiche également dans l’interface utilisateur de création d’expressions.

    • displayName : nom intelligible de la fonction. Ce nom apparaît dans l’interface utilisateur de création. Si cet attribut n’est pas spécifié, Expression Manager crée un nom par défaut à l’aide du préfixe et du nom local de la fonction.

    • description : description détaillée de la fonction. Cette description apparaît dans l’interface utilisateur de création. Si l’attribut est vide, Expression Manager construit une description par défaut à l’aide du préfixe et du nom local de la fonction.

    Les paramètres des méthodes peuvent éventuellement être annotés à l’aide de l’annotation @ServiceMethodParameter (com.adobe.exm.expeval.ServiceMethodParameter). Cette annotation est uniquement utilisée pour spécifier les noms intelligibles et les descriptions des paramètres de méthode à utiliser dans l’interface utilisateur de création.

  4. Vérifiez que les paramètres et les valeurs renvoyées des méthodes d’interface appartiennent à l’un des types pris en charge. Pour consulter une liste de types pris en charge, voir Exemples courants d’EL JSP.

  5. Définissez l’implémentation de l’interface, configurez-la comme bean Spring et exportez-la sous forme de service OSGi via BluePrint avec les propriétés spéciales suivantes :
    <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>

    L’entrée exm.service=true indique à Expression Manager que le service contient des fonctions distantes adaptées à une utilisation dans les expressions. La valeur <id_service> doit être un identifiant Java valide (alphanumérique/$/_ sans aucun autre caractère spécial). Cette valeur, précédée du mot-clé REMOTE_, forme le préfixe utilisé au sein des expressions. Par exemple, pour une interface avec une méthode annotée bar() et dont l’ID de service dans les propriétés du service BluePrint est foo, la méthode peut être référencée à l’intérieur d’expressions par REMOTE_foo:bar().

Ajout de fonctions locales personnalisées

Vous pouvez créer un regroupement personnalisé afin d’exporter vos propres fonctions locales pour les utiliser à l’intérieur d’expressions. Pour créer un regroupement personnalisé afin d’exporter vos propres fonctions locales, effectuez les tâches suivantes :
  1. Vérifiez que les classes Expression Manager, en particulier le package com.adobe.exm.expeval, sont importées dans le manifeste du regroupement.

  2. Pour chaque fonction locale logique, assurez-vous qu’une méthode statique est définie sur une classe Java et qu’une méthode normale équivalente est définie sur une classe ActionScript. Par exemple, pour la fonction locale f, supposons que l’implémentation Java est com.foo.SomeJavaClass.fn() et que l’implémentation ActionScript est com.foo.SomeASClass.flexFn().

  3. Créez un package de la classe Java dans le regroupement qui exporte la fonction locale et vérifiez qu’elle est désignée comme exportée dans le manifeste du regroupement. Dans le cas contraire, le regroupement Expression Manager ne peut pas charger la classe. Sur le côté client, assurez-vous que la classe ActionScript est disponible dans le domaine ApplicationDomain d’utilisation des bibliothèques Expression Manager.

  4. Annotez l’implémentation Java de la fonction locale avec l’annotation @LocalFunction (com.adobe.exm.expeval.LocalFunction). Expression Manager ne tient pas compte des méthodes sans annotation.

    L’annotation LocalFunction présente les attributs facultatifs suivants, qui peuvent également être définis :
    • FlexClassName : nom complet de la classe ActionScript hébergeant l’implémentation Flex de la fonction locale.

    • FlexMethodName : nom de la méthode ActionScript correspondant à l’implémentation Flex de la fonction locale.

    • enabled : détermine si cette méthode est activée. Expression Manager ignore toute méthode désactivée.

    • familyId : indique la famille (groupe) de méthodes. Si cet attribut n’est pas spécifié, Expression Manager présume que la méthode appartient à la famille par défaut. Il n’existe aucun registre des familles (à l’exception de la famille par défaut) à partir duquel les fonctions sont choisies. Expression Manager crée dynamiquement le registre à partir de l’union de tous les ID de famille, spécifiés par l’ensemble des fonctions exportées par les divers regroupements. Assurez-vous que l’ID spécifiée ici est suffisamment intelligible, car elle s’affiche également dans l’interface utilisateur de création d’expressions.

    • displayName : nom intelligible de la fonction. Ce nom apparaît dans l’interface utilisateur de création. Si cet attribut n’est pas spécifié, Expression Manager crée un nom par défaut à l’aide du préfixe et du nom local de la fonction.

    • description : description détaillée de la fonction. Cette description apparaît dans l’interface utilisateur de création. Si l’attribut est vide, Expression Manager construit une description par défaut à l’aide du préfixe et du nom local de la fonction.

    Les paramètres des méthodes peuvent éventuellement être annotés à l’aide de l’annotation @LocalFunctionParameter (com.adobe.exm.expeval.LocalFunctionParameter). Cette annotation est uniquement utilisée pour spécifier les noms intelligibles et les descriptions des paramètres de méthode à utiliser dans l’interface utilisateur de création.

  5. Vérifiez que les paramètres et les valeurs renvoyées des méthodes d’interface appartiennent à l’un des types pris en charge. Pour consulter une liste de types pris en charge, voir Exemples courants d’EL JSP.

  6. Définissez un bean vide de type com.adobe.exm.expeval.LocalFunctionProviderImpl dans le contexte Spring et attribuez-lui un ID.

  7. Exportez le bean sous forme de service OSGi avec les propriétés spéciales suivantes :
    <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>

Assurez-vous que les classes Java spécifiées en tant que valeurs pour les clés exm.local.function.entry.* sont exportées dans le manifeste du regroupement hôte. Dans le cas contraire, le regroupement Expression Manager ne peut pas les charger. Les préfixes spécifiés sont utilisés en l’état comme préfixes de fonction dans les expressions et doivent par conséquent être des identifiants Java valides. Par exemple, si localFoo est le préfixe de la classe com.foo.SomeJavaClass, la fonction locale peut utiliser la notation localFoo:fn() dans les expressions. Le nom local dans l’expression est identique au nom de la méthode Java.

Evaluation d’une expression avec une fonction personnalisée

L’exemple de code suivant illustre la manière d’appeler une expression contenant une fonction personnalisée :

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

Lors de l’évaluation des expressions, le nom de la fonction doit être précédé de la clé (fm1). Lors de l’appel d’une fonction « add », EL ajoute le préfixe fm1, par exemple « ${fm1:add(nombre1, nombre2)} ».