mishkin
mishkin

Reputation: 6212

How to evaluate NiFi attributes, containing other attributes

I receive and load a templated text content from external application with placeholder like below to a flowFile attribute, called app_template:

Hello ${firstname} ${lastname},

thanks for contacting ${repname} and ${company}.

the placeholder in the template needs to be replaced with NiFi attributes, initialized upstream and these attributes are not pre-defined upfront. Basically, that template can contain any attribute names.

Is it possible to evaluate that template and resolve attributes so NiFi will substitute ${firstname} and ${lastname} with corresponding attribute values without using replace string functions?

Something as simple as ${app_template:evaluateAttributes()}...

Thanks!

Upvotes: 2

Views: 3793

Answers (3)

daggett
daggett

Reputation: 28564

you can use ExecuteGroovyScript processor with the following code

import groovy.text.SimpleTemplateEngine

def ff=session.get()
if(!ff)return
//read template from flow file content
def template = ff.read().withReader("UTF-8"){r->
    new SimpleTemplateEngine().createTemplate(r)
}
//get attributes and make a copy because for template it should be midifiable 
def attr = new HashMap(ff.getAttributes())
//build template with attributes as binding variables
ff.write("UTF-8"){w->
    template.make(attr).writeTo(w)
}
REL_SUCCESS << ff

Note:

this template supports groovy and jsp expressions: ${ firstname } and <%= firstname %>

also you could use a groovy jsp-like code injections: <% out.print( firstname.toUpperCase() ) %>

Upvotes: 3

mishkin
mishkin

Reputation: 6212

I just found another SO answer and looks like the only way is to use script processor In Apache NiFi, can I evaluate expression language without an attribute?

Upvotes: 1

Andy
Andy

Reputation: 14184

You can absolutely evaluate other attributes within the Expression Language of Apache NiFi. I believe your issue is that you are trying to do this at the same effective time as defining the other attributes, so this does not work (attribute definition is not deterministic in a single processor configuration).

However, by using an UpdateAttribute processor, you can populate an attribute with the contents of other attributes as you like. I've created a template which does this to demonstrate.

Attribute evaluation flow

UpdateAttribute configuration

--------------------------------------------------
Standard FlowFile Attributes
Key: 'entryDate'
    Value: 'Fri Feb 16 20:48:52 PST 2018'
Key: 'lineageStartDate'
    Value: 'Fri Feb 16 20:48:52 PST 2018'
Key: 'fileSize'
    Value: '63'
FlowFile Attribute Map Content
Key: 'appendFullName'
    Value: 'Andy LoPresto'
Key: 'filename'
    Value: '422457211196462'
Key: 'firstName'
    Value: 'Andy'
Key: 'fullName'
    Value: ' '
Key: 'joinFullName'
    Value: 'Andy LoPresto'
Key: 'lastName'
    Value: 'LoPresto'
Key: 'path'
    Value: './'
Key: 'substitutionFullName'
    Value: 'Andy LoPresto'
Key: 'uuid'
    Value: '2a8ba776-e059-46b2-bc5e-ccafd509356d'
--------------------------------------------------
This is a message generated at 2018/02/16 20:48:52.362 -0800.

Upvotes: 4

Related Questions