Expert Consultancy from Yellow Pelican

Component Designer API

A site about Talend

Talend API for Component Designers

The API that you need to know when you're building your own components is poorly documented. Despite this, there are many features available that will help you to build your components. We'll start off with some of the more common calls that you will need to make and explain exactly what they do. The best way to get the full technical documentation is to access this through Talend Studio - Help->Help Contents->Developer Guide->API Reference. You may also access the documentation from here (Talend API Reference).

If you're not already familiar with Java Emitter Templates (JET), then now is probably a good time to read our article on Java Emitter Templates (JET).

Programming Style

The programming style shown here is not necessarily my own. For the examples shown, I have kept the the style that has been used for the standard Talend Components. Within these, there are variations in style. I have chosen a style that seems most common.

Imports

In the examples shown here, we usually refer to un-qualified Class names. Remember that if you use un-qualified names (which is usual), you must import these. For more information on this and Java Emitter Templates (JET) in general, refer to the documentation on Java Emitter Templates (JET).

The following code-fragment shows some basic imports.

<%@ jet
imports="
	org.talend.designer.codegen.config.CodeGeneratorArgument
	org.talend.core.model.process.INode
"
%>

CodeGeneratorArgument

Java Emitter Templates (JET) require an argument to be passed to the template. An Object of the Class org.talend.designer.codegen.config.CodeGeneratorArgument provides this argument. Most components provide a reference to argument, as shown below.

	CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;

This Class makes Job-level information available including jobName, jobVersion and argument (INode). For more documentation on this Class, read the Talend API Reference.

INode

From codeGenArgument we can now create an instance of org.talend.core.model.process.INode; which will provide information about the unique instance of our component.

It is usual for us to want to extract the unique component name from this Object. This is usually referred to as cid (Component ID). If, for example, we had a component named tMyComponent we might expect to see the value tMyComponent_1 returned for the first instance of the component. The nomenclature is confusing as we are using the get-method CodeGenArgument.getArgument to get an Object of type INode from argument.

	INode node = (INode) codeGenArgument.getArgument();
	String cid = node.getUniqueName();

This Class makes other key information available to us including information on the component's metadata and connections. We'll look at these shortly.

Overview

The following code provides an example of what we have learned so far. This is basic code that you might expect to see in any Java Emitter Templates (JET) file.

<%@ jet
imports="
	org.talend.designer.codegen.config.CodeGeneratorArgument
	org.talend.core.model.process.INode
"
%>

<%
	CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
	INode node = (INode)codeGenArgument.getArgument();
	String cid = node.getUniqueName();
%>

ElementParameterParser

The Class org.talend.core.model.process.ElementParameterParser allows us to extract our component's parameter values from node. Let's take a look at a simple example, from the component tJava.

<%=ElementParameterParser.getValue(node, "__CODE__") %>

The first observation worth noting with this method, is that a String is always returned, regardless of any inferred data type when you defined your parameters in the Component Descriptor File. i.e. all parameters are or type String.

The following code-fragment shows the specification of the getValue method.

public static java.lang.String getValue(IElement node, java.lang.String text)

When you get a parameter value, the parameter name must be specified with both a prefix and suffix of __, for example, __CODE__ where CODE is a parameter supported by the component tJava.

In the case of tJava, the parameter CODE is used to specify some user-defined Java code; which is simply emitted by the Java Emitter Template as instructed by the directive <%=. For more information on this JET Expression Scripting Element, read our tutorial on Java Emitter Templates (JET).

As can be seen from the example above, the value specified by the parameter CODE is simply emitted to form part of the Job's Java code. It is more common for a parameter's value to be assigned to a variable, for use within the template.

The following example is taken from the component tContextDump.

boolean hidePassword = ("true").equals(ElementParameterParser.getValue(node,"__HIDE_PASSWORD__"));

The component tContextDump allows you to write the values of Context Variables to the console, for debugging purposes; however, given their sensitivity, it allows you to specify that any variable that represent a password (Talend Data Type id_Password) will be obscured.

The parameter HIDE_PASSWORD is defined as a Checkbox as described in Component.xsd - PARAMETER FIELD Values. A Checkbox value always represents true or false; however, as we discovered earlier, parameters are always returned by ElementParameterParser.getValue as String. The boolean variable hidePassword is assigned a value based on whether or not the value "true" has been returned.

Metadata

If you're writing an input, output, or processing component, then you'll need to handle metadata. Metadata describes the data structures that flow through your component.

IMetadataTable

To work with metadata, the first thing we will do is to add the Interface org.talend.core.model.metadata.IMetadataTable to our imports. As components may support multiple metadatas, these are made available to us as java.util.List, so we will import this too, as shown below.

<%@ jet
imports="
        org.talend.designer.codegen.config.CodeGeneratorArgument
        org.talend.core.model.process.INode
	org.talend.core.model.metadata.IMetadataTable
	java.util.List
"
%>

Metadata is made available by the get-method Inode.getMetaDataList. This list is assigned to an Object of type List<IMetadataTable>, as shown below.

List<IMetadataTable> metadatas = node.getMetadataList();

Most components that work with metadata, work with a single metadata. For the purpose of this documentation, we'll look at this typical code. If you're realy to write components that support multiple metadatas, you'll probably already have a good understanding of how metadata works.

The following shows a typical code fragment, to get and handle a single metadata. Later, we'll look at what can be done with metadata once it has been made available to your code.

if((metadatas != null) && (metadatas.size() > 0)) {
	IMetadataTable metadata = metadatas.get(0);
	if(metadata != null) {

This code is fairly self-explanatory. If metadata is available, it will be assigned to the variable metadata and, in this instance, the component only supports a single metadata. If valid metadata has been returned, some component-specific processing may now be performed.

Connections

If you're writing an input, output, or processing component, then you'll need to handle connections. This represents the types of connections that you have between your components, as defined by the attribute CTYPE; which is described in our article on the Component Descriptor File.

IConnection

To work with connections, the first thing we will do is to add the Interface org.talend.core.model.process.IConnection to our imports. As components may support multiple connections, these are made available to us as java.util.List, so we will import this too, if we haven't already done so.

<%@ jet
imports="
        org.talend.designer.codegen.config.CodeGeneratorArgument
        org.talend.core.model.process.INode
	org.talend.core.model.metadata.IMetadataTable
	java.util.List
	org.talend.core.model.process.IConnection
"
%>

It is important to understand that IConnection represents a type of connection rather than a specific instance of two components being connected. We may, for example, allow data to FLOW from our component to one or more other components. One instance of IConnection will represent this connection type. We will need to drill in this to see the actual flow of data between components.

Connections are made available by a number of get-methods, for example, Inode.getOutgoingConnections, depending on what you are trying to achive. This list is assigned to an Object of type (usually) List< ? extends IConnection>, as shown below.

List< ? extends IConnection> conns = node.getOutgoingConnections();




Expert Consultancy from Yellow Pelican
comments powered by Disqus

© www.TalendByExample.com