kettle plugin 插件开发
http://wiki.pentaho.com/display/COM/PDI+Plugin+Loading
svn://source.pentaho.org/svnkettleroot/plugins/S3CsvInput
<?xml version="1.0" encoding="UTF-8"?>
<plugin
id="TemplatePlugin"
iconfile="icon.png"
description="Template Plugin"
tooltip="Only there for demonstration purposes"
category="Demonstration"
classname="plugin.template.TemplateStepMeta">
<libraries>
<library name="templatestep.jar"/>
</libraries>
</plugin>
ID:在kettle插件中必须全局唯一,因为被kettle序列化了,所以不要随便改变
Iconfile: kettle中插件显示的图片,必须是png图片
Description:插件描叙,显示在树形菜单里面。
Tooltip:树形菜单中,鼠标滑过的时候显示的提示信息
Category:插件显示的父目录
Classname:元数据类
Library:指明了插件需要加载所依赖的jar包
kettle转换步骤工作组件:
这里有四个类构成了这个kettle 步骤/节点,每一个类都有其特定的目的及所扮演的角色。
TemplateStep: 步骤类实现了StepInteface接口,在转换运行时,它的实例将是数据实际处理的位置。每一个执行线程都表示一个此类的实例。
TemplateStepData: 数据类用来存储数据,当插件执行时,对于每个执行的线程都是唯一的。执行时里面存储的东西主要包括数据库连接、文件句柄、缓存等等其他东西。
TemplateStepMeta: 元数据类实现了StepMetaInterface接口。它的职责是保存和序列化特定步骤实例的配置,在我们这个例子中,它负责保存用户设置的步骤名称和输出字段的名称。
TemplateStepDialog:对话框类实现了该步骤与用户交互的界面,它显示一对话框,通过对话框用户可以自己的喜好设定步骤的操作。对话框类与元数据类关系非常紧密,O(∩_∩)O~ 想想为什么吧? (元数据类可以追踪用户的设置)
除了上面的代码,还有一个plugin.xml,它设置好了插件的元数据,定义了步骤在kettle图形工作台中的显示效果。为了更好的让大家理解,我将利用这个步骤设计一个转换流程并执行它。对于插件的开发,我们将从plugin.xml配置文件开始讲起,然后讲讲元数据和对话框类,最后再讲讲步骤类和数据类。
======================================================================================
在我们做ETL工作的时候,在某些项目中往往会遇到一些特别的流程任务,kettle原有的流程处理节点已经不能满足我们的要求,这时 候我们就需要定制流程处理节点了。定制流程节点主要是针对数据的管理、数据的验证和某些特别文件数据的提取。大家通过查看kettle源代码,就可以知道 怎样去创建你自己的kettle插件了。
这篇文章主要告诉大家在kettle 4.0版本上怎样开发一个transformation类型的简单插件,这个插件可以接受任何记录流,然后在流后面再添加一个带值的字段,用户能够定义字段的名称,插件非常简单。O(∩_∩)O~ 我将尽可能简洁的介绍开发插件需要掌握的一些接口规范。
准备工作:
1、下载pdi-ce-4.0.0-stable.zip,供桌面测试用。
2、下载eclipse,任何版本都可以,装好SVN插件,后面下载kettle源代码之用。
3、 下载标准插件源代码模板工程。
建立插件工程:
1、 将下载的“标准插件源代码模板工程”导入到您的工作空间
2、 导入后工程会有一些错误,那是因为依赖的包没有导入。这时,你需要解压pdi-ce-4.0.0-stable.zip,进入解压目录将lib目录下面 kettle打头的所有jar包以及libswt/win32下面的swt.jar包(这个大家依赖操作系统导入)加入工程环境变量里面。
3、 重新编译一下工程,应该就没有错误了。
kettle转换步骤工作组件:
这里有四个类构成了这个kettle 步骤/节点,每一个类都有其特定的目的及所扮演的角色。
TemplateStep: 步骤类实现了StepInteface接口,在转换运行时,它的实例将是数据实际处理的位置。每一个执行线程都表示一个此类的实例。
TemplateStepData: 数据类用来存储数据,当插件执行时,对于每个执行的线程都是唯一的。执行时里面存储的东西主要包括数据库连接、文件句柄、缓存等等其他东西。
TemplateStepMeta: 元数据类实现了StepMetaInterface接口。它的职责是保存和序列化特定步骤实例的配置,在我们这个例子中,它负责保存用户设置的步骤名称和输出字段的名称。
TemplateStepDialog:对话框类实现了该步骤与用户交互的界面,它显示一对话框,通过对话框用户可以自己的喜好设定步骤的操作。对话框类与元数据类关系非常紧密,O(∩_∩)O~ 想想为什么吧? (元数据类可以追踪用户的设置)
除了上面的代码,还有一个plugin.xml,它设置好了插件的元数据,定义了步骤在kettle图形工作台中的显示效果。为了更好的让大家理解,我将利用这个步骤设计一个转换流程并执行它。对于插件的开发,我们将从plugin.xml配置文件开始讲起,然后讲讲元数据和对话框类,最后再讲讲步骤类和数据类。
书写你自己的plugin.xml:
下面plugin.xml是我们这个插件里面的内容,它的功能是告诉kettle插件的元数据类,插件的名称及描叙,还有需要加载的jar包。想要了解细节,可以查看文章:plug-in loading
<?xml version="1.0" encoding="UTF-8"?>
<plugin
id="TemplatePlugin"
iconfile="icon.png"
description="Template Plugin"
tooltip="Only there for demonstration purposes"
category="Demonstration"
classname="plugin.template.TemplateStepMeta">
<libraries>
<library name="templatestep.jar"/>
</libraries>
</plugin>
ID:在kettle插件中必须全局唯一,因为被kettle序列化了,所以不要随便改变
Iconfile: kettle中插件显示的图片,必须是png图片
Description:插件描叙,显示在树形菜单里面。
Tooltip:树形菜单中,鼠标滑过的时候显示的提示信息
Category:插件显示的父目录
Classname:元数据类
Library:指明了插件需要加载所依赖的jar包
一、元数据类:
下面显示了元数据的几个关键的方法,注意元数据类里面用私有成员变量outputField 存储了下一个步骤的输出字段。
// keep track of the step settings
public String getOutputField()
public void setOutputField(…)
public void setDefault()
// serialize the step settings to and from xml
public String getXML()
public void loadXML(…)
// serialize the step settings to and from a kettle repository
public void readRep(…)
public void saveRep(…)
// provide information about how the step affects the field structure of processed rows
public void getFields(…)
// perform extended validation checks for the step
public void check(…)
// provide instances of the step, data and dialog classes to Kettle
public StepInterface getStep(…)
public StepDataInterface getStepData()
public StepDialogInterface getDialog(…)
TemplateStepMeta元数据类其实还有很多方面,不过大多被他的父类BaseStepMeta给默认实现了,这些默认的实现足以使我们 的元数据类工作良好。想要了解更多,大家可以查查关于StepMetaInteface和BaseStepMeta的kettle官方文档。
二、对话框类:
TemeplateStepDialog为步骤实现了对话框的设置,kettle的用户界面部件是使用的eclipse的swt框架,如果要开发比较复杂的对话框,你还必须熟悉大部分swt代码。 Swt文档大家可以从eclipse上的帮助菜单点击在线获取。 在开发过程中,一个对话框对象拥有一个元数据对象,它记录了应该从哪里读取配置?应该把设置好的配置保存在哪里? 它仅仅设置了输出字段的名称在我们这个模板步骤里面。一个继承自BaseStepDialog特定的对话框类必须提供open(…)方法,这个方法必须返 回这个步骤的名称(发生改变时)或NULL(对话框被取消时)
三、步骤类:
步骤类是实际的处理和转换工作的地方。因为大部分样本代码已经由父类BaseStep提供了,大多数插件仅仅关注下面几个特定的方法就行。
// initialization and teardown
public boolean init(…)
public void dispose(..)
// processing rows
public void run()
public boolean processRow(..)
Init()方法在转换执行前被kettle调用,转换必须在所有步骤初始化成功时才真正执行。我们这个模板步骤没有做任何事情,这里仅仅是拿出来让大家了解了解。
dispose()方法是在步骤执行完之后执行(非转换执行完哈),它完成资源的关闭,像文件句柄、缓存等等。
run()方法在实际处理记录集的时候调用。里面其实是个调用processRow()方法处理记录的小循环,当此步骤再没有数据处理或转换被停止时退出循环。
processRow()方法在处理单条记录的时候被调用。这个方法通常通过调用getRow()来获取需要处理的单条记录。 这个方法如果有需要将会被阻塞,例如当此步骤希望放慢脚步处理数据时。processRow()随后的流程将执行转换工作并调用putRow()方法将处 理过的记录放到它的下游步骤。
注意:你的步骤可能会变记录的结构,为了安全起见,一定要多熟悉包org.pentaho.di.core.row,特别是类RowMetaInterface和RowDataUtil。
基类BaseStep对处理的记录提供了第一次访问的标识,在某些代码只执行一次的时候可能非常有用,例如某个费时的查找,其实这就是缓存。
四、数据类:
大多数步骤都需要临时的缓冲或者临时的数据。数据类就是这些数据合适的存放位置。每一个执行线程将得到其拥有的数据类实例,所以它能在独立的空间里面运 行。TemplateStepData继承自BaseStepData,作为一个经验法则,不要将non-constant字段放置 BaseStepData类里面,如果你必须,请将它最好放置TemplateStepData数据类里面.
我们的步骤仅仅使用了一个数据对象来存储记录集输出的结构,没有用到其他的存储介质,例如文件等等。
总结:
一个kettle步骤插件包括4个类,每一个类都有自己的角色和职责,元数据、对话框、步骤和数据类很好的结合在一起工作,特别是因为很多样板代码和通用的方法已经被父类实现,使得kettle的插件开发非常容易,若有需要讨论的,大家可以在http://www.ahuoo.com上给我留言,欢迎打扰!下一篇我们将具体讲解的插件开发及调试。O(∩_∩)O~
=================================debug=====================================================
kettle插件调试比较麻烦,因为是两个不同工程的依赖,但是大家如果掌握方法,其实也很简单,回顾JAVA常用的调试手法,如Link Source、JAVA远程调试,如果大家了解maven,甚至可以直接依赖调试,下面我来作重讲讲前面两种调试手法。
准备工作:
1、通过eclipse上的svn插件下载kettle4.0源码,地址是:http://source.pentaho.org/svnkettleroot/Kettle/branches/4.0.0
下载完成之后,发现eclipse里面存在两个工程:TemplateStepPlugin,Kettle 4.0.0,若有不同,请参见文章ETL工具——kettle插件开发(基础篇)
2、下载我这里给你准备的测试转换文件test.ktr
一、Link Source调试:
1、在Kettle4.0工程下面,进入plugins->steps目录,发现里面有个DummyPlugin目录,其就是kettle官 方提供的外部转换插件,细心地读者发现里面仅用三个文件DPL.png、dummy.jar、plugin.xml,其实它就是一个完整插件所需要的东 西。
2、在与DummyPlugin同级目录里面,建立文件夹TemplateStep, 将TemplateStepPlugin工程下面的icon.png、plugin.xml文件拷贝至此,jar包就不用了
否则调试时会关联不上源码,O(∩_∩)O~ 想想为什么吧??
3、最重要的一步来了,大家右击工程Kettle 4.0.0,选择属性Properties, 然后在左手边选择Java Build Path, 然后在上面的选项卡里面选择Source,此时右边就有几个按钮,
点击Link Source按钮,设置好你的插件源码目录以及目录名字,见下图:
4、运行。 关联好之后,咱们找到kettle的入口运行类Spoon.java,大家可以通过快捷键ctrl+shift+R找出此类选择调试运行即可,进入kettle工作台,打开测试文件test.ktr,
查看是否能正常运行,此时大家就可以在插件类TemplateStep里面打断点调试了,其他情况不再多说了
二、kettle远程调试
远程调试的关键是首先你的在kettle启动配置里面设置远程调试参数,然后在eclipse里面设置远程调试监控的端口号,这样就ok了。
1、进入pdi-ce-4.0.0-stable.zip解压出来的目录(上一篇文章:ETL工具——kettle插件开发(基础篇)),编辑启动配置文件Spoon.bat,linux下当然是spoon.sh
在文件里面加入这么一句话:
set OPT=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8285
2、点击Spoon.bat,进入kettle工作台
3、打开eclipse,进入菜单Run——>Debug Configurations,选择左边的Remote Java Application,右键新建一个远程调试应用程序,设置如下图,
端口就是上面参数里面的端口8285,一切ok,选择选择下面的debug按钮。
4、在kettle工作台,运行刚才的测试转换文件 test.ktr,eclipse开始监听调试了,大家断点设置就可。
======================================================================================
RowMetaInterface outputRowMeta = getInputRowMeta().clone();
//构造一个新的输出列。方法一
RowMetaInterface rowMeta = new RowMeta();
Object[] rowData = new Object[1];
int valtype = ValueMeta.getType("String");
ValueMetaInterface valueMeta = new ValueMeta( “FieldName1”, valtype); valueMeta .setLength(-1);
rowMeta.addValueMeta(valueMeta);
RowMetaAndData metaAndData = new RowMetaAndData(rowMeta, rowData);
RowMetaInterface newMeta = metaAndData.getRowMeta();
outputRowMeta.mergeRowMeta(newMeta);
//构造一个新的输出列。方法二
RowMetaInterface outputRowMeta = getInputRowMeta().clone();
int valtype = ValueMeta.getType("String");
ValueMetaInterface valueMeta = new ValueMeta( “FiledName1”, valtype);
valueMeta.setLength(-1);
outputRowMeta.addValueMeta(valueMeta);
//从上一个步骤获得一行数据。
Object[] r = null;
r = getRow();
//获得一行数据里,某一个字段的值
String fieldname = “MyOldField”;
int fieldIndex = this.getInputRowMeta().indexOfValue(fieldName);
Object value = r[fieldIndex];
//将新的数据追加到原来的行数据的后面,成为新的输出行:(转载请注明:http://pdi.itpub.net)
Object[] values = new Object[1];
values[0]=”new value”;
r = RowDataUtil.addRowData(r, getInputRowMeta().size(),values);
//将输出行的元数据和数据放到缓存里,这样下一个步骤可以读取了,注意元数据的个数和数据的个数要相等。:(转载请注明:http://pdi.itpub.net)
putRow(outputRowMeta, r);