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 compteurglobalMap.
put("NbLignes",
0);// Incrémente la valeurglobalMap.
put("NbLignes",
((Integer)globalMap.
get("NbLignes"))+1);// Récupère la valeurInteger 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 :
// Affectationif (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 MessageContextorg.
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 :
- cle=1, val1="a", val2=null
- cle=1, val1=null, val2="b"
- cle=2, val1="c", val2="d"
Et que vous souhaitez obtenir :
- cle=1, val1="a", val2="b"
- 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 :
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".