Qu'est-ce qu'un composant Talend
Cet article traite les sujets suivants qui sont essentiels si vous souhaitez développer vos propres composants :
- Qu'est-ce qu'un composant Talend ?
- Qu'est-ce qui en fait un composant Talend ?
- Modèle de génération de code du composant.
Notez que cet article vise à expliquer quels sont les composants Talend et sa lecture est recommandée avant de commencer à créer vos propres composants. Toutefois, il ne s'agit pas d'un tutoriel vous expliquant comment développer des composants personnalisés pas à pas. Pour un tutoriel et des explications détaillées sur la création de composants personnalisés, veuillez consultez Concevoir un composant (en anglais).
Qu'est-ce qu'un composant
Concrètement, un composant est un ensemble de fichiers stockés dans un dossier portant le nom du composant. Tous les composants natifs sont situés dans le répertoire <Talend Studio installation dir>/plugins/org.talend.designer.components.localprovider_[version]/components. Chaque composant est un sous-dossier dans ce répertoire et le nom du sous-dossier est le nom du composant.
Visuellement, un composant est une icône que vous pouvez glisser-déposer à partir de la Palette dans l'espace de modélisation graphique.
Techniquement, un composant est un extrait de code Java généré qui fait partie d'un Job qui est une classe Java. Un Job est composé d'un ou de plusieurs composants ou connecteurs. Le nom du Job sera celui de la classe et chaque composant dans un Job sera traduit en un extrait de code Java généré. Le code Java sera compilé automatiquement lorsque vous sauvegarderez le Job.
Qu'est-ce qui fait un composant Talend ?
Le descripteur de fichier XML
Par exemple, la structure du descripteur du tFileInputDelimited_java.xml ressemble à ceci :
<COMPONENT>
<HEADER PLATEFORM="ALL" SERIAL="" VERSION="0.102" STATUS="ALPHA" COMPATIBILITY="ALL"
AUTHOR="Talend" RELEASE_DATE="20070111A" STARTABLE="true" HAS_CONDITIONAL_OUTPUTS="true">
<SIGNATURE/>
</HEADER>
<FAMILIES>
<FAMILY>File/Input</FAMILY>
</FAMILIES>
<DOCUMENTATION>
<URL/>
</DOCUMENTATION>
<CONNECTORS>
<CONNECTOR CTYPE="FLOW" MAX_INPUT="0" MAX_OUTPUT="1"/>
<CONNECTOR NAME="REJECT" CTYPE="FLOW" MAX_INPUT="0" MAX_OUTPUT="1" LINE_STYLE="2"
COLOR="FF0000" BASE_SCHEMA="FLOW"/>
<CONNECTOR CTYPE="ITERATE" MAX_OUTPUT="1" MAX_INPUT="1"/>
<CONNECTOR CTYPE="SUBJOB_OK" MAX_INPUT="1"/>
<CONNECTOR CTYPE="SUBJOB_ERROR" MAX_INPUT="1"/>
<CONNECTOR CTYPE="COMPONENT_OK"/>
<CONNECTOR CTYPE="COMPONENT_ERROR"/>
<CONNECTOR CTYPE="RUN_IF"/>
</CONNECTORS>
<PARAMETERS>
<PARAMETER NAME="PROPERTY" FIELD="PROPERTY_TYPE" SHOW="true" NUM_ROW="10"
REPOSITORY_VALUE="DELIMITED"/>
<PARAMETER NAME="FILENAMETEXT" FIELD="LABEL" COLOR="0;0;0" NUM_ROW="15">
<DEFAULT>"When the input source is a stream or a zip file,footer and random shouldn't be
bigger than 0."</DEFAULT>
</PARAMETER>
<PARAMETER NAME="FILENAME" FIELD="FILE" NUM_ROW="20" REQUIRED="true"
REPOSITORY_VALUE="FILE_PATH">
<DEFAULT>"__COMP_DEFAULT_FILE_DIR__/in.csv"</DEFAULT>
</PARAMETER>
<PARAMETER NAME="ROWSEPARATOR" FIELD="TEXT" NUM_ROW="30" REPOSITORY_VALUE="ROW_SEPARATOR"
SHOW_IF="CSV_OPTION=='false'">
<DEFAULT>"\n"</DEFAULT>
</PARAMETER>
<PARAMETER NAME="CSVROWSEPARATOR" FIELD="OPENED_LIST" NUM_ROW="30"
REPOSITORY_VALUE="ROW_SEPARATOR" MAX_LENGTH="2" SHOW_IF="CSV_OPTION=='true'">
<ITEMS DEFAULT="LF">
<ITEM NAME="LF" VALUE=""\n""/>
<ITEM NAME="CR" VALUE=""\r""/>
<ITEM NAME="CRLF" VALUE=""\r\n""/>
</ITEMS>
</PARAMETER>
<PARAMETER NAME="FIELDSEPARATOR" FIELD="TEXT" NUM_ROW="30" REQUIRED="true"
REPOSITORY_VALUE="FIELD_SEPARATOR">
<DEFAULT>";"</DEFAULT>
</PARAMETER>
<PARAMETER NAME="CSV_OPTION" FIELD="CHECK" REQUIRED="true" REPOSITORY_VALUE="CSV_OPTION"
NUM_ROW="35">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="ESCAPE_CHAR" FIELD="TEXT" NUM_ROW="35" REQUIRED="true"
REPOSITORY_VALUE="ESCAPE_CHAR" SHOW_IF="CSV_OPTION == 'true'">
<DEFAULT>"""</DEFAULT>
</PARAMETER>
<PARAMETER NAME="TEXT_ENCLOSURE" FIELD="TEXT" NUM_ROW="35" REQUIRED="true"
REPOSITORY_VALUE="TEXT_ENCLOSURE" SHOW_IF="CSV_OPTION == 'true'">
<DEFAULT>"""</DEFAULT>
</PARAMETER>
<PARAMETER NAME="HEADER" FIELD="TEXT" NUM_ROW="40" REPOSITORY_VALUE="HEADER">
<DEFAULT>0</DEFAULT>
</PARAMETER>
<PARAMETER NAME="FOOTER" FIELD="TEXT" NUM_ROW="40" REPOSITORY_VALUE="FOOTER"
SHOW_IF="UNCOMPRESS=='false'">
<DEFAULT>0</DEFAULT>
</PARAMETER>
<PARAMETER NAME="LIMIT" FIELD="TEXT" NUM_ROW="40" REPOSITORY_VALUE="LIMIT">
<DEFAULT/>
</PARAMETER>
<PARAMETER NAME="REMOVE_EMPTY_ROW" FIELD="CHECK" REQUIRED="true" NUM_ROW="46"
REPOSITORY_VALUE="REMOVE_EMPTY_ROW">
<DEFAULT>true</DEFAULT>
</PARAMETER>
<PARAMETER NAME="UNCOMPRESS" FIELD="CHECK" NUM_ROW="46">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="DIE_ON_ERROR" FIELD="CHECK" NUM_ROW="46">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="SCHEMA" FIELD="SCHEMA_TYPE" REQUIRED="true" NUM_ROW="44">
<DEFAULT/>
</PARAMETER>
<PARAMETER NAME="SCHEMA_REJECT" FIELD="SCHEMA_TYPE" REQUIRED="true" NUM_ROW="44"
CONTEXT="REJECT" SHOW="true">
<TABLE READONLY="true">
<COLUMN NAME="errorCode" TYPE="id_String" LENGTH="255" READONLY="false"
CUSTOM="true"/>
<COLUMN NAME="errorMessage" TYPE="id_String" LENGTH="255" READONLY="false"
CUSTOM="true"/>
</TABLE>
</PARAMETER>
</PARAMETERS>
<ADVANCED_PARAMETERS>
<PARAMETER FIELD="DIRECTORY" NAME="TEMP_DIR" NUM_ROW="1" READONLY="false" REQUIRED="true"
SHOW="false">
<DEFAULT>"__COMP_DEFAULT_FILE_DIR__"</DEFAULT>
</PARAMETER>
<PARAMETER NAME="ADVANCED_SEPARATOR" FIELD="CHECK" REQUIRED="true" NUM_ROW="41">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="THOUSANDS_SEPARATOR" FIELD="TEXT" REQUIRED="true" NUM_ROW="41"
SHOW_IF="(ADVANCED_SEPARATOR == 'true')">
<DEFAULT>","</DEFAULT>
</PARAMETER>
<PARAMETER NAME="DECIMAL_SEPARATOR" FIELD="TEXT" REQUIRED="true" NUM_ROW="41"
SHOW_IF="(ADVANCED_SEPARATOR == 'true')">
<DEFAULT>"."</DEFAULT>
</PARAMETER>
<PARAMETER NAME="RANDOM" FIELD="CHECK" REQUIRED="true" NUM_ROW="45"
SHOW_IF="(CSV_OPTION == 'false') AND (UNCOMPRESS=='false')">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="NB_RANDOM" FIELD="TEXT" REQUIRED="true" NUM_ROW="45"
SHOW_IF="(CSV_OPTION == 'false') and (RANDOM == 'true') AND (UNCOMPRESS=='false')">
<DEFAULT>10</DEFAULT>
</PARAMETER>
<PARAMETER NAME="TRIMALL" FIELD="CHECK" NUM_ROW="46">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="TRIMSELECT" FIELD="TABLE" NUM_ROW="47" NB_LINES="5"
SHOW_IF="TRIMALL=='false'">
<ITEMS BASED_ON_SCHEMA="true">
<ITEM NAME="TRIM" FIELD="CHECK"/>
</ITEMS>
</PARAMETER>
<PARAMETER NAME="CHECK_FIELDS_NUM" FIELD="CHECK" NUM_ROW="46">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="CHECK_DATE" FIELD="CHECK" NUM_ROW="46">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="ENCODING" FIELD="ENCODING_TYPE" NUM_ROW="45" REQUIRED="true"
REPOSITORY_VALUE="ENCODING">
<DEFAULT>"ISO-8859-15"</DEFAULT>
</PARAMETER>
<PARAMETER NAME="SPLITRECORD" FIELD="CHECK" REQUIRED="true" NUM_ROW="50"
SHOW_IF="CSV_OPTION == 'false'" REPOSITORY_VALUE="SPLITRECORD">
<DEFAULT>false</DEFAULT>
</PARAMETER>
<PARAMETER NAME="DESTINATION" FIELD="TEXT" NUM_ROW="90" SHOW="false">
<DEFAULT/>
</PARAMETER>
</ADVANCED_PARAMETERS>
<CODEGENERATION>
<IMPORTS>
<IMPORT NAME="Talen File Enhanced" MODULE="talend_file_enhanced_20070724.jar"
REQUIRED="true"/>
<IMPORT NAME="Talend_CSV" MODULE="talendcsv.jar" REQUIRED="true"/>
</IMPORTS>
</CODEGENERATION>
<RETURNS>
<RETURN NAME="NB_LINE" TYPE="id_Integer" AVAILABILITY="AFTER"/>
</RETURNS>
</COMPONENT>
L'élément HEADER
définit les informations de base du composant, comme la
version, l'auteur du composant, etc.
<HEADER PLATEFORM="ALL" SERIAL="" VERSION="0.102" STATUS="ALPHA"
COMPATIBILITY="ALL" AUTHOR="Talend" RELEASE_DATE="20070111A"
STARTABLE="true" HAS_CONDITIONAL_OUTPUTS="true">
<SIGNATURE />
</HEADER>
L'attribut STARTABLE
spécifie si le composant peut être le premier composant
d'un sous-Job. La valeur de l'attribut est toujours true pour les
composants d'entrée, comme le composant tMysqlInput ou le
composant tFileInputDelimited et false
pour les composants de sortie, comme le tMysqlOutput.
L'attribut HAS_CONDITIONAL_OUTPUTS
spécifie si le composant a plusieurs flux
de données de sortie. Par exemple, si vous souhaitez que le composant possède à la fois
une connexion principale et une connexion de rejets, la valeur de cet attribut doit être
true.
L'élément FAMILIES
spécifie le(s) groupe(s) de la famille dans le(s)quel(s)
le composant doit être classé dans la Palette. Un composant peut
être classé dans plusieurs groupes. On peut par exemple classer un composant dans les
groupes System et Orchestration :
<FAMILIES>
<FAMILY>System</FAMILY>
<FAMILY>Orchestration</FAMILY>
</FAMILIES>
L'élément CONNECTORS
définit le type de connexion ou de lien utilisé par le
composant pour se connecter à d'autres composants dans le Job. Cet élément définit
comment ce composant interagit avec d'autres composants.
<CONNECTORS>
<CONNECTOR CTYPE="FLOW" MAX_INPUT="0" MAX_OUTPUT="1"/>
<CONNECTOR NAME="REJECT" CTYPE="FLOW" MAX_INPUT="0"
MAX_OUTPUT="1" LINE_STYLE="2" COLOR="FF0000" BASE_SCHEMA="FLOW" />
<CONNECTOR CTYPE="ITERATE" MAX_OUTPUT="1" MAX_INPUT="1" />
<CONNECTOR CTYPE="SUBJOB_OK" MAX_INPUT="1" />
<CONNECTOR CTYPE="SUBJOB_ERROR" MAX_INPUT="1" />
<CONNECTOR CTYPE="COMPONENT_OK" />
<CONNECTOR CTYPE="COMPONENT_ERROR" />
<CONNECTOR CTYPE="RUN_IF" />
</CONNECTORS>
Les différents types de liens Trigger (déclencheurs) ou de connecteurs de flux acceptés s'affichent dans le menu contextuel du composant :
L'attribut CONNECTOR CTYPE
définit le type de connecteur.
Le type FLOW
signifie que le connecteur peut gérer un flux de données
Main
ou Reject
. L'attribut
MAX_INPUT
définit le nombre maximum de connecteurs d'entrées
autorisés reliés à ce composant et l'attribut MAX_OUTPUT
définit le
nombre maximum de connecteurs de sortie auxquels le composant peut se connecter. Par
exemple :
<CONNECTOR CTYPE="FLOW" MAX_INPUT="0" MAX_OUTPUT="1"/>
Dans cet exemple, le composant n'autorise pas la connexion à un flux de données
Main
et envoie un unique flux de données Main
vers
un autre composant.
L'élément PARAMETERS
définit les propriétés du composant. L'attribut
PARAMETER NAME
définit le nom de la propriété, l'attribut
PARAMETER FIELD
définit le type de champ et par conséquent, le type
de valeur à définir.
<PARAMETERS>
<PARAMETER NAME="PROPERTY" FIELD="PROPERTY_TYPE" SHOW="true"
NUM_ROW="10" REPOSITORY_VALUE="DELIMITED" />
......
<PARAMETER NAME="SCHEMA_REJECT" FIELD="SCHEMA_TYPE"
REQUIRED="true" NUM_ROW="44" CONTEXT="REJECT" SHOW="true">
<TABLE READONLY="true">
<COLUMN NAME="errorCode" TYPE="id_String" LENGTH="255"
READONLY="false" CUSTOM="true" />
<COLUMN NAME="errorMessage" TYPE="id_String"
LENGTH="255" READONLY="false" CUSTOM="true" />
</TABLE>
</PARAMETER>
</PARAMETERS>
Ces valeurs sont affichées dans la vue Basic settings du composant.
Les attributs du composant dépendent de la fonction du composant et des informations requises saisies par l'utilisateur pour que le composant fonctionne comme prévu. Comme ces informations varient selon les utilisateurs, il est possible de les stocker dans une variable, comme attribut de composant.
L'élément ADVANCED_PARAMETERS
définit les propriétés avancées du
composant.
<ADVANCED_PARAMETERS>
<PARAMETER
FIELD="DIRECTORY"
NAME="TEMP_DIR"
NUM_ROW="1"
READONLY="false"
REQUIRED="true"
SHOW="false">
<DEFAULT>"__COMP_DEFAULT_FILE_DIR__"</DEFAULT>
</PARAMETER>
......
<PARAMETER
NAME="DESTINATION"
FIELD="TEXT"
NUM_ROW="90"
SHOW="false">
<DEFAULT></DEFAULT>
</PARAMETER>
</ADVANCED_PARAMETERS>
Cet élément est affiché dans le panneau Advanced settings du composant.
L'élément CODEGENERATION
déclare les fichiers Jar qui seront utilisés dans
le composant. Ces fichiers Jar sont placés dans le dossier du composant.
<CODEGENERATION>
<IMPORTS>
<IMPORT NAME="Talend File Enhanced"
MODULE="talend_file_enhanced_20070724.jar" REQUIRED="true" />
<IMPORT NAME="Talend_CSV" MODULE="talendcsv.jar"
REQUIRED="true" />
</IMPORTS>
</CODEGENERATION>
L'élément RETURNS
définit les variables globales retournées par le
composant. L'attribut RETURN NAME
définit le nom de la variable,
l'attribut TYPE
définit le type de données de la variable et l'attribut
AVAILABILITY
définit l'utilisation de la variable. L'attribut
AVAILABILITY
peut avoir une valeur AFTER ou
FLOW.
<RETURNS>
<RETURN NAME="NB_LINE" TYPE="id_Integer" AVAILABILITY="AFTER" />
</RETURNS>
Les variables globales peuvent être utilisées par d'autres composants dans le même sous-Job
ou dans d'autres sous-Jobs en fonction de la définition de l'attribut
AVAILABILITY
.
La variable globale la plus courante est la variable NB_LINE
, généralement
utilisée pour compter le nombre total de lignes traitées.
Le fichier messages.properties
Le fichier messages.properties tFileInputDelimited_messages.properties pour le tFileInputDelimited ressemble à ceci :
#Created by JInto - www.guh-software.de
#Mon Aug 24 17:23:58 CST 2009
ADVANCED_SEPARATOR.NAME=Advanced separator(for number)
CHECK_FIELDS_NUM.NAME=Check each row structure against schema
CHECK_DATE.NAME=Check date
CSV_OPTION.NAME=CSV options
DECIMAL_SEPARATOR.NAME=Decimal separator
DIE_ON_ERROR.NAME=Die on error
ENCODING.NAME=Encoding
ESCAPE_CHAR.NAME=Escape char
FIELDSEPARATOR.NAME=Field Separator
FILENAME.NAME=File Name/Input Stream
FOOTER.NAME=Footer
HEADER.NAME=Header
#HELP=org.talend.help.tFileInputDelimited
LIMIT.NAME=Limit
LONG_NAME=Reads a file row by row with simple separated fields
NB_LINE.NAME=Number of lines
NB_RANDOM.NAME=Number of lines
RANDOM.NAME=Extract lines at random
REJECT.LINK=Reject
REJECT.MENU=Reject
Le fichier messages.properties contient également une courte description du composant, par exemple :
LONG_NAME=Reads a file row by row with simple separated fields
Ce libellé s'affiche comme une infobulle du composant dans la Palette, lorsque vous passez votre curseur sur un composant dans la Palette.
Le fichier modèle Java
- <component_name>_begin.javajet
- <component_name>_main.javajet
- <component_name>_end.javajet
Pour plus d'informations concernant le modèle de génération de code pour les composants, consultez Modèle de génération de code pour les composants.
JET est un moteur "model to text" qui vous permet de générer une sortie (texte) à partir d'un modèle EMF. Vous pouvez par exemple générer du SQL, du Java, du XML, du texte, du HTML, etc. JET utilise une technologie de modèle très proche de la syntaxe des pages Java Server Pages (JSP).
Dans le Studio Talend, les fichiers des
modèles sont traduits en code Java. Un fichier de modèle contient deux types de code Java : le
code modèle et le code Java de sortie. Le code modèle est compris dans les balises
<% %>
. Dans le cas de JSP, les classes requises sont importées dans la
partie supérieure du fichier de modèles. Elles peuvent varier en fonction de vos besoins.
Cependant, il existe des classes par défaut qui sont généralement ajoutées à chaque fichier de
modèle .javajet.
<%@ jet
imports="
org.talend.core.model.process.INode
org.talend.core.model.process.ElementParameterParser
org.talend.core.model.metadata.IMetadataTable
org.talend.core.model.metadata.IMetadataColumn
org.talend.core.model.process.IConnection
org.talend.core.model.process.IConnectionCategory
org.talend.designer.codegen.config.CodeGeneratorArgument
org.talend.core.model.metadata.types.JavaTypesManager
org.talend.core.model.metadata.types.JavaType
java.util.List
java.util.Map
"
%>
Cette section du modèle JET est particulière : il s'agit de la section d'import JET. Vous en aurez besoin dans les fichiers de modèles, car ils sont compilés séparément. Les classes listées dans la section d'import sont spécifiques à Talend.
Les lignes ci-dessous sont présentes dans chaque fichier de modèle javajet après la section d'import JET.
<%
CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
INode node = (INode)codeGenArgument.getArgument();
String cid = node.getUniqueName();
%>
Ces codes sont utilisés pour récupérer les valeurs des propriétés définies du composant et
pour obtenir le nom unique du composant. Chaque composant dans un Job est un nœud dont
l'interface est INode
. cid
est un identifiant et possède un
nom unique.
Un composant peut être utilisé plusieurs fois dans un Job et vous ne pouvez pas prédire le nom des variables utilisées dans les autres composants, ou prédire combien de fois un même composant sera utilisé, comment les composants sont interconnectés, etc. Talend fournit une méthode sûre pour obtenir une variable unique : ajouter le nom unique du composant comme suffixe pour chaque variable déclarée dans le fichier de modèle. Par exemple :
int nb_line_<%=cid %> = 0;
tFileInputDelimited_1
est le nom unique du composant
tFileInputDelimited dans le Job ci-dessous :
Cette ligne est traduite dans le code Java ci-dessous, dans le code généré par le Job :
int nb_line_tFileInputDelimited_1 = 0;
Voici une partie du code d'un fichier de modèle :
<%
public void useShareConnection(INode node) {
String sharedConnectionName = ElementParameterParser.getValue(node, "__SHARED_CONNECTION_NAME__");
%>
String sharedConnectionName_<%=cid%> = <%=sharedConnectionName%>;
conn_<%=cid%> = SharedDBConnection.getDBConnection("<%=this.getDirverClassName(node)%>",url_<%=cid%>,userName_<%=cid%> , password_<%=cid%> , sharedConnectionName_<%=cid%>);
<%
}
%>
Le code modèle est compris entre les balises <% %>
et le code de sortie
Java, qui fera partie du code généré par le Job et sera exécuté, s'il n'est pas entouré des
balises <% %>
. Dans ce cas, les deux lignes suivantes constituent le code
de sortie Java :
String sharedConnectionName_<%=cid%> = <%=sharedConnectionName%>;
conn_<%=cid%> = SharedDBConnection.getDBConnection("<%=this.getDirverClassName(node)%>",url_<%=cid%>,userName_<%=cid%> , password_<%=cid%> , sharedConnectionName_<%=cid%>);
À la fin du modèle, vous devez fermer les blocs ouverts :
<%
}
%>
L'icône du composant
Cette image est l'icône du composant qui s'affiche dans la Palette. Le nom de l'icône doit correspondre au format suivant : NomDuComposant_icon32.png.