ExecuteGroovyScript

文档中心 › 组件索引 › ExecuteGroovyScript

ExecuteGroovyScript Processor

类型全限定名:cn.org.acal.lynxus.processors.groovyx.ExecuteGroovyScript

所属 Bundle:cn.org.acal.lynxus:lynxus-groovyx-nar:2.11.8

描述

执行自定义 Groovy 脚本来处理输入 FlowFile 并路由到标准关系。 脚本验证包含 5 分钟的超时,以避免动态依赖解析的潜在问题。

标签

scriptgroovygroovyx

属性

下表中,加粗的属性为必填项;其余为可选项。表格同时标注默认值、是否支持表达式语言,以及是否为敏感属性(值会被加密)。

名称默认值可选值描述
Script File要执行的脚本文件的路径。 只能使用脚本文件或脚本体之一
支持表达式语言:是(仅使用环境/系统变量求值)
Script Body要执行的脚本主体。 只能使用脚本文件或脚本体之一
Failure Strategyrollback
  • rollback
  • transfer to failure
处理未处理异常的方式。如果您想通过代码管理异常,请保持默认值 `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