构建组件.docx
《构建组件.docx》由会员分享,可在线阅读,更多相关《构建组件.docx(31页珍藏版)》请在冰豆网上搜索。
构建组件
构建组件
ThispagelastchangedonNov29,2006bybseyler.
这个指南描述了为何及如何添加一个新组件进PentahoBusinessIntelligence(BI)套件。
假设你在读这篇文档之前,已经读了且理解了以下两篇指南:
Ø技术白皮书
Ø创建Solutions指南
或继续阅读这篇文档中的以下章节:
?
Architecture
?
BIComponentAPIs
?
InternalAPI
?
WhyCreateaPentahoComponent?
体系结构
ThispagelastchangedonDec05,2006bybseyler.
体系结构的设计使得每个组件仅需作最少量的操作,就可完成它的任务。
一个组件不必知道有关schedulers,工作流引擎,auditlogs,或其他组件的任何信息。
控制流
如果某人或某物需要PentahoSolutionEngine执行一个actionsequence时,就执行BI组件。
用户,schedulers,web服务,工作流引擎和API调用均可执行Actionsequences。
在所有的情况下,调用者可为actionsequence提供参数。
除了请求中的参数,actionsequence可定义来自其他地方的参数,例如一个session。
这一节和图表描述了当执行一个actionsequence时发生的事件的顺序。
1.启动。
在服务层调用一个对象,请求执行一个actionsequence。
这些对象使用一个实现了org.pentaho.core.services.IactionRequestHandler的requesthandler对象,创建org.pentaho.solution.SolutionEngine的一个实例,或使用org.pentaho.core.solution.SolutionHelper中的helper方法。
在每种情况下,parametersproviders被传送到solutionengine。
requesthandlers和solutionhelper创建SolutionEngine的一个实例,并调用它的'execute'方法,指定要执行的actionsequence的路径和名字,以及parameterprovider。
可以完成这个的对象实例有:
ØServlet:
org.pentaho.ui.servlet.ViewAction
ØUI组件:
ponent.ActionComponent
ØWeb服务:
org.pentaho.ui.servlet.HttpWebService
ØScheduler:
org.pentaho.plugin.quartz.QuartzExecute
ØAPI:
org.pentaho.core.solution.SolutionHelper
2.SolutionEngine的'execute'方法:
Ø检查已经提供了actionsequence路径和名字。
Ø创建IRuntimeElement和IruntimeContext的实例,实例创建的详细信息以及它和调用会话的关联被添加进auditlog。
如果process正长时间运行,RuntimeElement存储actionsequence的状态,RuntimeContext将处理组件的执行。
Ø调用SolutionRepository装载actionsequence。
如果不能找到actionsequence,返回一个错误给调用者,failure被audited。
Ø调用RuntimeContext的‘validateSequence’方法。
3.RuntimeContext的'validateSequence'方法:
Ø将actionsequence的日志级别设置需要的级别(可由初始调用者指定)
Ø为actionsequence中定义的每个action创建组件的一个实例。
如果sequence包括两个使用EmailComponent的actions,创建组件的两个实例。
不会对两个actions使用组件的相同实例。
RuntimeContext需要BIComponents有一个不接收参数的默认构造函数。
Ø为每一个组件提供不同的对象,例如调用者的session,需要的logginglevel和RuntimeContext。
Ø调用每个组件的‘validate’方法。
4.组件的'validate'方法:
Ø调用它自己的‘validateSystemSettings’方法来验证任何它需要的system-wide设置。
Ø调用它自己的‘validateAction’方法验证对它可用的输入,资源和输出(如在actionsequence中定义的)使之执行是足够的。
如果对任何组件,这些验证中的一个失败了,actionsequence的执行被终止,状态被返回给调用者。
5.SolutionEngine的‘execute’方法调用RuntimeContext的‘executeSequence’方法。
6.RuntimeContext的'executeSequence'方法:
逐步循环检查actionsequence中的action定义,对于每个定义的action,调用它的‘executeAction’方法。
7.RuntimeContext的'executeAction'方法:
ØAudits组件执行的起点。
Ø解释actionsequence中定义的组件可用的参数,例如来自requestparameterprovider,sessionparameterprovider或其他组件的输出。
Ø调用组件的‘init’方法。
8.组件的‘init’方法执行任何它需要的任何初始化步骤。
9.RuntimeContext的‘executeAction’方法调用它的‘executeComponent’方法。
10.RuntimeContext的‘executeComponent’方法调用组件的‘execute’方法。
11.组件的‘execute’方法执行完成它的功能所必需的步骤。
12.RuntimeContext的‘executeComponent’方法调用组件的‘done方法。
13.组件的‘done’方法执行任何必需的clean-up步骤。
14.RuntimeContext的‘executeAction’方法audits组件执行的终点。
15.SolutionEngine的'execute'方法
ØAuditsactionsequence执行的终点
Ø将RuntimeContext返回给调用者
16.终点。
调用者可使用RuntimeContext来:
Ø获取执行的最终状态
Ø获取actionsequence的output对象
Ø获取调试或错误信息
SolutionEngine
RuntimeContext
BIComponent
1.start
1.start
1.start
requesthandlers和solutionhelper创建SolutionEngine的一个实例,并调用它的‘execute’方法,指定要执行的actionsequence的路径和名字,以及parameterprovider。
requesthandlers和solutionhelper创建SolutionEngine的一个实例,并调用它的‘execute’方法,指定要执行的actionsequence的路径和名字,以及parameterprovider。
requesthandlers和solutionhelper创建SolutionEngine的一个实例,并调用它的‘execute’方法,指定要执行的actionsequence的路径和名字,以及parameterprovider。
2.execute()
Ø检查已经提供了actionsequence的路径和名字。
Ø创建IRuntimeElement和IRuntimeContext的一个实例。
Ø调用SolutionRepository装载actionsequence。
Ø调用RuntimeContext的'validateSequence'方法。
3.validateSequence()
Ø设置logginglevel。
Ø创建一个实例组件。
Ø为每个组件提供它需要的不同系统对象。
Ø调用每个组件的‘validate’方法。
4.validate()
Ø调用它的‘validateSystemSettings’方法验证它需要的任何systemwide设置。
Ø调用它的'validateAction'方法验证输入,资源和输出。
5.execute()
调用RuntimeContext的'executeSequence'方法。
.
6.executeSequence()循环逐步检查调用‘executeAction’的actionsequence中的action定义
7.executeAction()Audits一个组件执行的起点。
解释调用组件的‘init’方法的参数。
8.init()方法执行任何必需的初始化步骤
9.executeAction()调用'executeComponent'。
10.executeComponent()调用组件的'execute'方法。
11.execute()
执行完成其功能必需的步骤。
12.executeComponent()调用组件的'done方法。
13.done()
执行任何必需的clean-up步骤
14.executeAction()
Audits组件执行的终点。
15.execute()
Auditsactionsequence执行的终点。
返回RuntimeContext给调用者。
16.end
调用者可使用RuntimeContext:
Ø获取执行的最终状态。
Ø获取actionsequence的输出对象
Ø获取调试或错误信息。
如图所见,在SolutionEngine的‘execute’和组件的‘execute’间仅有几层方法调用。
这个轻量级的框架很强大,但并没有给系统带来太大的处理负载。
BIComponents并没有在对SolutionEngine的调用间缓存,必须是线程安全的。
如果一个BI组件需要创建任何全局资源或调用任何静态的初始化方法,必须编写实现了IPentahoSystemListener的一个类,并在‘system/pentaho.xml’中注册。
实例请参考org.pentaho.plugin.kettle.KettleSystemListener和org.pentaho.plugin.jfreereport.JFreeReportSystemListener。
每个BI组件都需要知道完成它的任务所需要的参数。
例如,scripting组件需要被提供脚本以被执行,而一个报表组件需要被提供报表模板,还要有数据。
BI组件APIs
ThispagelastchangedonDec04,2006bymlowery.
有四种创建BI组件的方式:
从头开始创建BI组件,将现有类转换成BI组件,创建ComponentBase(org.pentaho.plugin.ComponentBase)的子类,或创建SimpleComponent(org.pentaho.plugin.core.SimpleComponent)的子类。
为成为BI组件,Java对象必须实现ponent.IComponent接口。
IComponent接口扩展了其它两个接口:
org.pentaho.core.audit.IAuditable和org.pentaho.util.logging.ILogger。
Pentaho提供了实现了这些接口的类。
Pentaho类层次如下所示:
org.pentaho.core.system.PentahoBase(实现ILogger和Serializable)-->org.pentaho.core.system.PentahoMessenger
-->org.pentaho.plugin.ComponentBase(实现IComponent和IAuditable)-->org.pentaho.plugin.core.SimpleComponent
-->otherPentaho-providedBIComponents
你可在任何你喜欢的包里创建你的BI组件,不管它是否是Pentaho类的子类。
如果你使用一个非Pentaho包,就没有不可访问的必需方法。
扩展SimpleComponent
这是创建一个新组件的最简单的方式,推荐新手使用。
1.创建一个新的Java类,它是org.pentaho.plugin.core.SimpleComponent的子类(扩展)。
2.实现一个executeAction()方法和一个getLogger()方法。
这些方法的描述请参考下面的‘ComponentMethods’。
扩展ComponentBase
如果你的组件需要验证它的输入和/或系统设置,或需要执行任何初始化和/或清理,你应该扩展org.pentaho.plugin.ComponentBase。
1.创建一个新的Java类,它是org.pentaho.plugin.ComponentBase的子类(扩展)。
2.适当的在init,validateSystemSettings,validateAction,executeAction,done和getLogger方法中添加代码。
将一个Java对象转换成一个BI组件
如果你有一个现有对象,你想将之转换成一个BI组件,有两个选择:
Ø创建一个新对象,其是现有对象的子类,实现了必需的接口。
Ø修改你的对象以实现必需的接口。
哪种选择更适合于你的特定对象将依赖于你的特定环境,但我们建议创建一个子类,以保证你的源文件大小可管理。
如果你不必使用这个方法,可在这些类中找到创建你的新类所必需的大多数代码:
org.pentaho.core.system.PentahoBase,org.pentaho.core.system.PentahoMessenger和org.pentaho.plugin.ComponentBase。
为使这个过程更简单,我们已创建了一个类,org.pentaho.plugin.ComponentSubclassExample,其包含你需要的代码。
为将一个Java类转换成一个BI组件:
1.从org.pentaho.plugin.ComponentSubclassExample复制imports,成员变量和方法进你的Java类。
2.适当的在init,validateSystemSettings,validateAction,executeAction,done和getLogger方法中添加代码。
从头开始创建组件
为从头开始创建一个组件,必须创建一个实现了接口ponent.IComponent的新类。
为实现所有三个接口,需要实现大约30个方法。
不推荐使用这个选项,假如有其他选择,就没有必要采用这种方法。
组件方法
如果使用推荐的3个方法之一创建新组件,以下的方法就是需要被定制的BI组件方法,以提供你必需的功能。
列出了方法,以使之在正常处理中被调用。
依据创建你的组件的方法,不是所有的方法都是必需的。
更多信息请参考以上章节。
done
ThispagelastchangedonNov29,2006bymbatchelor.
调用这个方法,使组件有机会执行必需的cleanup操作。
executeAction
ThispagelastchangedonDec04,2006bymlowery.
调用这个方法,组件就能执行它的功能。
在这个方法中,你可调用其他内部API方法获取输入值,获取资源,询问用户参数,和获取输出流。
通常,在execute方法中,一个组件将:
1.收集输入值。
这些可能是参数或组件设置。
如果输入值是不完整的,组件可停止执行,或提示用户额外的信息。
2.收集资源。
这些可能是模板或定义文件。
3.获取某类输出pipe(例如一个输出流)。
4.创建输出内容。
5.返回执行状态。
我们将使用PrintComponent(org.pentaho.plugin.print.PrintComponent)的executeAction()方法作为一个实例(为了清晰做了一些小的修改)。
.
protectedbooleanexecuteAction(){
StringprintFileName=null;
IActionResourceprintFileResource=null;
//seeifweareprintingafileif(isDefinedInput("print-file")){
//getnameoffiletoprint
printFileName=getInputStringValue("print-file");
}
InputStreaminStream=null;
//Getnameofprintertouse
if(isDefinedInput("printer-name")){
printerName=getInputStringValue("printer-name");
}
//trytofindrequestedprinter
PrintServiceprinter=getPrinterInternal(printerName);
if(printer==null){
//requestedprinterisnotavailable
if(!
feedbackAllowed()){
//wearenotallowedtopromptuserforaprinter,wehavetofail
error("requestedprinter"+printerName+"isnotavailable");
returnfalse;
}
//promptuserforanavailableprinter
//getalistofavailableprintservices
PrintService[]services=PrinterJob.lookupPrintServices();
ArrayListvalues=newArrayList();
//addeachprintservicetoourlistofprinters
for(inti=0;iStringvalue=services[i].getName();
values.add(value);
}
//createaparameterforusertoselectfrom
createFeedbackParameter("printer-name",
"selectaprinter","",null,values,null,"select");
returnnull;
}promptNeeded();
returntrue;
}
//Getnumberofcopies
intcopies=1;
if(isDefinedInput("copies")){
copies=Integer.valueOf(getInputStringValue("copies")).intValue();
//CheckforavalidprintFileNameorprintFileResource
if(printFileName!
=null){
try{
inStream=newFileInputStream(printFileName);
}catch(FileNotFoundExceptionfnfe){
error(fnfe.toString(),fnfe);
returnfalse;
}
//Setinputsourceforsendingtodriver.
InputSourcesource=newInputSource(inStream);
try{
Driverdriver=newDriver(source,null);
PrinterJobpj=PrinterJob.getPrinterJob();
pj.setPrintService(printer);
PrintRendererrenderer=newPrintRenderer(pj,copies);
driver.setRenderer(renderer);
driver.run();
}catch(Exceptionex){
error("Couldnotprintdocument",ex);
returnfalse;
}
returntrue;
}
getLogger
ThispagelastchangedonNov29,2006bymbatchelor.
这个方法创建一个Log对象,其用于记录你的组件的日志信息。
它必须被你的组件(而不是一个超类)创建,这样日志就可以正确记录你的对象的