Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
This document is intended to provide a walk-through of what is necessary
in order to add a new function to the Expression Language. Doing so requires
a handful of steps, so we will outline each of those steps here, in the order
that they must be done. While this documentation is fairly verbose, it is often
the case that reading the documentation takes longer than performing the tasks
outlined by the documentation.
1) In order to make the nifi-expression-language Maven module compile in your IDE, you may need to add the ANTLR-generated sources to your IDE's classpath.
This can be done using Eclipse, as follows:
- Right-click on the nifi-expression-language project
- Go to "Properties" on the context menu
- Go to the "Java Build Path" item in the left tree and choose the "Source" tab.
- Click "Add Folder..."
- Add the target/generated-sources/antlr3 folder. If this folder does not exist, first build the project from Maven and then
right-click on the nifi-expression-language project in Eclipse and click Refresh.
- Click OK to close all dialogs.
2) Add the method name to the Tokens for the Lexer
- Open the src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g file
- Add the function name to the list of tokens in this file. These functions are grouped by the number of arguments
that they take. This grouping mechanism could probably be made better, perhaps grouping by the type of function
provided. However, for now, it is best to keep some sort of structure, at least. If the function has optional
arguments, the function should be grouped by the maximum number of arguments that it takes (for example, the
substring function can take 1 or 2 arguments, so it is grouped with the '2 argument functions').
- We can add the function into our parsing logic by updating the #buildFunctionEvaluator method of the org.apache.nifi.attribute.expression.compile.ExpressionCompiler class.
A static import will likely need to be added to the Query class in order to reference the new token. The token can then be added to the existing
'case' statement, which will return a new instance of the Evaluator that was just added.
7) Add Unit Tests!
- Unit tests are critical for the Expression Language. These expressions can be used throughout the entire application and it is important that each function
perform its task properly. Otherwise, incorrect routing decisions could be made, or data could become corrupted as a result.
- Each function should have its battery of unit tests added to the TestQuery class. This class includes a convenience method named #verifyEquals that is
used to ensure that the Expression returns the same value, regardless of how it is compiled and evaluated.
8) Add Documentation!
- The documentation for each function is provided in the nifi-docs module, under src/main/asciidoc/expression-language-guide.adoc.
The format of the document is crucial to maintain, as this document is not only rendered as HTML in the NiFi Documentation page, but the
CSS classes that are used in the rendered docs are also made use of by the NiFi UI. When a user is entering an Expression Language expression and
presses Ctrl+Space, the UI provides auto-completion information as well as inline documentation for each function. This information is pulled
directly from the HTML that is generated from this expression-language-guide file.
- Rebuild NiFi and run the application. Add an UpdateAttribute Processor to the graph and add a new property. For the value, type the Expression Language
opening tokens ${ and then press Ctrl+Space to ensure that the function and its documentation is presented as expected. Most functions that are added
will require a Subject. In order to see the function, then, you will need to provide a subject, such as typing "${myVariable:" (without the quotes)
and then press Ctrl+Space. This step is important, as it is quite easy to make a mistake when creating the documentation using a free-form text editor,
and this will ensure that users receive a very consistent and quality experience when using the new function.