Utilitaires
Scripts
Divers
Jeux
Rechercher
Quillevere.net
Réflexions informatiques

Astuces sur Talend

04/06/2020
Quelques techniques et extraits de code qui peuvent aider sur des projets Talend.

Afficher le contenu du globalMap

La variable globalMap est un tableau permettant de stocker en mémoire les données du traitement en cours. Voici comment afficher son contenu :

java.util.Iterator<String> it = globalMap.keySet().iterator();
while(it.hasNext())
    {
    String key = it.next().toString();
    String value = globalMap.get(key)==null ? "null" : globalMap.get(key).toString();
    System.out.println(" - " + key + " = " + value);
    }

Pour afficher ces mêmes valeurs mais triées dans l'ordre croissant des propriétés :

java.util.Iterator<String> it = globalMap.keySet().iterator();
java.util.List<String> liste = new java.util.ArrayList();
while(it.hasNext())
    {
    String key =it.next().toString();
    liste.add(key + " = " + (globalMap.get(key)==null ? "<null>" : globalMap.get(key).toString()));
    }

java.util.Collections.sort(liste);
for (int i=0; i<liste.size(); i++)
 log.info(" - {}", liste.get(i));

Ajouter un numéro incrémenté sur chaque ligne d'un flux

  • Ajouter un TMap sur le job
  • Placer ceci sur la variable contenant le numéro auto : Numeric.sequence("ordre",1,1)

Ne garder que la dernière ligne sur des lignes dupliquées

Le tUniqRow ne conserve que la première ligne des lignes dupliquées. Pour faire l'inverse, il faut inverser l'ordre des lignes.

  • Ajouter un champ contenant un numéro incrémenté sur chaque ligne (astuce précédente)
  • Faire un tri inversé sur le champ ajouté (tSortRow)
  • Faire un tUniqRow

Incrémenter un compteur et récupérer sa valeur

// Initialise le compteur
globalMap.put("NbLignes", 0);
// Incrémente la valeur
globalMap.put("NbLignes", ((Integer)globalMap.get("NbLignes"))+1);
// Récupère la valeur
Integer compteur=((Integer)globalMap.get("NbLignes"));

Récupérer une donnée précise d'un sous-job

  • Dans le sous-job :
    • Créer une variable de contexte : globaMapParent (de type Object)
    • Ajouter un tJavaRow avec le code suivant :
      // Affectation
      if (context.globaMapParent instanceof java.util.Map)
      ((java.util.Map) context.globaMapParent).put("id_classe", input_row.id);
  • Dans le job principal :
    • Ajouter un tJava avec le code suivant :
      // Crée un global map pour envoi des données enfant
      globalMap.put("globalMapEnfant", new java.util.concurrent.ConcurrentHashMap());
    • Sur le tRunJob, affecter le paramètre
      globalMapParent = globalMap.get("globalMapEnfant");

Appliquer une condition Run If sur chaque ligne d'un flux

Si vous utilisez la condition Run If sur chaque Row d'un flux, seulement la dernière ligne du flux sera traitée dans la condition. Le traitement sera scindé en deux parties : la première partie avant le Run If et la seconde après.

Pour pouvoir appliquer une condition sur chaque ligne, il faut utiliser le composant tFlowToIterate, branché vers un composant de démarrage (un tJava par exemple). Ensuite, placez entre les deux la relation Run If. Le schéma ci-dessous présente la situation :

Le flux complet sera ainsi traité du début à la fin, en appliquant le Run If sur chaque ligne.

Pour récupérer les données lues, cochez sur le tFlowToIterate la case "Utilisation par défaut : (clé, valeur) en variable globale". Les données seront alors accessibles selon le nommage du flux (dans l'exemple ci-dessus, avec globalMap.get("row1.XXX"), où XXX sera le nom de la variable.

Exécuter une requête SQL

Le composant tDBRow permet d'exécuter certaines requêtes particulières. Si besoin, voici un code qui récupère la connexion établie au préalable et exécute aussi une requête :

java.sql.Statement statement = ((java.sql.Connection) globalMap.get("conn_tDBConnection_1")).createStatement();statement.execute("ALTER SEQUENCE ma_table RESTART WITH 1;");statement.close();

Trier les lignes par date avec NULL au début ou en fin de liste

Le composant TSortRow permet de trier le flux selon un champ spécifique. Cependant, dans certains cas, si on souhaite avoir les NULL en fin de liste ou en en début de liste, le composant ne propose pas de solution directe. Voici comment le gérer pour un champ date :

  • Lors d'un tri par dates décroissantes, pour avoir le NULL en fin de liste, spécifiez "Tri Date"
  • Lors d'un tri par dates décroissantes, pour avoir le NULL en début de liste, spécifiez "Tri Alpha"
  • Lors d'un tri par dates croissantes, pour avoir le NULL en fin de liste, spécifiez "Tri Alpha"
  • Lors d'un tri par dates croissantes, pour avoir le NULL en début de liste, spécifiez "Tri Date"

Afficher dans les logs le nombre de lignes en cours de traitement

Voici une technique pour afficher dans les logs ou la console le nombre de lignes actuellement traitées, afin de donner du retour pendant un traitement long. En cas de lecture d'une requête renvoyant beaucoup de résultats, il est préférable d'utiliser un curseur (sur un tDBInput, cochez 'Utiliser un curseur).

  • Créer les 4 variables de contexte suivantes :
    Nom Type Commentaire
    nb_lignes_traitees_totales LONG Nombre de lignes totales
    nb_lignes_traitees_sequence INT Nombre de lignes traitées dans la séquence actuelle
    nb_lignes_par_sequence INT Nombre de lignes traitées entre 2 mesures
    date_demarrage_sequence LONG Date de démarrage des mesures
  • Dans le prejob ou au début du traitement, initialisez les valeurs de ces variables
    context.nb_lignes_traitees_totales=0L;
    context.nb_lignes_traitees_sequence=0;
    context.nb_lignes_par_sequence=10;
    context.date_demarrage_sequence=System.currentTimeMillis();
  • Au niveau du flux où vous souhaitez afficher le nombre de lignes, ajoutez un tJavaRow, générez le code pour la copie des champs du flux puis ajoutez le code suivant :
    context.nb_lignes_traitees_sequence++;

    if (context.nb_lignes_traitees_sequence % context.nb_lignes_par_sequence==0) {
        context.nb_lignes_traitees_totales+=context.nb_lignes_traitees_sequence;

        log.info(" - {} lignes traitées, {} lig/sec", context.nb_lignes_traitees_totales, Math.round(context.nb_lignes_traitees_sequence/ ( (System.currentTimeMillis() - context.date_demarrage_sequence+0.001)/1000)));

        context.date_demarrage_sequence=System.currentTimeMillis();
        context.nb_lignes_traitees_sequence=0;
    }

La fonction log utilise Log4J2 (il faut donc l'avoir ajouté au projet) et affichera ainsi, toutes les X lignes lues, le nombre de lignes totales et la vitesse de lecture de la séquence.

Lancer Talend avec un autre JDK que celui par défaut

Vous pouvez obtenir, lors d'une nouvelle installation, un message du type "Version 1.8.xxx of the JVM is not suitable for this product. Version: 11 or greater is required" :

Vous pouvez malgré tout utiliser cette version en téléchargeant Open JDK (version 11 ou supérieur) et lancer Talend avec le raccourci suivant (en précisant le lien vers le JDK) :

TOS_ESB-win-x86_64.exe -vm "E:\Utilitaires\OpenJDK11\jre\bin"

Afficher les paramètres d'appel à un Web service

Sur Talend ESB, suite à un tRequest, vous pouvez afficher les paramètres d'appel à votre web service de la façon suivante :

  • Ajoutez un tFlowToIterate afin de conserver les paramètres d'appel
  • Ajoutez un tJava avec le code ci-dessous :
    // Affiche l'IP de l'appelant
    // - Récupère l'objet restRequest
    java.util.Map mapRequest = (java.util.Map)globalMap.get("restRequest");

    // - Récupère l'objet MessageContext
    org.apache.cxf.jaxrs.ext.MessageContext messageContext = (org.apache.cxf.jaxrs.ext.MessageContext) mapRequest.get("MESSAGE_CONTEXT");

    log.info("Appelant :");
    log.info("- IP : {}", messageContext.getHttpServletRequest().getRemoteAddr());
    log.info("- Hote : {}", messageContext.getHttpServletRequest().getRemoteHost());
    log.info("- En-têtes : {}", mapRequest.get("ALL_HEADER_PARAMS"));
    log.info("- Paramètres : {}", mapRequest.get("ALL_QUERY_PARAMS"));

Fusionner les valeurs de lignes avec des clés dupliquées

Si vous avez plusieurs lignes comportant une même clé mais des valeurs différentes, et que vous souhaitez conserver une seule ligne avec les valeurs non vides/non nulles, voici comment faire.

Prenons le cas où vous avez les lignes suivantes :

  1. cle=1, val1="a", val2=null
  2. cle=1, val1=null, val2="b"
  3. cle=2, val1="c", val2="d"

Et que vous souhaitez obtenir :

  1. cle=1, val1="a", val2="b"
  2. cle=2, val1="c", val2="d"

Vous pouvez créer un tAggregateRow afin de regouper les lignes :

  • Mettez dans la partie GroupBy le clé d'unicité
  • Dans les opérations, ajoutez les autres colonnes, choisissez la fonction Max et cocher "Ignorer les valeurs null"

Récupérer le chemin du bureau de l'utilisateur

Dans un tJava, ajouter les lignes suivantes :

javax.swing.filechooser.FileSystemView view = javax.swing.filechooser.FileSystemView.getFileSystemView();
java.io.File file = view.getHomeDirectory();

System.out.println(file.getPath());

Lancer un programme externe avec attente ou non de la fin de l'exécution

Si vous souhaitez utiliser un programme externe, vous avez deux possibilités selon ce que vous souhaitez :

  • Si vous voulez attendre la fin du programme externe, utilisez le composant tSystem, et indiquez le chemin du programme
  • Si vous ne souhaitez pas attendre la fin du programme externe, utilisez un tJava et copiez-coller le code suivant (pour notepad.exe) :
    Runtime.getRuntime().exec("notepad.exe");

Extraire chaque élément d'un tableau JSON

Voici comment procéder si vous avez besoin d'extraire chaque élément d'une liste au format JSON, comme ci-dessous.

{"liste": ["element1","element2","element3"]}

Ajouter un composant tExtractJSONFields, indiquez comme requête d'itération $.liste[*] et créez une variable avec la valeur "@". Chaque élément itéré de la liste viendra alimenter la variable "element".

Dernière modification le 04/06/2020 - Quillevere.net

Rechercher sur le site

fr en rss RSS info Informations