ExecuteGroovyScript Processor
描述
执行自定义 Groovy 脚本来处理输入 FlowFile 并路由到标准关系。 脚本验证包含 5 分钟的超时,以避免动态依赖解析的潜在问题。
标签
属性
| 名称 | 默认值 | 可选值 | 描述 |
|---|---|---|---|
| Script File | | 要执行的脚本文件的路径。 只能使用脚本文件或脚本体之一 支持表达式语言:是(仅使用环境/系统变量求值) | |
| Script Body | | 要执行的脚本主体。 只能使用脚本文件或脚本体之一 | |
| Failure Strategy | rollback |
| 处理未处理异常的方式。如果您想通过代码管理异常,请保持默认值 `rollback`。如果选择 `transfer to failure` 且发生未处理异常,则在此会话中从传入队列接收的所有 FlowFile 将被转移到 `failure` 关系,并设置附加属性:ERROR_MESSAGE 和 ERROR_STACKTRACE。如果选择 `rollback` 且发生未处理异常,则从传入队列接收的所有 FlowFile 将被处罚并返回。如果处理器没有传入连接,则此参数无效。 |
| Additional Classpath | | 类路径列表以分号或逗号分隔。 您可以在文件名中使用“*”、“*.jar”等掩码。 支持表达式语言:是(仅使用环境/系统变量求值) |
动态属性
| 名称 | 值 | 描述 |
|---|---|---|
| 要更新的脚本引擎属性 | 要设置的值 | 使用动态属性值指定的值更新由动态属性键指定的脚本引擎属性。使用 `CTL.` 访问任何控制器服务,`SQL.` 访问任何 DBCPService,`RecordReader.` 访问 RecordReaderFactory 实例,或 `RecordWriter.` 访问任何 RecordSetWriterFactory 实例。 |
关系 (Relationships)
| 名称 | 描述 | 自动终止 |
|---|---|---|
failure | 处理失败的FlowFiles | 否 |
success | 已成功处理的 FlowFiles | 否 |
状态管理
| 作用域 | 描述 |
|---|---|
| LOCAL、CLUSTER | 脚本可以使用状态管理 API 来存储和检索状态。 有关更多详细信息,请参阅开发人员指南的状态管理器部分。 |
受限 (Restricted)
该组件不受限。
输入要求
该组件允许有传入连接。
另请参阅
详细说明
Groovy
概述
这是最"Groovy"的 Groovy 脚本 :)
脚本绑定:
| 变量 | 类型 | 说明 |
|---|---|---|
| session | cn.org.acal.lynxus.processor.ProcessSession | 用于获取、修改和转移输入文件的 |
| session | ||
| context | cn.org.acal.lynxus.processor.ProcessContext | 上下文(几乎没什么用) |
| log | cn.org.acal.lynxus.logging.ComponentLog | 该 |
| Processor 实例的日志器 | ||
| REL_SUCCESS | cn.org.acal.lynxus.processor.Relationship | success Relationship |
| REL_FAILURE | cn.org.acal.lynxus.processor.Relationship | failure Relationship |
| CTL | java.util.HashMap<String,ControllerService> | 由 |
| `CTL.*` Processor 属性定义的 | ||
| Controller Service 填充的 | ||
| Map。 | ||
带 |
||
| `CTL.` 前缀的属性可以链接到 | ||
| Controller Service,无需额外代码即可在脚本中访问该服务。 | ||
| SQL | java.util.HashMap<String, groovy.sql.Sql> | 由 |
| `SQL.*` Processor 属性定义的、连接到对应数据库的 | ||
| `groovy.sql.Sql` 对象填充的 | ||
| Map。 | ||
带 |
||
| `SQL.` 前缀的属性只能链接到 | ||
| DBCPService。 | ||
| RecordReader | java.util.HashMap<String,RecordReaderFactory> | 由 |
| `RecordReader.*` Processor 属性定义的 | ||
| Controller Service 填充的 | ||
| Map。 | ||
带 |
||
| `RecordReader.` 前缀的属性应链接到 | ||
| RecordReaderFactory Controller Service 实例。 | ||
| RecordWriter | java.util.HashMap<String,RecordSetWriterFactory> | 由 |
| `RecordWriter.*` Processor 属性定义的 | ||
| Controller Service 填充的 | ||
| Map。 | ||
带 |
||
| `RecordWriter.` 前缀的属性应链接到 | ||
| RecordSetWriterFactory Controller Service 实例。 | ||
| 动态 | ||
| Processor 属性 | cn.org.acal.lynxus.components.PropertyDescriptor | 所有不以 |
| `CTL.` 或 | ||
| `SQL.` 开头的 | ||
| Processor 属性都会绑定为脚本变量 |
SQL Map 详情
示例: 如果你定义了属性
`SQL.mydb` 并把它链接到任意
DBCPService,就可以在代码中这样访问:
SQL.mydb.rows('select * from mytable')
该 Processor 会在执行脚本前自动从 dbcp 服务获取连接,并尝试处理事务: 脚本发生异常时数据库事务自动回滚,成功时提交。 你也可以手动管理事务。 注意:脚本不能断开连接。
SessionFile - FlowFile 扩展
(cn.org.acal.lynxus.processors.groovyx.flow.SessionFile) 是 Extended Groovy Processor 中 session 返回的实际对象。 该 FlowFile 是一个引用 session 和真实 FlowFile 的容器。 这允许使用简化的语法处理文件 Attribute 和内容:
设置新的 Attribute 值
flowFile.ATTRIBUTE_NAME = ATTRIBUTE_VALUE
flowFile.'mime.type' = 'text/xml'
flowFile.putAttribute("ATTRIBUTE_NAME", ATTRIBUTE_VALUE)
// 等同于
flowFile = session.putAttribute(flowFile, "ATTRIBUTE_NAME", ATTRIBUTE_VALUE)
移除 Attribute
flowFile.ATTRIBUTE_NAME = null
// 等同于
flowFile = session.removeAttribute(flowFile, "ATTRIBUTE_NAME")
获取 Attribute 值
String a = flowFile.ATTRIBUTE_NAME
写入内容
flowFile.write("UTF-8", "THE CharSequence to write into flow file replacing current content")
flowFile.write("UTF-8") { writer ->
// 对
// java.io.Writer 做些处理...
}
flowFile.write { outStream ->
// 对输出流做些处理...
}
flowFile.write { inStream, outStream ->
// 对输入流和输出流做些处理...
}
获取内容
InputStream i = flowFile.read()
def json = new groovy.json.JsonSlurper().parse(flowFile.read())
String text = flowFile.read().getText("UTF-8")
把 FlowFile 转移到 success Relationship
REL_SUCCESS << flowFile
flowFile.transfer(REL_SUCCESS)
// 等同于:
session.transfer(flowFile, REL_SUCCESS)
使用 dbcp
import groovy.sql.Sql
// 定义名为
// `SQL.db`、连接到
// DBCPConnectionPool Controller Service 的属性
// 本例是一个
// H2 数据库示例
// 使用预编译语句从数据库读取值
// 并赋给
// FlowFile Attribute `db.yesterday`
def daysAdd = -1
def row = SQL.db.firstRow("select dateadd('DAY', ${daysAdd}, sysdate) as DB_DATE from dual")
flowFile.'db.yesterday' = row.DB_DATE
// 处理数据库中的
// BLOB 和
// CLOB 时,
// 使用
// groovy.sql.Sql.BLOB(Stream) 和
// groovy.sql.Sql.CLOB(Reader) 进行参数类型转换
// 把
// FlowFile 的内容写入数据库
// blob
flowFile.read { rawIn ->
def parms = [
p_id : flowFile.ID as Long, // 获取名为
// \`ID\` 的
// FlowFile Attribute
p_data: Sql.BLOB(rawIn), // 把输入流用作
// BLOB SQL 参数
]
SQL.db.executeUpdate(parms, "update mytable set data = :p_data where id = :p_id")
}
处理
Processor 启动与停止
在 extended groovy processor 中,你可以通过提供对应的静态方法来捕获 `start`、`stop` 和 `unscheduled` 事件:
import cn.org.acal.lynxus.processor.ProcessContext
import java.util.concurrent.atomic.AtomicLong
class Const {
static Date startTime = null;
static AtomicLong triggerCount = null;
}
static onStart(ProcessContext context) {
Const.startTime = new Date()
Const.triggerCount = new AtomicLong(0)
println "onStart $context ${Const.startTime}"
}
static onStop(ProcessContext context) {
def alive = (System.currentTimeMillis() - Const.startTime.getTime()) / 1000
println "onStop $context executed ${Const.triggerCount} times during ${alive} seconds"
}
static onUnscheduled(ProcessContext context) {
def alive = (System.currentTimeMillis() - Const.startTime.getTime()) / 1000
println "onUnscheduled $context executed ${Const.triggerCount} times during ${alive} seconds"
}
flowFile.'trigger.count' = Const.triggerCount.incrementAndGet()
REL_SUCCESS << flowFile