目錄
用create()搞一個新的FlowFile發送到下一個處理器
介紹
ExecuteScript 的 Groovy,Jython,Javascript(Nashorn)和JRuby 寫法, ExecuteScript優勢可言靈活的寫出內容,在運行中使用腳本。
幾個重要的玩意
- session(會話):這是對分配給處理器的ProcessSession的引用。會話允許您對流文件(如
create()
,putAttribute()
和transfer()
以及read()
和write()
()進行操作。 - context(上下文):這是對處理器的ProcessContext的引用。它可以用來檢索處理器屬性,關係,Controller服務和StateManager。
- log:這是對處理器ComponentLog的引用。用它來記錄消息給NiFi,比如
log.info('Hello world!')
- REL_SUCCESS:這是對處理器定義的“成功”關係的引用。它也可以通過引用父類(ExecuteScript)的靜態成員來繼承,但是一些引擎(如Lua)不允許引用靜態成員,所以這是一個方便的變量。這也節省了必須使用關係的完全合格的名稱。
- REL_FAILURE:這是對處理器定義的“失敗”關係的引用。和REL_SUCCESS一樣,它也可以通過引用父類(ExecuteScript)的靜態成員來繼承,但是一些引擎(如Lua)不允許引用靜態成員,所以這是一個方便的變量。這也節省了必須使用關係的完全合格的名稱。
- Dynamic Properties : 在ExecuteScript中定義的任何動態屬性都將作爲設置爲與動態屬性對應的PropertyValue對象的變量傳遞給腳本引擎。這允許您獲取屬性的String值,還可以針對NiFi表達式語言評估該屬性,將該值作爲適當的數據類型(例如布爾值)等進行轉換。由於動態屬性名稱會成爲腳本的變量名稱,您必須知道所選腳本引擎的變量命名屬性。例如,Groovy不允許在變量名稱中使用句點(。),因此如果“my.property”是一個動態屬性名稱,則會發生錯誤。
獲取文件前提條件
- 從會話中獲取傳入的流文件
- 在ExecuteScript 的前一個節點要有個流文件 FlowFile ,大部分處理器都ok
- 用 session.get() 就可以獲取
獲取流file小李子
-
Groovy
flowFile = session.get()
if(!flowFile) return
- jython
flowFile = session.get()
if (flowFile != None):
# All processing code starts at this indent
# implicit return at the end
- Javascript
var flowFile = session.get();
if (flowFile != null) {
// All processing code goes here
}
- JRuby
flowFile = session.get()
if flowFile != nil
# All processing code goes here
end
從回話中獲取多個流文件然後弄它
- 使用會話對象中的get(maxResults)此方法返回到來自工作隊列的maxResults FlowFiles
- 如果沒有FlowFiles可用,則返回一個空列表(該方法不返回null)
- 如果存在多個傳入隊列,則根據一次調用是否輪詢所有隊列或僅調用一個隊列,行爲是未指定的。
小李子
- Groovy
flowFileList = session.get(100)
if(!flowFileList.isEmpty()) {
flowFileList.each { flowFile ->
// Process each FlowFile here
}
}
- Jython
flowFileList = session.get(100)
if not flowFileList.isEmpty():
for flowFile in flowFileList:
# Process each FlowFile here
- Javascript
flowFileList = session.get(100)
if(!flowFileList.isEmpty()) {
for each (var flowFile in flowFileList) {
// Process each FlowFile here
}
}
- JRuby
flowFileList = session.get(100)
if !(flowFileList.isEmpty())
flowFileList.each { |flowFile|
# Process each FlowFile here
}
end
用create()搞一個新的FlowFile發送到下一個處理器
- 使用會話對象的create()方法。
- 此方法返回一個新的FlowFile對象,
- 在上執行進一步的處理
小李子
- Groovy
flowFile = session.create()
// Additional processing here
- Jython
flowFile = session.create()
# Additional processing here
- Javascript
var flowFile = session.create();
// Additional processing here
- JRuby
flowFile = session.create()
# Additional processing here
從基於傳入的FlowFile生成新的FlowFile
- 使用會話對象的create(parentFlowFile)方法。
- 此方法採用父級FlowFile引用
- 並返回一個新的子FlowFile對象。
- 新創建的FlowFile將繼承除UUID之外的所有父級屬性
- 此方法將自動生成Provenance FORK事件或Provenance JOIN事件
- 具體取決於在提交ProcessSession之前是否從同一父級生成了其他FlowFiles
栗子
- Groovy
flowFile = session.get()
if(!flowFile) return
newFlowFile = session.create(flowFile)
// Additional processing here
- Jython
flowFile = session.get()
if (flowFile != None):
newFlowFile = session.create(flowFile)
# Additional processing here
- Javascript
var flowFile = session.get();
if (flowFile != null) {
var newFlowFile = session.create(flowFile);
// Additional processing here
}
- JRuby
flowFile = session.get()
if flowFile != nil
newFlowFile = session.create(flowFile)
# Additional processing here
end
想要添加自定義屬性的流文件,爲流文件添加一個屬性
- 使用會話對象中的putAttribute(flowFile,attributeKey,attributeValue)方法
- 此方法使用給定的鍵/值對更新給定的FlowFile屬性
- 注意:“uuid”屬性對於FlowFile是固定的,不能修改; 如key被命名爲“uuid”,它將被忽略。
FlowFile對象介紹
這也是一個很好的提及FlowFile對象是不可變的;這意味着如果您通過API更新FlowFile的屬性(或以其他方式更改),則會獲得新版本的FlowFile的新參考。將FlowFiles傳輸到關係時,這是非常重要的。您必須保留對最新版本FlowFile的引用,並且必須傳輸或刪除從會話中檢索或創建的所有FlowFiles的最新版本,否則在執行時會出現錯誤。大多數情況下,用於存儲FlowFile引用的變量將被從改變FlowFile的方法返回的最新版本覆蓋(中間FlowFile引用將自動丟棄)。在這些示例中,您將看到添加屬性時重新使用flowFile引用的這種技術。請注意,對FlowFile的當前引用被傳遞給putAttribute()方法。生成的FlowFile具有名爲“myAttr”的屬性,其值爲“myValue”。另請注意,該方法需要一個字符串的值;如果你有一個對象,你將不得不將它序列化爲一個字符串。最後,請注意,如果您要添加多個屬性,最好創建一個Map並使用putAllAttributes()來代替 看下邊栗子
小李子
- Groovy
flowFile = session.get()
if(!flowFile) return
flowFile = session.putAttribute(flowFile, 'myAttr', 'myValue')
- Jython
flowFile = session.get()
if (flowFile != None):
flowFile = session.putAttribute(flowFile, 'myAttr', 'myValue')
# implicit return at the end
- Javascript
var flowFile = session.get();
if (flowFile != null) {
flowFile = session.putAttribute(flowFile, 'myAttr', 'myValue')
}
- JRuby
flowFile = session.get()
if flowFile != nil
flowFile = session.putAttribute(flowFile, 'myAttr', 'myValue')
end
想要添加自定義屬性的流文件,將多個屬性添加到流文件
- 使用會話對象中的putAllAttributes(flowFile,attributeMap)方法。
- 此方法使用給定Map中的鍵/值對更新給定的FlowFile屬性。
- 注意:“uuid”屬性對於FlowFile是固定的,不能修改;如果密鑰被命名爲“uuid”,它將被忽略。
Map介紹
這裏的技術是創建一個你想更新的屬性鍵/值對的Map(Jython中的字典,JRuby中的Hash),然後調用putAllAttributes()。這比爲每個鍵/值對調用putAttribute()要高效得多,因爲後一種情況會導致框架爲添加的每個屬性創建一個臨時版本的FlowFile。這些示例顯示了兩個條目myAttr1和myAttr2的映射,設置爲“1”,將數字2的語言特定的強制轉換爲字符串(以符合key和value均需要字符串值的方法簽名)。請注意,session.transfer()沒有在這裏指定(所以下面的代碼片段不工作)
示例
- Groovy
attrMap = ['myAttr1': '1', 'myAttr2': Integer.toString(2)]
flowFile = session.get()
if(!flowFile) return
flowFile = session.putAllAttributes(flowFile, attrMap)
- Jython
attrMap = {'myAttr1':'1', 'myAttr2':str(2)}
flowFile = session.get()
if (flowFile != None):
flowFile = session.putAllAttributes(flowFile, attrMap)
# implicit return at the end
- Javascript
var number2 = 2;
var attrMap = {'myAttr1':'1', 'myAttr2': number2.toString()}
var flowFile = session.get()
if (flowFile != null) {
flowFile = session.putAllAttributes(flowFile, attrMap)
}
- JRuby
attrMap = {'myAttr1' => '1', 'myAttr2' => 2.to_s}
flowFile = session.get()
if flowFile != nil
flowFile = session.putAllAttributes(flowFile, attrMap)
end
從流文件中獲取屬性
- 使用FlowFile對象的getAttribute(attributeKey)方法。
- 此方法返回給定attributeKey的String值,如果找不到attributeKey,則返回null。 這些例子顯示了檢索“filename”屬性的值。
栗子
- Groovy
flowFile = session.get()
if(!flowFile) return
myAttr = flowFile.getAttribute('filename')
- Jython
flowFile = session.get()
if (flowFile != None):
myAttr = flowFile.getAttribute('filename')
# implicit return at the end
- Javascript
var flowFile = session.get()
if (flowFile != null) {
var myAttr = flowFile.getAttribute('filename')
}
- JRuby
flowFile = session.get()
if flowFile != nil
myAttr = flowFile.getAttribute('filename')
end
從流文件獲取所有屬性 all
- 使用FlowFile對象的getAttributes()方法。
- 此方法返回一個帶有String鍵和String值的Map,表示流文件的屬性的鍵/值對。示例顯示了對FlowFile的所有屬性的Map的迭代。
栗子:
- Groovy
flowFile = session.get()
if(!flowFile) return
flowFile.getAttributes().each { key,value ->
// Do something with the key/value pair
}
- Jython
flowFile = session.get()
if (flowFile != None):
for key,value in flowFile.getAttributes().iteritems():
# Do something with key and/or value
# implicit return at the end
- Javascript
var flowFile = session.get()
if (flowFile != null) {
var attrs = flowFile.getAttributes();
for each (var attrKey in attrs.keySet()) {
// Do something with attrKey (the key) and/or attrs[attrKey] (the value)
}
}
- JRuby
flowFile = session.get()
if flowFile != nil
flowFile.getAttributes().each { |key,value|
# Do something with key and/or value
}
end
將流文件轉移到關係 (“成功”或“失敗”)
- 在處理流文件(新建或傳入)之後,您要將流文件轉換爲關係(“成功”或“失敗”)。
- 在這種簡單的情況下,讓我們假設有一個名爲“errorOccurred”的變量,指出FlowFile應該傳送到哪個關係。
- 使用會話對象的transfer(flowFile,relationship)方法。
- 此方法根據給定的關係將給定的FlowFile傳送到適當的目標處理器工作隊列。
- 從文檔:如果關係導致多於一個目的地,則FlowFile的狀態被複制,使得每個目的地都接收到FlowFile的精確副本,儘管每個目的地將具有其自己的唯一標識。
重點
- ExecuteScript將在每次執行結束時執行session.commit()以確保操作已被提交。不需要(也不應該)在腳本中執行session.commit()。
栗子
- Groovy
flowFile = session.get()
if(!flowFile) return
// Processing occurs here
if(errorOccurred) {
session.transfer(flowFile, REL_FAILURE)
}
else {
session.transfer(flowFile, REL_SUCCESS)
}
- Jython
flowFile = session.get()
if (flowFile != None):
# All processing code starts at this indent
if errorOccurred:
session.transfer(flowFile, REL_FAILURE)
else:
session.transfer(flowFile, REL_SUCCESS)
# implicit return at the end
- Javascript
var flowFile = session.get();
if (flowFile != null) {
// All processing code goes here
if(errorOccurred) {
session.transfer(flowFile, REL_FAILURE)
}
else {
session.transfer(flowFile, REL_SUCCESS)
}
}
- JRuby
flowFile = session.get()
if flowFile != nil
# All processing code goes here
if errorOccurred
session.transfer(flowFile, REL_FAILURE)
else
session.transfer(flowFile, REL_SUCCESS)
end
end
設置自己的日誌和日誌級別弄起來
- 使用帶有warn(),trace(),debug(),info()或error()方法的log變量。
這些方法可以採用單個字符串,或者一個字符串,後跟一個對象數組,或者一個字符串,後跟一個Throwable對象數組。第一個用於簡單的消息。當你有一些你想記錄的動態對象/值的時候使用第二種。要在消息字符串中引用這些消息,請在消息中使用“{}”。這些是按照外觀順序對Object數組進行評估的,所以如果消息的內容是“Found these things:{} {} {}”,而Object數組是[‘Hello’,1,true],那麼記錄的消息將會是“找到這些東西:你好1true”。這些日誌記錄方法的第三種形式也需要一個Throwable參數,並且在發生異常並且想要記錄它時非常有用。
栗子
- Groovy
log.info('Found these things: {} {} {}', ['Hello',1,true] as Object[])
- Jython
from java.lang import Object
from jarray import array
objArray = ['Hello',1,True]
javaArray = array(objArray, Object)
log.info('Found these things: {} {} {}', javaArray)
- Javascript
var ObjectArrayType = Java.type("java.lang.Object[]");
var objArray = new ObjectArrayType(3);
objArray[0] = 'Hello';
objArray[1] = 1;
objArray[2] = true;
log.info('Found these things: {} {} {}', objArray)
- JRuby
log.info('Found these things: {} {} {}', ['Hello',1,true].to_java)
ok
持續更新