Thursday, February 1, 2018

InvokeScriptedProcessor template revisited (with Javascript)

I recently got a request on Google+ for a Javascript/Nashorn example of InvokeScriptedProcessor, and since I've done articles on an InvokeScriptedProcessor template (to port from ExecuteScript) for Groovy and Jython, I thought I'd do the same for Javascript, since the template also illustrates the methods you'd have to override in order to write your own InvokeScriptedProcessor that does more powerful/flexible things.

Javascript/Nashorn is a slightly peculiar animal in terms of its ScriptEngine. In Groovy and Jython you need to create a subclass of Processor, implement the requisite methods, and assign an instance of the subclass to the variable "processor". The same is true of Javascript, except in order to invoke methods on the "processor" object, it has to be an instance of ScriptObject (an internal Nashorn class) or ScriptObjectMirror (a class of the Nashorn scripting API). In our context, the script body/file of InvokeScriptedProcessor is the thing that gets evaluated and cast as a ScriptObjectMirror, which means we need a slightly different approach than just creating a subclass and setting "processor" to an instance of it.  Instead the script itself has to be able to be cast as a Processor, so it can be a ScriptObjectMirror and Processor at the same time.

To that end, we declare the Processor interface methods (and its inherited interface methods) as functions on the main script, and then we set the "processor" variable to "this". Another difference from the other scripting language examples is that you need variable access to the various Java classes (both in Java proper and the NiFi API) before you can instantiate them. So in the "imports" section you will see a number of Java.type() calls, to get JS references to the Java classes.  You will have to do the same if you reference other Java classes in your executeScript() body.

Speaking of which, I tried to keep the same approach to giving an obvious place to paste your ExecuteScript code into the InvokeScriptedProcessor template, to make porting from ExecuteScript to InvokeScriptedProcessor easier. The template follows:

////////////////////////////////////////////////////////////
// "imports" go here
////////////////////////////////////////////////////////////

var Processor = Java.type("org.apache.nifi.processor.Processor");
var Relationship =  Java.type("org.apache.nifi.processor.Relationship");
var HashSet =  Java.type("java.util.HashSet");
var log = null;
var REL_SUCCESS = new Relationship.Builder().name("success").description('FlowFiles that were successfully processed are routed here').build();
var REL_FAILURE = new Relationship.Builder().name("failure").description('FlowFiles that were not successfully processed are routed here').build();
    

function executeScript(session, context, log, REL_SUCCESS, REL_FAILURE) {
   ////////////////////////////////////////////////////////////
   // your code goes here
   ////////////////////////////////////////////////////////////
   
}


function initialize(context) { log = context.logger; }
function getRelationships() {
    var r = new HashSet(); 
    r.add(REL_FAILURE);
    r.add(REL_SUCCESS);
    return r; 
}
function validate(context) { return null; }
function getPropertyDescriptor(name) { return null; }
function onPropertyModified(descriptor, oldValue, newValue) { return null; }
function getPropertyDescriptors() { return null; }
function getIdentifier() { return null; }
function onTrigger(context, sessionFactory) {
        var session = sessionFactory.createSession();
        try {
            executeScript(session, context, log, REL_SUCCESS, REL_FAILURE);
            session.commit();
        } catch (t) {
            log.error("{} failed to process due to {}; rolling back session", Java.to([this, t], "java.lang.Object[]"));
            session.rollback(true);
            throw t;
        }
   }

processor = this;

As always, please let me know how/if this works for you, and of course comments, questions, and suggestions are welcome.  Cheers!

14 comments:

  1. Is there a way to modify Variables defined in the Process Group in a Groovyscript?

    ReplyDelete
  2. This is very helpful post.
    Do you plan to write post about ScriptedRecordSetWriter on javascript?
    Thanks

    ReplyDelete
  3. Hi,

    I am very new to NIFI.

    I have some case what to know how can I do

    So I have jason file contain multiple config but I would like to general flow file from that jason and put all the config to attribute can I use this script or how can I do

    [
    {
    "Name": "Debian",
    "Version": "9",
    "Install": "apt",
    "Owner": "SPI",
    "Kernel": "4.9"
    },
    {
    "Name": "Ubuntu",
    "Version": "17.10",
    "Install": "apt",
    "Owner": "Canonical",
    "Kernel": "4.13"
    }
    ]

    from this jason I would like to split in 2 flow file and that flow file contain attribute Name,Version,Install,Owner and kernel

    could you help provide some suggestion.

    ReplyDelete
  4. do you have any idea to use node.js in nifi InvokeScriptedProcessor?

    ReplyDelete
  5. I am impressed by the information that you have on this blog. It shows how well you understand this subject. hyip template

    ReplyDelete
  6. You might comment on the order system of the blog. You should chat it's splendid. Your blog audit would swell up your visitors. I was very pleased to find this site.I wanted to thank you for this great read!! website builder weebly

    ReplyDelete
  7. I was very pleased to find this site.I wanted to thank you for this great read!! I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post. iphonexr case

    ReplyDelete
  8. Cool you write, the information is very good and interesting, I'll give you a link to my site. best online digital marketing courses

    ReplyDelete
  9. Hi to everybody, here everyone is sharing such knowledge, so it’s fastidious to see this site, and I used to visit this blog daily Weight loss

    ReplyDelete
  10. I am always searching online for articles that can help me. There is obviously a lot to know about this. I think you made some good points in Features also. Keep working, great job ! Vanity mirror

    ReplyDelete
  11. I have read your article, it is very informative and helpful for me.I admire the valuable information you offer in your articles. Thanks for posting it.. patriotic shirt

    ReplyDelete
  12. You might comment on the order system of the blog. You should chat it's splendid. Your blog audit would swell up your visitors. I was very pleased to find this site.I wanted to thank you for this great read!! Dogecoin free

    ReplyDelete
  13. Binance, BTCTurk, Paribu sahibi kim merak ediyorsanız tıklayın: Binance, BTCTurk, Paribu Sahibi





    Binance, BTCTurk, Paribu ne zaman kuruldu merak ediyorsanız tıklayın: Binance, BTCTurk, Paribu Ne Zaman Kuruldu





    Komisyon oranları için tıklayın: BtcTurk, Binance, Paribu Güvenilir mi? Komisyon Oranları





    Hangisi güvenilir merak ediyorsanız tıklayın: Btcturk, Binance, Paribu Güvenilir mi

    ReplyDelete
  14. Cách tạo ra các hình của bạn đơn giản mà mình rất thích, mời các bạn xem các thông tin >> Quá trình mọc răng của trẻ diễn ra như thế nào ?

    ReplyDelete