1
votes

I'm trying to make a custom processor in Apache NiFi that can add an attribute/string to the JSON object in the flowfile content. At the moment it works when I just use a string but it's not working when I use NiFi's expression language although I have it supported in my code.

The expression language is 100% correct as it works in another processor and I've also tried different attributes to make sure it's not the attribute.

The property:

public static final PropertyDescriptor ADD_ATTRIBUTE = new PropertyDescriptor
        .Builder().name("Add Attribute")
        .description("Example Property")
        .required(true)
        .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
        .expressionLanguageSupported(true)
        .build();

Later in my code when I want to get the value and put in the JSON object I use:

jsonObject.put("hostname", context.getProperty(ADD_ATTRIBUTE).evaluateAttributeExpressions().getValue());

I also made a Unit Test and it works when I assign a text value to the testrunner.setProperty. However I don't know how I can assign an attribute to the testrunner or how I can use expression language in my test.

Thanks in advance for any suggestions or a solution!

2
What is the return value you get from "context.getProperty(ADD_ATTRIBUTE).evaluateAttributeExpressions().getValue()"? - Joe Witt
Do you need anything from the input flowfile in evaluating your expression? If so be sure to pass the flowfile into the evaluateAttributeExpressions() call. - Joe Witt
Hi the return value is an empty string when I use expression language. When I just use a regular string, for example just "test", then the return value is "test". I don't need anything but also tried that to see if it did anything but it doesn't. - Matthias

2 Answers

5
votes

I'll put my answer from Hortonworks Community Connection here too FWIW:

If the expression refers to attributes on a flow file, you will need to pass a reference to the flow file into evaluateAttributeExpressions:

FlowFile flowFile = session.get();
jsonObject.put("hostname", context.getProperty(ADD_ATTRIBUTE).evaluateAttributeExpressions(flowFile).getValue());

If the property contains an attribute name (rather than an Expression containing an attribute name) and you want the value from the flow file:

jsonObject.put("hostname", flowFile.getAttribute(context.getProperty(ADD_ATTRIBUTE).getValue()));

If the attribute value itself contains Expression Language and you want to evaluate it, take a look at the following class:

org.apache.nifi.attribute.expression.language.Query
2
votes

Regarding testing...

Assuming you are evaluating the expression language against an incoming FlowFile (evaluateAttributeExpressions(flowFile)) then you can do the following:

runner.setProperty(ADD_ATTRIBUTE, "${my.attribute}");

Then create an attribute Map that has my.attribute in it:

final Map<String,String> attributes = new HashMap<>(); attributes.put("my.attribute", myAttribute);

Then enqueue some content with the attributes:

runner.enqueue(fileIn, attributes); runner.run();

An example from the code base:

https://github.com/apache/nifi/blob/1e56de9521e4bc0752b419ffc7d62e096db1c389/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/test/java/org/apache/nifi/processors/solr/TestPutSolrContentStream.java#L243