'NIFI: NoClassDefFoundError - AbstractListProcessor

I'm extending a standard processor to create a custom nifi processor. The project builds fine. But, when I restart my nifi after adding the newly generated nar to lib/ directory, nifi fails to start with NoClassDefFoundError:

    java.lang.NoClassDefFoundError: org/apache/nifi/processor/util/list/AbstractListProcessor
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:370)
        at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
        at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
        at org.apache.nifi.nar.ExtensionManager.loadExtensions(ExtensionManager.java:138)
        at org.apache.nifi.nar.ExtensionManager.discoverExtensions(ExtensionManager.java:113)
        at org.apache.nifi.web.server.JettyServer.start(JettyServer.java:699)
        at org.apache.nifi.NiFi.<init>(NiFi.java:160)
        at org.apache.nifi.NiFi.main(NiFi.java:267)

Can someone help me understand if I'm missing something here.

I'm using the following dependencies in processor-bundle's POM.xml:

    <dependency>
        <groupId>org.apache.nifi</groupId>
        <artifactId>nifi-api</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.nifi</groupId>
        <artifactId>nifi-standard-processors</artifactId>
        <version>1.3.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.nifi</groupId>
        <artifactId>nifi-processor-utils</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.nifi</groupId>
        <artifactId>nifi-utils</artifactId>
        <version>1.3.0</version>
    </dependency>

My imports in my code:

    import org.apache.commons.io.IOUtils;
    import org.apache.nifi.components.PropertyDescriptor;
    import org.apache.nifi.flowfile.attributes.CoreAttributes;
    import org.apache.nifi.processor.ProcessContext;
    import org.apache.nifi.processor.util.StandardValidators;
    import org.apache.nifi.processor.util.list.AbstractListProcessor;
    import org.apache.nifi.processors.standard.util.FileInfo;
    import org.apache.nifi.processors.standard.util.FileTransfer;
    import org.apache.nifi.processors.standard.ListFile;


Solution 1:[1]

Generally processors aren't really meant to be extended and it would be better to not have a dependency on nifi-standard-nar. The nifi-processor-utils project exists to hold common code to share across processors like AbstractListProcessor:

https://github.com/apache/nifi/tree/master/nifi-nar-bundles/nifi-extension-utils

If there is other code in nifi-standard-processors that should be shared then we should look at refactoring and moving it into modules under nifi-extension-utils.

For now, you are probably better off copying and pasting ListFile, FileTransfer, and FileInfo into your own project and modifying them accordingly, and remove the dependency on nifi-standard-processors.

To answer the specific question about why you get that exception... its because your NAR needs to have a NAR dependency on nifi-standard-nar in order to resolve the classes at runtime. This wiki page shows an example which would be the same situation:

https://cwiki.apache.org/confluence/display/NIFI/Maven+Projects+for+Extensions#MavenProjectsforExtensions-LinkingProcessorsandControllerServices

Solution 2:[2]

check that in your nar (nifi archive) the file META-INF/MANIFEST.MF contains Nar-* attributes

for example this one defines dependency on another nar:

Nar-Dependency-Id: nifi-standard-services-api-nar

and libraries from nifi-standard-services-api-nar.nar will be available in classloader of your nar file...

read this:

https://nifi.apache.org/docs/nifi-docs/html/developer-guide.html#nars

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bryan Bende
Solution 2 daggett