Show Menu
SUJETS×

API orientées données

Les API orientées données permettent d'adresser le modèle de données dans son intégralité.

Principe du modèle de données

Adobe Campaign ne propose pas une API de lecture dédiée par entité (pas de fonction de type getRecipient, getDelivery, etc.). Vous devez utiliser les méthodes de lecture et modification des données, QUERY & WRITER, pour accéder aux données du modèle.
Adobe Campaign permet de gérer les collections : un appel (query) permet de récupérer un ensemble d'informations collectées dans toute la base. Contrairement à un accès aux données en mode SQL, les API Adobe Campaign ne renvoient pas des colonnes de données mais une arborescence XML. Ainsi, Adobe Campaign crée des documents composites avec toutes les données collectées.
Ce mode de fonctionnement ne propose pas un mapping un pour un entre les attributs et éléments des documents XML et les colonnes des tables de la base de données.
Les documents XML sont stockés dans des champs de type MEMO de la base.

Description du modèle

Vous devez impérativement connaître le modèle de données Adobe Campaign afin d'adresser correctement les champs de la base de données dans vos scripts.
Pour obtenir une présentation du modèle de données, consultez la section Description du modèle de données d’Adobe Campaign .
Pour générer sa structure, reportez-vous l’article suivant : Comment générer un modèle de données ou un dictionnaire de données .

Query et Writer

Le schéma introductif suivant montre les échanges bas niveaux pour la lecture (ExecuteQuery) et l'écriture (Writer) entre la base de données et un client (pages web ou console cliente Adobe Campaign).

ExecuteQuery

Pour les colonnes et les conditions, vous pouvez utiliser des Query.
Vous pouvez ainsi isoler le SQL sous-jacent. Le langage des requêtes est indépendant du moteur sous-jacent : certaines fonctions vont être re-mappées, ce qui peut générer de nombreux ordres SELECT SQL.
La méthode ExecuteQuery est présentée dans ExecuteQuery (xtk:queryDef) .

Write

Les commandes Write permettent d'écrire des documents simples ou complexes, avec des écritures dans une ou plusieurs tables de la base.
Les API transactionnelles permettent de gérer les réconciliations via la commande updateOrInsert : une même commande permet la création ou la mise à jour des données. Vous pouvez également paramétrer la fusion ( merge ) des modifications : ce mode de fonctionnement permet d'autoriser la mise à jour partielle.
La structure XML propose une vision logique des données et permet de s'affranchir de la structure physique de la table SQL.
La méthode Write est présentée dans Write / WriteCollection (xtk:session) .

ExecuteQuery (xtk:queryDef)

Cette méthode permet d'effectuer des requêtes à partir de données associées à un schéma. Elle prend en paramètres une chaîne d'authentification (nécéssité d'être loggé) et un document XML décrivant la requête à soumettre. Le paramètre de retour est un document XML contenant le résultat de la requête au format du schéma sur lequel porte la requête.
Définition de la méthode "ExecuteQuery" dans le schéma "xtk:queryDef" :
<method name="ExecuteQuery" const="true">
  <parameters>
    <param desc="Output XML document" name="output" type="DOMDocument" inout="out"/>
  </parameters>
</method>

Cette méthode est de type "const", les paramètres en entrée sont compris dans un document XML au format du schéma "xtk:queryDef".

Format du document XML de la requête en entrée

La structure du document XML de la requête est décrite dans le schéma "xtk:queryDef ", ce document décrit les différentes clauses d'une requête SQL : "select", "where", "order by", "group by", "having".
<queryDef schema="schema_key" operation="operation_type">
  <select>
    <node expr="expression1">
    <node expr="expression2">
    ...
  </select>
  <where> 
    <condition expr="expression1"/> 
    <condition expr="expression2"/>
    ... 
  </where>
  <orderBy>
    <node expr="expression1">
    <node expr="expression2">
    ...
  </orderBy>
  <groupBy>
    <node expr="expression1">
    <node expr="expression2">
    ...
  </groupBy>
  <having>
    <condition expr="expression1"/> 
    <condition expr="expression2"/>
    ...
  </having>
</queryDef>

Une sous-requête ( <subquery> ) peut être définie dans un élément <condition> . La syntaxe d’un élément <subquery> repose sur la syntaxe d’un <querydef> .
Exemple d’un <subquery> : </subquery>
<condition setOperator="NOT IN" expr="@id" enabledIf="$(/ignored/@ownerType)=1">
  <subQuery schema="xtk:operatorGroup">
     <select>
       <node expr="[@operator-id]" />
     </select>
     <where>
       <condition expr="[@group-id]=$long(../@owner-id)"/>
     </where>
   </subQuery>
</condition>  
  

Une requête doit référencer un schéma de départ à partir de l'attribut schema .
Le type d'opération souhaité est renseigné dans l'attribut operation et contient une des valeurs suivantes :
  • get : récupère un enregistrement de la table, et retourne une erreur si la donnée n'existe pas,
  • getIfExists : récupère un enregistrement de la table, et retourne un document vide si la donnée n'existe pas,
  • select : crée un curseur pour retourner plusieurs enregistrements, et retourne un document vide si aucune données,
  • count : retourne un comptage des données.
La syntaxe XPath sert à localiser les données en fonction du schéma de départ. Pour plus d’informations sur XPath, voir Schémas de données .

Exemple avec l'opération 'get'

Récupère le nom et le prénom d'un destinataire (schéma "nms:recipient") avec un filtre sur l'email.
<queryDef schema="nms:recipient" operation="get">
  <!-- fields to retrieve -->
  <select>
    <node expr="@firstName"/>
    <node expr="@lastName"/>
  </select> 

  <!-- condition on email -->
  <where>  
    <condition expr="@email= 'john.doe@aol.com'"/>
  </where>
</queryDef>

Exemple avec l'operation 'select'

Retourne la liste des destinataires filtrés sur un dossier et le domaine de l'email avec un tri descendant sur la date de naissance.
<queryDef schema="nms:recipient" operation="select">
  <select>
    <node expr="@email"/>
    <!-- builds a string with the concatenation of the last name and first name separated by a dash -->      
    <node expr="@lastName+'-'+@firstName"/>
    <!-- get year of birth date -->
    <node expr="Year(@birthDate)"/>
  </select> 

  <where>  
     <condition expr="[@folder-id] = 1234 and @domain like 'Adobe%'"/>
  </where>

  <!-- order by birth date -->
  <orderBy>
    <node expr="@birthDate" sortDesc="true"/> <!-- by default sortDesc="false" -->
  </orderBy>
</queryDef>

Les expressions peuvent être des champs simples ou des expressions complexes telles que les opérations arithmétiques ou la concaténation de chaînes.
Pour limiter le nombre d’enregistrements à retourner, il faut ajouter l’attribut lineCount à l’élément <querydef> .
Pour limiter à 100 le nombre d'enregistrements retournés par la requête :
<queryDef schema="nms:recipient" operation="select" lineCount="100">
...

Pour récupérer les 100 enregistrements suivants, lancer de nouveau la même requête en ajoutant l'attribut startLine .
<queryDef schema="nms:recipient" operation="select" lineCount="100" startLine="100">
...

Exemple avec l'opération 'count'

Pour compter le nombre d'enregistrements sur une requête :
<queryDef schema="nms:recipient" operation="count"">
  <!-- condition on the folder and domain of the e-mail -->
  <where>  
    <condition expr="[@folder-id] = 1234" and @domain like 'Adobe%'"/>
  </where>
</queryDef>

Encore une fois, nous utilisons la condition de l’exemple précédent. Les <select> et clauses ne sont pas utilisés. </select>

Groupement de données

Pour récupérer les adresses email référencées plus d'une fois :
<queryDef schema="nms:recipient" operation="select">
  <select>
    <node expr="@email"/>
    <node expr="count(@email)"/>
  </select>

  <!-- e-mail grouping clause -->
  <groupby>
    <node expr="@email"/>
  </groupby>

  <!-- grouping condition -->
  <having>
    <condition expr="count(@email) > 1"/>
  </having>

</queryDef>

On peut simplifier la requête en renseignant l'attribut groupBy directement sur le champ à grouper :
<select>
  <node expr="@email" groupBy="true"/>
</select>

Il n’est plus nécessaire de renseigner l’élément <groupby> .

Parenthésage dans les conditions

Voici deux exemples de parenthésages sur une même condition.
  • La version simple en une seule expression :
    <where>
      <condition expr="(@age > 15 or @age <= 45) and  (@city = 'Newton' or @city = 'Culver City') "/>
    </where>
    
    
  • La version structurée avec des éléments <condition>  :
    <where>
      <condition bool-operator="AND">
        <condition expr="@age > 15" bool-operator="OR"/>
        <condition expr="@age <= 45"/>
      </condition>
      <condition>
        <condition expr="@city = 'Newton'" bool-operator="OR"/>
        <condition expr="@city = 'Culver City'"/>
      </condition>
    </where>
    
    
Il est possible de remplacer l'opérateur 'OR' avec l'opérateur 'IN' lorsque plusieurs conditions portent sur le même champ :
<where>
  <condition>
    <condition expr="@age IN (15, 45)"/>
    <condition expr="@city IN ('Newton', 'Culver City')"/>
  </condition>
</where>

Cette syntaxe simplifie la requête lorsque plus de deux données sont utilisées dans la condition.

Binding des paramètres de la clause 'where' et 'select'

Le binding des paramètres laisse le moteur fixer les valeurs des paramètres utilisés dans la requête. Ceci est très utile car l'échappement des valeurs est à la charge du moteur et on bénéficie en plus d'un cache sur les paramètres à récupérer.
Lorsqu’une requête est créée, les valeurs « liées » sont remplacées par un caractère (? dans ODBC, #[index]# dans postgres...) dans le corps de la requête SQL.
<select>
  <!--the value will be bound by the engine -->
  <node expr="@startDate = #2002/02/01#"/>                   
  <!-- the value will not be bound by the engine but visible directly in the query -->
  <node expr="@startDate = #2002/02/01#" noSqlBind="true"/> 
</select>

Pour ne pas binder un paramètre, il faut renseigner l'attribut "noSqlBind" avec la valeur "true".
Dans le cas où la requête comprend des instructions du type "order-by" ou "group-by", les moteurs de base de données ne peuvent pas "binder" les valeurs. Il est donc indispensable de placer dans la même requête l'attribut @noSqlBind="true" sur les instructions "select" et/ou "where".

Astuce pour construire une requête :

Pour vous aider à trouver la syntaxe d'une requête, vous pouvez mettre au point la requête à partir du requêteur générique dans la console cliente Adobe Campaign (menu Outils/Requêteur générique... ). Pour cela :
  1. Sélectionnez les données à récupérer :
  2. Définissez le critère de filtrage :
  3. Exécutez la requête et appuyez sur les touches CTRL+F4 pour visualiser le code source de la requête.

Format du document de sortie

Le paramètre de retour est un document XML au format du schéma associé à la requête.
Exemple de retour à partir du schéma "nms:recipient" sur une opération de type "get" :
<recipient email="john.doe@adobe.com" lastName"Doe" firstName="John"/>

Sur une opération de type "select", le document retourné est une énumération d'éléments :
<!-- the name of the first element does not matter -->
<recipient-collection>   
  <recipient email="john.doe@adobe.com" lastName"Doe" firstName="John"/>
  <recipient email="peter.martinez@adobe.com" lastName"Martinez" firstName="Peter"/>
  <recipient...
</recipient-collection>  

Exemple de document de retour sur une opération de type "count" :
<recipient count="3"/>

Alias

Un alias permet de modifier l'emplacement des données dans le document en sortie. L'attribut alias doit être renseigné avec un XPath sur le champ correspondant.
<queryDef schema="nms:recipient" operation="get">
  <select>
    <node expr="@firstName" alias="@firstName"/>
    <node expr="@lastName"/>
    <node expr="[folder/@label]" alias="@My_folder"/>
  </select> 
</queryDef>

Retourne :
<recipient My_folder="Recipients" First name ="John" lastName="Doe"/>

A la place de :
<recipient firstName="John" lastName="Doe">
  <folder label="Recipients"/>
</recipient>

Exemple de messages SOAP

  • Requête:
    <?xml version='1.0' encoding='ISO-8859-1'?>
    <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='http://xml.apache.org/xml-soap' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
      <SOAP-ENV:Body>
        <ExecuteQuery xmlns='urn:xtk:queryDef' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
          <__sessiontoken xsi:type='xsd:string'/>
          <entity xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
            <queryDef operation="get" schema="nms:recipient" xtkschema="xtk:queryDef">
              <select>
                <node expr="@email"/>
                <node expr="@lastName"/>
                <node expr="@firstName"/>
              </select>
              <where>
                <condition expr="@id = 3599"/>
              </where>
            </queryDef>
          </entity>
        </ExecuteQuery>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    
    
  • Réponse :
    <?xml version='1.0' encoding='ISO-8859-1'?>
    <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='http://xml.apache.org/xml-soap' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
      <SOAP-ENV:Body>
        <ExecuteQueryResponse xmlns='urn:xtk:queryDef' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
          <pdomOutput xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
            <recipient email="john.doe@adobe.com" lastName"Doe" firstName="John"/>
          </pdomOutput>
        </ExecuteQueryResponse>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    
    

Write / WriteCollection (xtk:session)

Ces services permettent l'insertion/la mise à jour/la suppression d'une entité (méthode "Write") ou d'une collection d'entités (méthode "WriteCollection").
Les entités à mettre à jour sont associées à un schéma de données. Les paramètres en entrée sont une chaîne d'authentification (nécéssité d'être loggé) et un document XML contenant les données à mettre à jour.
Ce document est complété par des instructions permettant de paramétrer les procédures d'écriture.
L'appel ne retourne pas de données, hormis les erreurs.
Définition des méthodes "Write" et "WriteCollection" dans le schéma "xtk:session" :
<method name="Write" static="true">
  <parameters>
    <param name="doc" type="DOMDocument" desc="Difference document"/>
  </parameters>
</method>
<method name="WriteCollection" static="true">
  <parameters>
    <param name="doc" type="DOMDocument" desc="Difference collection document"/>
  </parameters>
</method>

Cette méthode est de type "static", les paramètres en entrée sont compris dans un document XML au format du schéma à mettre à jour.

Présentation

La réconciliation des données s'opère à partir de la définition des clés renseignées dans le schéma associé. La procédure d'écriture va rechercher la première clé éligible en fonction des données renseignées dans le document en entrée. L'entité est insérée ou mise à jour en fonction de son existence dans la base de données.
La clé du schéma de l'entité à mettre à jour est renseignée à partir de l'attribut xtkschema .
La clé de réconciliation peut être forcée avec l'attribut _key contenant la liste des XPath qui composent la clé (séparés par une virgule).
Il est possible de forcer le type d'opération en renseignant l'attribut _operation avec les valeurs suivantes :
  • insert : force l'insertion de l'enregistrement (la clé de réconciliation n'est pas utilisée),
  • insertOrUpdate : met à jour ou insère l'enregistrement en fonction de la clé de réconciliation (mode par défaut),
  • update : met à jour l'enregistrement, ne fait rien si la donnée n'existe pas,
  • delete : supprime les enregistrements,
  • none : utilisé uniquement pour la réconciliation de lien, sans mise à jour ni insertion.

Exemple avec la méthode 'Write'

Mise à jour ou insertion d'un destinataire (opération "insertOrUpdate" implicite) avec son email, sa date de naissance et sa ville :
<recipient xtkschema="nms:recipient" email="john.doe@adobe.com" birthDate="1956/05/04" folder-id=1203 _key="@email, [@folder-id]">
  <location city="Newton"/>
</recipient>

Suppression d'un destinataire :
<recipient xtkschema="nms:recipient" _operation="delete" email="rene.dupont@adobe.com" folder-id=1203 _key="@email, [@folder-id]"/>

Dans le cas d'une opération en suppression, le document en entrée ne doit contenir que les champs qui composent la clé de réconciliation.

Exemple avec la méthode 'WriteCollection'

Mise à jour ou insertion sur plusieurs destinataires :
<recipient-collection xtkschema="nms:recipient">    
  <recipient email="john.doe@adobe.com" firstName="John" lastName="Doe" _key="@email"/>
  <recipient email="peter.martinez@adobe.com" firstName="Peter" lastName="Martinez" _key="@email"/>
  <recipient ...
</recipient-collection>

Eléments de collections XML

Par défaut, pour mettre à jour les éléments de collection XML, il faut renseigner tous les éléments de collection. Les données de la base seront remplacées par les données du document en entrée. Si le document contient uniquement les éléments à mettre à jour, vous devez renseigner l'attribut "_operation" sur tous les éléments de collection à mettre à jour afin de forcer la fusion (merge) avec les données XML de la base.

Exemple de messages SOAP

  • Requête:
    <?xml version='1.0' encoding='ISO-8859-1'?>
    <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='http://xml.apache.org/xml-soap' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
      <SOAP-ENV:Body>
        <Write xmlns='urn:xtk:persist' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
          <__sessiontoken xsi:type='xsd:string'/>
          <domDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
            <recipient xtkschema="nms:recipient" email="rene.dupont@adobe.com" firstName="René" lastName="Dupont" _key="@email">
          </domDoc>
        </Write>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    
    
  • Réponse :
    <?xml version='1.0' encoding='ISO-8859-1'?>
    <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='http://xml.apache.org/xml-soap' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
      <SOAP-ENV:Body>
        <WriteResponse xmlns='urn:' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
        </WriteResponse>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    
    
    Retour avec erreur :
    <?xml version='1.0'?>
    <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
      <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
          <faultcode>SOAP-ENV:Server</faultcode>
          <faultstring xsi:type="xsd:string">Error while executing the method 'Write' of service 'xtk:persist'.</faultstring>
          <detail xsi:type="xsd:string">PostgreSQL error: ERROR:  duplicate key violates unique constraint &quot;nmsrecipient_id&quot;Impossible to save document of type 'Recipients (nms:recipient)'</detail>
        </SOAP-ENV:Fault>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>