Russell Bateman
August 2016
last update:
Though I've been developing custom NiFi processors for the better part of a year now, I've never got around to making notes on the (rather confusing) set-up of a project in the filesystem and, especially, the pom.xml files needed to pull it off.
There are 3+ pom.xml files and your project necessarily has multiple modules as shown here. One is the "root" pom.xml, another is the pom.xml in the nar subdirectory, still another in the subdirectory (module) where resides the Java source code for your custom processor. (Here, I am only showing one subdirectory with code in it in this example. This is the processor subdirectory, but, if you intend spreading multiple custom processor code across multiple such subdirectories, you only need to them as siblings to processor as covered next.)
You can freely add more such subdirectories to this project—they each will have...
The trick is to get the multiple pom.xml files set up. You can't do it with one because you must built each module into its own JAR, then roll that JAR into the NAR for deployment to NiFi.
I named my project "Trick" so there would be no mistake, confusion or ambiguity as to what is what here. The important source artifacts are:
Note that there is nothing sacred about the subdirectory names, nar, processor, nor the project directory name, trick.
Here's what the project looks like when finished, but before any build. (I've got some IntelliJ IDEA files in here—they don't count):
~/dev/trick $ tree . ├── .idea ├── nar │ ├── pom.xml │ └── nar.iml ├── pom.xml ├── processor │ ├── pom.xml │ ├── processor.iml │ └── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── etretatlogiciels │ │ │ └── nifi │ │ │ └── processor │ │ │ └── Trick.java │ │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.apache.nifi.processor.Processor │ └── test │ └── java │ └── com │ └── etretatlogiciels │ └── nifi │ └── processor │ └── TrickTest.java └── trick.iml 18 directories, 9 files
Or, if clearer, this illustration (which is missing the Java test file for simplicity's sake):
The Maven build is done this way, to produce the NAR for deployment (not showing the copious Maven output, but only what the project filesystem looks like afterward). Your mileage may vary, but it should look something very much like this. The NAR file is clearly highlighted: it is built from an intermediate JAR file, processor-1.0.SNAPSHOT.jar. If you have multiple subdirectories (like processor here), each with code to build custom NiFi processors, the NAR will be built from JAR files underneath each of those subdirectories.
Note that some treatments of this topic give longer, more descriptive names to module/subdirectory names like nifi-processor-bundle, what I call simply parent here inside pom.xml, nifi-myprocessor-processor, what I call processor here, and nifi-myprocessor-nar, what I call nar. (Replace myprocessor with meaningful name that echo what you're doing, what you call your custom processor, etc.).
~/dev/trick $ mvn clean test package . . . ~/dev/trick $ tree . ├── .idea ├── nar │ ├── pom.xml │ ├── target │ │ ├── classes │ │ │ └── META-INF │ │ │ └── nar │ │ │ └── com.etretatlogiciels.nifi.processor │ │ │ └── nar │ │ │ └── nar.properties │ │ ├── maven-archiver │ │ │ └── pom.properties │ │ └── trick-nar-1.0-SNAPSHOT.nar │ └── nar.iml ├── pom.xml ├── processor │ ├── pom.xml │ ├── processor.iml │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ └── etretatlogiciels │ │ │ │ └── nifi │ │ │ │ └── processor │ │ │ │ └── Trick.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── services │ │ │ └── org.apache.nifi.processor.Processor │ │ └── test │ │ └── java │ │ └── com │ │ └── etretatlogiciels │ │ └── nifi │ │ └── processor │ │ └── TrickTest.java │ └── target │ ├── classes │ │ ├── com │ │ │ └── etretatlogiciels │ │ │ └── nifi │ │ │ └── processor │ │ │ └── Trick.class │ │ └── META-INF │ │ └── services │ │ └── org.apache.nifi.processor.Processor │ ├── generated-sources │ │ └── annotations │ ├── generated-test-sources │ │ └── test-annotations │ ├── maven-archiver │ │ └── pom.properties │ ├── maven-status │ │ └── maven-compiler-plugin │ │ ├── compile │ │ │ └── default-compile │ │ │ ├── createdFiles.lst │ │ │ └── inputFiles.lst │ │ └── testCompile │ │ └── default-testCompile │ │ ├── createdFiles.lst │ │ └── inputFiles.lst │ ├── processor-1.0-SNAPSHOT.jar │ ├── surefire-reports │ │ ├── com.etretatlogiciels.nifi.processor.TrickTest.txt │ │ └── TEST-com.etretatlogiciels.nifi.processor.TrickTest.xml │ └── test-classes │ └── com │ └── etretatlogiciels │ └── nifi │ └── processor │ └── TrickTest.class └── trick.iml 52 directories, 23 files
Here are the source files listed earlier. This processor is pretty much nonsense and doesn't do anything, and its test doesn't test anything. However, this exposé is only to help you get a) the pom.xml files and b) the layout of the project and important files.
The project's pom.xml files, for the project root, the source code subdirectory and the NAR-builder. Now, what's highlighted is very important for making the build work.
Mostly, this defines the modules to build the source code and bundle the NAR. It also holds the plug-in that Maven calls to build the NAR. trick is an ugly name for an artifact, but this is the parent that builds the NAR—this ugly name will only be seen in Maven, never on JAR artifacts or the NAR.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- root pom.xml --> <groupId>com.etretatlogiciels.nifi.processor</groupId> <artifactId>trick</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <description>Etretat Logiciels NiFi Processor</description> <properties> <nifi.version>1.9.2</nifi.version> <slf4j.version>1.7.21</slf4j.version> <junit.version>4.12</junit.version> <maven.compiler.plugin.version>3.5.1</maven.compiler.plugin.version> <nifi-nar-maven-plugin.version>1.3.1</nifi-nar-maven-plugin.version> <maven.install.skip>true</maven.install.skip> <maven.deploy.skip>true</maven.deploy.skip> </properties> <modules> <module>processor</module> <!-- as noted: you might have multiple such modules --> <module>nar</module> </modules> </project>
Notice that we're going to build trick-1.0.SNAPSHOT.jar. This will be supplied to the NAR file build later.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- processor/pom.xml --> <artifactId>processor</artifactId> <packaging>jar</packaging> <parent> <groupId>com.etretatlogiciels.nifi.processor</groupId> <artifactId>trick</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <dependencies> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-api</artifactId> <version>${nifi.version}</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-processor-utils</artifactId> <version>${nifi.version}</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-mock</artifactId> <version>${nifi.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.plugin.version}</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
Notice that we're going to build trick-nar-1.0.SNAPSHOT.nar. In order to do that, it's this pom.xml whose artifact identity must be "trick." The dependency is the JAR full of processor code built in the processor subdirectory.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- nar/pom.xml --> <artifactId>nar</artifactId> <packaging>nar</packaging> <parent> <groupId>com.etretatlogiciels.nifi.processor</groupId> <artifactId>trick</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <dependencies> <dependency> <groupId>com.etretatlogiciels.nifi.processor</groupId> <artifactId>processor</artifactId> <version>1.0-SNAPSHOT</version> <type>jar</type> </dependency> </dependencies> <build> <plugins> <plugin> <!-- what builds the NAR file... --> <groupId>org.apache.nifi</groupId> <artifactId>nifi-nar-maven-plugin</artifactId> <version>${nifi-nar-maven-plugin.version}</version> <extensions>true</extensions> </plugin> </plugins> </build> </project>
One last note. When ready to use the new processor, you have only to drop the .nar file into ${NIFI_ROOT}/lib, then restart NiFi.
After building, you should be able to see something like this, proving that the JAR (processor) and NAR (NiFi deployment artifact) were built:
russ@nargothrond ~/dev/trick $ find . -name '*.jar' ./nar/target/classes/META-INF/bundled-dependencies/nifi-api-1.9.2.jar ./nar/target/classes/META-INF/bundled-dependencies/jBCrypt-0.4.1.jar ./nar/target/classes/META-INF/bundled-dependencies/processor-1.0-SNAPSHOT.jar ./nar/target/classes/META-INF/bundled-dependencies/nifi-properties-1.9.2.jar ./nar/target/classes/META-INF/bundled-dependencies/jackson-core-2.9.7.jar ./nar/target/classes/META-INF/bundled-dependencies/jackson-annotations-2.9.0.jar ./nar/target/classes/META-INF/bundled-dependencies/jackson-databind-2.9.7.jar ./nar/target/classes/META-INF/bundled-dependencies/nifi-security-utils-1.9.2.jar ./nar/target/classes/META-INF/bundled-dependencies/nifi-processor-utils-1.9.2.jar ./nar/target/classes/META-INF/bundled-dependencies/bcprov-jdk15on-1.60.jar ./nar/target/classes/META-INF/bundled-dependencies/commons-lang3-3.8.1.jar ./nar/target/classes/META-INF/bundled-dependencies/nifi-utils-1.9.2.jar ./nar/target/classes/META-INF/bundled-dependencies/bcpkix-jdk15on-1.60.jar ./nar/target/classes/META-INF/bundled-dependencies/commons-io-2.6.jar ./nar/target/classes/META-INF/bundled-dependencies/commons-codec-1.11.jar ./processor/target/processor-1.0-SNAPSHOT.jar russ@nargothrond ~/dev/trick $ find . -name '*.nar' ./nar/target/trick-nar-1.0-SNAPSHOT.nar
package com.etretatlogiciels.nifi.processor; import java.util.List; import org.junit.Test; import static org.junit.Assert.assertEquals; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; public class TrickTest { private final static String TEST_CONTENT = "This is a test."; @Test public void testProcessor() { TestRunner runner = TestRunners.newTestRunner( Trick.class ); runner.setProperty( Trick.TRICK_PROPERTY, "This is just a property value." ); // will fail to validate without property runner.enqueue( TEST_CONTENT ); // injects flowfile content for testing runner.run( 1 ); // initializes processor, calls onTrigger() runner.assertQueueEmpty(); List< MockFlowFile > flowfiles = runner.getFlowFilesForRelationship( Trick.RELATIONSHIP ); MockFlowFile flowfile = results.get( 0 ); String content = new String( runner.getContentAsByteArray( flowfile ) ); assertEquals( "Changed flowfile content?", content, TEST_CONTENT ); } }
(What does this processor do? It merely transfers the in-coming flowfile straight through, unchanged, to the success relationship.)
package com.etretatlogiciels.nifi.processor; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.flowfile.FlowFile; import org.apache.nifi.annotation.documentation.CapabilityDescription; import org.apache.nifi.annotation.documentation.Tags; import org.apache.nifi.processor.AbstractProcessor; import org.apache.nifi.processor.ProcessContext; import org.apache.nifi.processor.ProcessSession; import org.apache.nifi.processor.ProcessorInitializationContext; import org.apache.nifi.processor.Relationship; import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.processor.util.StandardValidators; @Tags( { "trick" } ) @CapabilityDescription( "Trick processor." ) public class Trick extends AbstractProcessor { @Override public void onTrigger( final ProcessContext context, final ProcessSession session ) throws ProcessException { FlowFile flowfile = session.get(); if( flowfile == null ) { context.yield(); return; } session.transfer( flowfile, TRICK_RELATIONSHIP ); } public static final PropertyDescriptor TRICK_PROPERTY = new PropertyDescriptor.Builder() .name( "Trick Property" ) .description( "Just a property." ) .required( true ) .addValidator( StandardValidators.NON_EMPTY_VALIDATOR ) .build(); public static final Relationship TRICK_RELATIONSHIP = new Relationship.Builder() .name( "Trick relationship" ) .description( "Just a relationship." ) .build(); private List< PropertyDescriptor > properties; private Set< Relationship > relationships; @Override protected void init( final ProcessorInitializationContext context ) { final List< PropertyDescriptor > props = new ArrayList<>(); props.add( TRICK_PROPERTY ); this.properties = Collections.unmodifiableList( props ); final Set< Relationship > relationships = new HashSet<>(); relationships.add( TRICK_RELATIONSHIP ); this.relationships = Collections.unmodifiableSet( relationships ); } @Override public Set< Relationship > getRelationships() { return this.relationships; } @Override public final List< PropertyDescriptor > getSupportedPropertyDescriptors() { return properties; } }
com.etretatlogiciels.nifi.processor.Trick
It's a temptation to set up a project with simpler structure with only one module in IntelliJ IDEA (or a single Eclipse project) and I'll show a little of it here. Do not succumb to the temptation! What results will run and work, but only partially. Among things that do not work are that, when getting usage for the processor (in the UI canvas), you will not get what you put into the @CapabilityDescription annotation on your processor code. Instead, you get some generic or default documentation entitled Apache NiFi Overview and no discussion of your processor. There may be other aspects that do not work; what I report here is my own experience.
The "three-module" approach (covered above) is held by the Apache NiFi community as the minimum required for successful and complete custom processor building and deployment.
The following notes used to figure in these greater notes as an alternative until I discovered that it won't work. I leave it here for comparison to your own in case you stumble upon these notes because you've done it this way and you're in search of why it's not working.
Such structure uses a single pom.xml that contains everything to build trick-nar-1.0-SNAPSHOT.nar. The source code referred to is the same as above.
~/dev/trick $ tree . ├── .idea ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── etretatlogiciels │ │ │ └── nifi │ │ │ └── processor │ │ │ └── Trick.java │ │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.apache.nifi.processor.Processor │ └── test │ └── java │ └── com │ └── etretatlogiciels │ └── nifi │ └── processor │ └── TrickTest.java ├── target │ ├── classes │ ├── etc... │ └── trick-nar-1.0-SNAPSHOT.nar └── trick.iml
Here's the single pom.xml file at project's root. What keeps the documentation from working is probably that a NAR must be built from a (one or more) JAR and the full and complete bundling process does not occur.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.etretatlogiciels.nifi.processor</groupId> <artifactId>trick</artifactId> <version>1.0-SNAPSHOT</version> <packaging>nar</packaging> <description>Etretat Logiciels NiFi Processor</description> <properties> <nifi.version>1.9.2</nifi.version> <slf4j.version>1.7.21</slf4j.version> <junit.version>4.12</junit.version> <maven.compiler.plugin.version>3.5.1</maven.compiler.plugin.version> <nifi-nar-maven-plugin.version>1.3.1</nifi-nar-maven-plugin.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.install.skip>true</maven.install.skip> <maven.deploy.skip>true</maven.deploy.skip> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-api</artifactId> <version>${nifi.version}</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-processor-utils</artifactId> <version>${nifi.version}</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-mock</artifactId> <version>${nifi.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.nifi</groupId> <artifactId>nifi-nar-maven-plugin</artifactId> <version>${nifi-nar-maven-plugin.version}</version> <extensions>true</extensions> </plugin> </plugins> </build> </project>
First, we don't care especially how the name of the subordinate JAR(s) end up, here, processor-1.0.SNAPSHOT.jar because it's only the NAR that counts. (Although, you will see the JAR name(s) if you dig down into the NAR archive.)
But, the name of the resulting NAR above is awkward. It's formed from the NAR subdirectory pom.xml's artifactId:
${project.artifactId}-${project.version}.nar
Hence, it's not possible to name the artifactId the same as the parent's in nar subdirectory's pom.xml in order to get trick-1.0.SNAPSHOT.nar instead of trick-nar-1.0.SNAPSHOT.nar.
However, nifi-nar-maven-plugin gives us a work-around. Just add this to the plug-in configuration:
<build> <plugins> <plugin> <groupId>org.apache.nifi</groupId> <artifactId>nifi-nar-maven-plugin</artifactId> <version>${nifi-nar-maven-plugin.version}</version> <extensions>true</extensions> <configuration> <narName>${project.artifactId}-${project.version}</narName> </configuration> </plugin> </plugins> </build>
This works a charm and our distributable NAR receives the name trick-1.0-SNAPSHOT.nar.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.windofkeltia.processor</groupId> <artifactId>Claims</artifactId> <version>1.0</version> <packaging>pom</packaging> <description>X12 Claims Processor</description> <properties> <nifi.version>1.13.2</nifi.version> <yarsquidy.version>2.0.0</yarsquidy.version> <slf4j.version>1.7.21</slf4j.version> <junit.version>4.13.2</junit.version> <maven-antrun-plugin.version>3.0.0</maven-antrun-plugin.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.release>8</maven.compiler.release> <maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version> <maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version> <nifi-nar-maven-plugin.version>1.4.0</nifi-nar-maven-plugin.version> <maven.install.skip>true</maven.install.skip> <maven.deploy.skip>true</maven.deploy.skip> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <modules> <module>processor</module> <module>nar</module> </modules> </project>
This is one whose artifactId names the NAR file produced.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>x12-claims</artifactId> <packaging>nar</packaging> <parent> <groupId>com.windofkeltia.processor</groupId> <artifactId>Claims</artifactId> <version>1.0</version> <relativePath>../pom.xml</relativePath> </parent> <dependencies> <dependency> <groupId>com.windofkeltia.processor</groupId> <artifactId>processor</artifactId> <version>1.0</version> <type>jar</type> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.nifi</groupId> <artifactId>nifi-nar-maven-plugin</artifactId> <version>${nifi-nar-maven-plugin.version}</version> <extensions>true</extensions> <configuration> <narName>${project.artifactId}-${project.version}</narName> </configuration> </plugin> </plugins> </build> </project>
Of course, in a big NAR project, you'd have multiple subdirectories like this and they'd all be referenced in the root pom.xml's <modules ... > list.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>processor</artifactId> <packaging>jar</packaging> <parent> <groupId>com.windofkeltia.processor</groupId> <artifactId>Claims</artifactId> <version>1.0</version> <relativePath>../pom.xml</relativePath> </parent> <dependencies> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-api</artifactId> <version>${nifi.version}</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-processor-utils</artifactId> <version>${nifi.version}</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-mock</artifactId> <version>${nifi.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.yarsquidy</groupId> <artifactId>x12-parser</artifactId> <version>${yarsquidy.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.plugin.version}</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>${maven-antrun-plugin.version}</version> <executions> <execution> <phase>compile</phase> <configuration> <target> <!-- How to echo out properties and their definitions; uncomment this! <echoproperties /> --> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${maven-surefire-plugin.version}</version> <configuration> <systemPropertyVariables> <catalina.home>${project.build.directory}</catalina.home> <buildDirectory>${project.build.directory}</buildDirectory> </systemPropertyVariables> </configuration> </plugin> </plugins> </build> </project>
If you cannot restart the UI successfully after adding your NAR to the extensions subdirectory, checkout what's in logs/nifi-app.log If you get an error such as this one:
Failure to launch NiFi due to java.util.ServiceConfigurationError: \ org.apache.nifi.processor.Processor: Provider could not be instantiated
It could mean that you must add the following dependency to pom.xml in the nar subdirectory (where ${nifi.version} is the version of NiFi you intend to support):
<dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-standard-nar</artifactId> <version>${nifi.version}</version> <type>nar</type> </dependency>