Why custom NiFi processor rebuilds are the step teams underestimate
If your team runs custom NARs on NiFi 1.x, every one of them must be rebuilt against the NiFi 2 API and tested before cutover, because the 1.x line cannot be carried forward. The NiFi project explains that 1.x cannot be maintained further because it depends on Jetty 9.4, Spring Framework 5.3 and AngularJS 1.8, which cannot be upgraded within that line. Staying on 1.x therefore means running extensions on a platform that will not receive the fixes you need, so the rebuild is a required step rather than an optional cleanup.
The supported path runs through NiFi 1.27.0. The NiFi migration guidance requires upgrading to 1.27.0 before moving to 2.0.0, and it also changes the flow configuration file from flow.xml.gz to flow.json.gz. Teams often plan the custom code work as a single build change, but the work spans the API, packaging, UI and expression language, and each change can break a processor that compiled cleanly before. Treat the NiFi migration guidance as the reference list of changes, and map each one to the classes, resources and flows in your own NARs before estimating the work.
Ask for an inventory before committing to a schedule: every custom NAR, the NiFi version it was built against, its third-party dependencies, and every flow that references its components. Confirm which of those components use removed expression language scopes or deprecated APIs, and which depend on a JDK or servlet stack that must change. A NAR that is only tested against a development instance can pass a build and still fail in a cluster, so plan the test environment as part of the rebuild rather than after it.
Code changes NiFi 2 requires in custom NARs
This table lists the code, build and packaging changes that NiFi 2 asks of custom processor bundles, with the impact of each and the action to take. Read each row as a checklist item for the rebuild, and confirm the exact class names and method signatures against the NiFi 2 API and component documentation before editing code. The main takeaway is that most changes are mechanical, but a missed one can stop a NAR from loading or change how a component behaves.
| Change | Impact | Action needed |
|---|---|---|
| Java 21 as the minimum runtime | Custom NARs built for older Java targets may fail to load or run on NiFi 2 hosts that use Java 21. | Compile and test against Java 21, and confirm the build target and any third-party dependencies support it. |
| javax.servlet to jakarta.servlet imports (Servlet API 6 from 2.0.0-M2) | Code that imports javax.servlet classes will not compile or bind against the NiFi 2 web layer. | Replace javax.servlet imports with jakarta.servlet, then check any libraries bundled in the NAR for the same change. |
| Null no longer accepted in property descriptor defaultValue() | Descriptors that pass null as the default value will fail at build or startup. | Remove null defaults and use an explicit default value, or omit the default where the API allows it. |
| additionalDetails.html moved to additionalDetails.md in 2.0.0 | Component help content in the old HTML file is no longer the file NiFi reads, so help text may be missing. | Write the component documentation in additionalDetails.md and confirm the file path inside the NAR resources. |
| Custom Advanced UIs open at the web application root instead of /configure | Bookmarks, links or proxy rules that target the /configure path can break for operators. | Update links and reverse proxy rules, and confirm the root path behavior in the NiFi 2 Developer's Guide. |
| VARIABLE_REGISTRY expression language scope removed, replaced by ENVIRONMENT scope | Property descriptors that declare VARIABLE_REGISTRY scope no longer match the platform, and expressions may not resolve as expected. | Change the scope to ENVIRONMENT and test each property that uses expression language with parameter contexts. |
| Rebuild against the NiFi 2.0 API | NARs compiled against 1.x APIs may reference removed or changed classes and will not load correctly. | Update the nifi-api and related dependency versions to the NiFi 2.0 API, rebuild every NAR, and confirm the API version in the NiFi component documentation. |
How to find every NAR and code path that breaks
Start by listing every custom NAR and the flows that instantiate its processors, controller services and reporting tasks, because a rebuild is only as complete as that inventory. Pull the source for each custom bundle into version control, record its Maven parent and NiFi API version, and list any third-party libraries it packages. Then search the source tree for the patterns the migration guidance names: javax.servlet imports, which must become jakarta.servlet; additionalDetails.html files, which must be converted to additionalDetails.md; defaultValue() calls that pass null; VARIABLE_REGISTRY in expression language scope declarations; and any path or link that assumes the old /configure route for a custom Advanced UI. Each hit is a change to make or a test to write, and the search results should be attached to the change ticket.
Search results alone miss what flows actually do at runtime. NiFi 2 writes the flow configuration to flow.json.gz instead of flow.xml.gz, so take the flow definition from your 1.x environment through the migration path and then load it into the 2.x test cluster. Once it loads, check every processor and controller service that comes from a custom NAR for invalid or missing state, since a component can load in a stopped or invalid condition when its properties or scope no longer match. Also confirm that any expression language reference to a variable still resolves, because a flow that references a removed scope will not fail at load time in a way that is obvious to operators.
Treat the flow check as a list of confirmations rather than a pass-fail count. Ask the team that owns each NAR to confirm the Java 21 build target, the Servlet 6 dependency set and the test coverage for each property descriptor. Confirm with the flow owners which processors feed production data paths, because those are the ones that need a replay test against sample data before cutover. The NiFi migration guidance and the deprecated components documentation are the reference for the exact change list, so verify each item against the version you are targeting rather than relying on memory of an earlier release.
What to prepare before rebuilding NARs
Rebuilding custom NARs against the NiFi 2 API is mostly a preparation exercise. The six items below decide whether you can tell a compile fix from a behavior change, and whether you can roll back if a rebuilt bundle misbehaves in a cluster.
Source inventory and build baseline
List every custom NAR, its source repository, the NiFi version it was built against, and every processor, controller service and Advanced UI it contains. Record the current build tool, dependency versions and any shaded libraries. Build the unchanged 1.x source once and keep that output as the baseline, so later failures can be traced to your code changes rather than to a drifting toolchain or a dependency that moved while you were preparing.
NiFi 2 build and test environment
Stand up a build host or CI runner on the Java 21 runtime that the NiFi administration guide lists as the minimum, and compile against the NiFi 2 API rather than the 1.x API. Pin the JDK build and the Maven or Gradle plugin versions. Confirm that your build fails on the javax.servlet imports and the removed variable registry scope so you know the compiler is checking what you expect.
Production flow copy and sample data
Export the flows that use each custom component, then take a sanitized copy of production flow definitions and a representative sample of input data, including edge cases such as malformed records, large payloads and duplicates. Use these for regression runs. Keep sensitive values out of the copy, and confirm that the flow definitions you test in a NiFi 2 instance are the same ones that run in production, so results reflect real configurations.
Version control for NAR source
Place each custom extension in a Git repository with tagged 1.x release points, a branch for the NiFi 2 port, and a documented build command that anyone on the team can run. Record which commit produced each NAR artifact and its checksum. This history lets you compare behavior between versions, reproduce a build for audit, and tell the team exactly which code is running in each environment.
Named owners for behavior changes
Assign an owner for each custom component who can approve any change in observable behavior, such as altered property validation, changed output attributes, different record handling or new Markdown documentation. Agree in advance who reviews deprecated API replacements and who accepts a difference in test results. Without named owners, compile fixes tend to merge quietly, and a changed default only appears after data has already flowed through production.
Rollback copy of 1.x NARs
Keep the built 1.x NAR files, their checksums and the matching flow definitions in a controlled artifact store before any cluster change. Confirm that you can redeploy them to the 1.x instance without rebuilding from source. This matters most when you run a mixed estate during migration, because a rollback that depends on a rebuild can take longer than the window you planned for the cutover.
How rebuild work differs by component type
Custom processors are the most common rebuild target and usually the first to fail compilation. NiFi 2.0.0-M2 moved from Servlet API 3 to Servlet API 6, so any code that imports javax.servlet must switch to jakarta.servlet. Descriptor logic also changed: passing null to a property descriptor's defaultValue() is no longer supported, so defaults must be explicit values. Processors must also be compiled against the NiFi 2.0 API and built on Java 21.
- Servlet imports: replace every
javax.servletreference, including indirect uses through helper libraries. - Descriptor defaults: remove any
defaultValue(null)calls and set an explicit value or leave the default unset. - Expression language scope: drop any use of the VARIABLE_REGISTRY scope and move references to parameter contexts or ENVIRONMENT.
- Build target: compile against the NiFi 2 API and Java 21, not the 1.x baseline.
- Additional details: move documentation from
additionalDetails.htmltoadditionalDetails.md.
Retest each processor against a flow that exercises every relationship, property validation path and expression language configuration, and confirm the NAR loads with no missing class errors on a clean NiFi 2 node.
Controller services share the same Java, servlet and descriptor changes as processors, but they fail in a different way. A service may compile and load while a processor that depends on it breaks at enable time, so the service needs its own test pass. Services that expose connection pools, clients or credentials also tend to touch expression language and sensitive values, which changed with the variable registry removal.
- Service API: confirm the service interface still matches what consuming processors call after the NiFi 2 rebuild.
- Enable and disable: test enabling, disabling and restarting the service, since lifecycle errors often appear only then.
- Variable references: check that any property moved from the variable registry now resolves through a parameter context.
- Descriptor rules: apply the same null default and jakarta changes used in processors.
- Consumer tests: run each dependent processor against the rebuilt service with realistic credentials and endpoints.
Confirm that every processor referencing the service is listed and tested, because a service that enables cleanly can still break its consumers.
Custom Advanced UIs are the part of an extension most likely to break silently. In NiFi 2.0.0, these UIs open at the web application root instead of /configure. Any link, redirect, bookmark, or hard-coded path in the UI code or in operator runbooks that assumes the old path will fail or load the wrong page. The UI also runs inside the NiFi web application, so its servlet and resource references must follow the jakarta changes.
- Root path: update routes and redirects so the UI loads from the web application root.
- Servlet references: move any servlet or filter code to
jakarta.servletpackages. - Asset paths: check relative URLs for scripts, styles and images, which can resolve differently after the path change.
- Operator links: update bookmarks, saved links and monitoring checks that point at
/configure. - Browser coverage: test the UI in the browsers your operators use, with the configured authentication provider active.
Retest the UI after login, after a page reload and from a deep link, since these are the paths most often broken by a root path change.
Component documentation is easy to overlook because it does not affect compilation, but NiFi 2 reads it from a new file name. Documentation written as additionalDetails.html in 1.x must be converted to additionalDetails.md in NiFi 2.0.0. Documentation that is left behind will not appear in the component help that operators and flow designers use while building flows, which slows adoption and invites misconfiguration.
- File rename: convert each
additionalDetails.htmlfile to Markdown and place it at the new path. - Content review: check that HTML-only markup, such as inline tables or scripts, renders correctly in Markdown.
- Links and images: update any links or image references that depended on the old HTML layout.
- Packaging: confirm the Markdown file is included in the rebuilt NAR.
- Help dialog: open the component help in a running NiFi 2 instance and check the rendered page.
Check the help dialog for every rebuilt component, because a missing or unrendered page is only visible in the running UI.
Rebuild and test sequence for custom NARs
This sequence turns custom NiFi processor code into tested NARs that run on NiFi 2, with a clear check and rollback point at each stage so a failed rebuild never reaches the production cluster. It ends with NARs staged for cluster cutover.
Pin the NiFi 2 API target
The developer sets the nifi-api and nifi-framework dependency versions in the Maven build to a NiFi 2.x release, selects the Java 21 compiler target, and records the chosen version in the project's build notes. The team confirms which 2.x release the test node will run so the NAR is built against the same API it will load under. Check: a clean build with the pinned version compiles without falling back to 1.x artifacts. Rollback: keep the 1.x branch and build tags untouched so the original NAR can be rebuilt at any time.
Fix imports and property descriptors
The developer replaces every javax.servlet import with the jakarta.servlet equivalent, which NiFi 2.0.0-M2 and later require after the move to Servlet API 6. In the same pass, each PropertyDescriptor that passed null to defaultValue() is changed to omit the call or supply a real default. Check: a compile with warnings treated as errors passes, and a grep for javax.servlet and defaultValue(null) returns no hits in main or test code. Rollback: revert the commit that contains the import and descriptor changes, which should be isolated from behavior changes.
Move additional details to Markdown
Component documentation moves from additionalDetails.html to additionalDetails.md in NiFi 2.0.0. The developer converts each file, keeps the same resource path under the component's package, and checks that the rendered help text still describes the current property names and relationships. Check: the NAR's docs folder contains the .md file and the processor help opens in a test build without a missing-document error. Rollback: keep the original HTML files in version control until the Markdown version has been reviewed.
Remove VARIABLE_REGISTRY expression language scope
The developer finds every property that declares the VARIABLE_REGISTRY expression language scope and changes it to a scope NiFi 2 supports, normally FLOWFILE_ATTRIBUTES or ENVIRONMENT where the value is read from the environment. Values that were previously sourced from variable registry entries are reviewed with the flow owner so they can move to parameter contexts. Check: a search for VARIABLE_REGISTRY in the source returns nothing, and unit tests that resolve expressions pass. Rollback: restore the previous descriptor set on the branch, since the change alters how property values are resolved.
Build and run unit tests
The developer runs the Maven build with the NiFi test harness, covering processor validation, relationship routing, property validation and any controller service mocks. The team reviews failing tests and adds cases for the changes made in earlier steps, such as jakarta servlet handlers and expression language resolution. Check: the build produces a NAR file, the NAR manifest shows the expected NiFi API dependency, and all unit tests pass. Rollback: if a test cannot be fixed without changing behavior, tag the commit and hold the NAR out of the test node until the cause is understood.
Deploy to a NiFi 2 test node
The team copies the NAR into the lib directory of a NiFi 2 test node that matches the target release and Java 21 runtime, then loads a copy of the production flow converted to the flow.json.gz configuration format. The migration guidance requires that flow file format for NiFi 2, so the conversion must be completed before this step. Check: the node starts, the custom processor appears in the component list without a missing-component warning, and the flow validates. Rollback: remove the NAR from the lib directory and restart the node with the previous flow file, which is retained from the 1.x instance.
Run flow regression tests with provenance comparison
The flow owner feeds a fixed set of representative inputs through the flow on the 1.x instance and the NiFi 2 test node, then compares output content, attributes, routing relationships and provenance event types for each run. Differences in attribute values, dropped events or changed routing are logged and traced to the custom processor or to the NiFi 2 changes. Check: every expected output matches or each difference has a documented, accepted cause. Rollback: keep the 1.x flow running in production and return the test node to the previous NAR until differences are resolved.
Confirm custom UI paths
If the NAR includes a custom Advanced UI, the team confirms that it opens at the web application root in NiFi 2 rather than at the /configure path used in earlier releases. Links, bundled scripts and any hard-coded URLs in the UI are updated to match, and the team checks that the UI loads for a user with the expected authorization. Check: the Advanced UI opens from the processor configuration dialog on the test node and its API calls succeed. Rollback: restore the previous UI routes in a separate build if the change cannot be completed in time.
Stage NARs for cluster cutover
The team publishes the verified NAR, its checksum, the build version and the test evidence to the artifact store used for deployments, and records the exact NiFi 2 release each NAR was built against. The cluster upgrade plan then references these artifacts so every node receives the same NAR during cutover. Check: each node in the staging inventory has the matching NAR checksum and a signed-off regression report is attached to the change record. Rollback: keep the 1.x NARs available in the artifact store and the previous NiFi 1.x installation ready until the cutover is accepted.
How to test rebuilt NARs before cutover
Testing a rebuilt NAR has to cover more than whether it compiles. Start with compile and unit tests against the NiFi 2 API, then load the packaged NAR on a NiFi 2 instance and confirm every custom processor, controller service and property descriptor appears without errors in the bulletin board and the component list. A NAR that builds cleanly can still fail at load time because of a leftover javax.servlet import or a property descriptor that passes null to defaultValue(), so the load check is the first gate that catches what the compiler does not. Keep the unit tests focused on logic, and add a test for each property descriptor that exercises its validators and default values under the NiFi 2 rules.
The most useful layer is a flow-level regression against the 1.x baseline. Run the same representative input through the old flow on 1.x and the rebuilt flow on NiFi 2, then compare output content, FlowFile attributes and provenance event types and counts for each custom component. Differences in attribute names, routing relationships or event sequences are usually the first sign of a changed default or a removed expression language scope, so record them as defects rather than accepting them as expected. Include the UI check here as well: open each custom Advanced UI at the web application root rather than /configure, and confirm that its configuration saves correctly and its additional details render from additionalDetails.md. Confirm the exact behavior of your own components with the NiFi 2 Developer's Guide and the NiFi migration guidance before you write expectations.
Load tests on representative data come last, using volumes and record shapes taken from production rather than synthetic samples. Measure throughput, error rates and memory use of the rebuilt NAR under the same settings the 1.x flow used. Every run, including the Java 21 runtime version, the NAR build identifier and the NiFi 2 release, must use the same Java 21 runtime as production, because results from a different JDK do not prove anything about the target. Record each test layer's inputs, outputs, pass or fail decisions and open defects in a sign-off record that the component owner and the operations team both approve before cutover. Ask your quote to include this record as a deliverable, and confirm with your own change process which evidence it must contain.
What makes NAR rebuilds take longer
This table compares the factors that change how long a custom NAR rebuild takes for NiFi 2. Read each row as a question to answer about your own extensions before estimating effort. The main takeaway is that the count of components matters less than how deeply each one depends on removed APIs, variable registry expressions and missing tests.
| Driver | Effect on effort | What to check |
|---|---|---|
| Number of custom processors and controller services | Each component needs its imports, descriptors and tests reviewed, so effort grows with the count | Inventory every processor and controller service in your NARs and note which ones your flows use |
| Use of VARIABLE_REGISTRY in expressions | Expressions that rely on the removed scope must be rewritten, and the work spreads into flows and parameter setup | Search property descriptors and expression definitions for the VARIABLE_REGISTRY scope and map each use to an ENVIRONMENT or parameter replacement |
| Custom Advanced UIs | UI assets served from the old /configure path must be moved to the new root path and retested in the browser | Confirm which components ship Advanced UIs and check their paths, scripts and API calls |
| Depth of Servlet or Jetty code | Moving from javax.servlet to jakarta.servlet touches every class that handles HTTP, and Jetty-specific code may need more changes | Find all javax.servlet imports and any direct Jetty references, then confirm which handlers are part of the extension |
| Third-party libraries that must support Java 21 | A library without a Java 21 compatible release can block the build or force a replacement, which adds vendor and design work | Check the version of every bundled dependency and confirm Java 21 support with each library maintainer |
| Missing or outdated source and tests | Without source or tests, changes cannot be verified and behavior changes can go unnoticed, which lengthens validation | Confirm you hold buildable source, the original build configuration and automated tests for each NAR |
| Flows that depend on the components | Every flow using a rebuilt component needs a regression run, and flows with unusual settings take longer to validate | List the process groups and templates that reference each NAR and plan a test run against each one in a non-production cluster |
Questions teams ask about rebuilding NiFi custom NARs
How much does rebuilding custom NiFi NARs cost?
No supplied figure sets this cost, and the quote depends on the written scope. The main cost drivers are how many custom processors, controller services and UI components you have, how many use APIs that changed, how much of the code relies on the removed VARIABLE_REGISTRY scope or null property defaults, and how much testing the flows need. Ask for a quote that separates the code changes, the build and packaging work, the test plan, and any cutover support. Most of this is one-time work, while rebuilding after each future NiFi release is a recurring cost to plan for.
How long does a NAR rebuild take?
Duration depends mainly on the number of extensions, how far they depart from the NiFi 2 API, and how many flows depend on them. Teams with a small set of processors that use standard APIs usually finish code changes faster than teams with large bundles that use the Servlet API, custom UIs or scripted logic. Testing often takes longer than the code changes because each flow must run against realistic data. Ask for a timeline in the written scope that lists the milestones and the internal reviews it depends on.
What does the internal team need to provide for a NAR rebuild?
Plan to provide three things: access to the current source code and build files, representative test data that reflects real record formats and edge cases, and named flow owners who can confirm expected behavior. Source access lets engineers find imports and property descriptors that need changes. Flow owners confirm which processors are used, which properties are set and which outputs matter. Without test data and flow owners, it is hard to show that a rebuilt NAR behaves the same as the original.
Can our own team rebuild the custom NARs without outside help?
Yes, if the team has Java developers who know the NiFi Developer's Guide, can work with Maven builds, and can run the flows in a non-production NiFi 2 environment. The work is usually manageable for a small number of extensions with standard APIs. The risk grows with large bundles, unfamiliar third-party dependencies or many production flows. Decide based on available time, familiarity with the NiFi 2 API changes in the migration guidance, and the cost of a failed cutover.
Can a NAR rebuilt for NiFi 2 run on NiFi 1.x?
Do not plan on it. The NiFi 2 API changes the Servlet imports to jakarta.servlet, removes null defaults in property descriptors, and changes the expression language scope, so a NAR built against the NiFi 2 API is not designed to run on NiFi 1.x. The 1.x line also cannot be maintained further because it depends on Jetty 9.4, Spring Framework 5.3 and AngularJS 1.8, which the project says cannot be upgraded in that line. Keep the original 1.x NARs for the legacy environment and confirm compatibility with the project's documentation for your exact versions.
What happens to a custom component that is only used in a removed component's flow?
The custom NAR may still be valid, but the flow around it may not be. If a custom processor depends on a service such as a removed component, you need to replace or remove that dependency before the NAR can work in NiFi 2. Start by listing every flow that references the custom component and every removed component it connects to. Then decide whether to rebuild the custom code against a replacement, move the logic into a supported processor, or retire the flow. This decision should be made with the flow owners before the rebuild begins.
What should we check after rebuilding a custom NAR?
Check that the NAR loads in a NiFi 2 test instance, that every processor and controller service appears with the expected properties, and that the Markdown additional details render. Then run each flow with the test data and compare outputs, provenance events and error routes against the 1.x baseline. Confirm that expression language uses the ENVIRONMENT scope where it previously used the variable registry, and that any custom Advanced UI opens at the web application root. Record the results so the change can be reviewed.
How to keep a rollback path during NAR cutover
Keep the working 1.x NARs, the 1.x flow files and a full copy of the 1.x configuration untouched until the NiFi 2 cluster has passed regression on your custom processors. Treat the 1.x installation as the fallback, not as a directory you clean up after the first successful run. Store the rebuilt 2.x NARs in a separate extensions directory and do not overwrite the 1.x set in place, so that a bad deployment can be reversed by pointing the node back at the old artifacts. Confirm with your own change records that each custom NAR has a known source revision and a checksum for both the 1.x and 2.x builds.
Rollback is a restore operation, not a configuration switch. NiFi 2 changes the flow configuration file from flow.xml.gz to flow.json.gz, as the migration guidance requires, so a 2.x node that has written its flow cannot simply be started again on 1.x with the old file alone. Before cutover, take a backup of the 1.x flow.xml.gz, the conf directory, the flow repositories and the sensitive properties key, and confirm with the NiFi migration guidance how the 2.x upgrade rewrites the flow. Rehearse the restore on a non-production copy so that the time it takes is known before it is needed.
Record which NAR build runs on which node, and keep that record current during the rollout. A simple inventory that lists each node, the NiFi version, the JDK version and the checksum of every custom NAR in the extensions directory is enough for a regression review and for an incident responder. Compare the inventory against the cluster view after each node restarts, because a single node left on an old NAR can produce results that look like a flow defect. Ask your NAR build pipeline to publish these checksums automatically so that the record is generated, not typed.
How DeployOpen scopes and delivers NAR rebuilds
DeployOpen plans, implements, tests and documents custom NiFi processor and NAR rebuilds inside your own infrastructure, starting from a written scope. The work is agreed before it begins, and the rebuilt extensions are handed over with the test evidence your team needs to run them.
How we scope
- Inventory every custom NAR, its processors, controller services and the NiFi 1.x API calls it uses.
- Record which flows reference each extension and which expression language scopes they depend on.
- Agree the written scope, deliverables and timeline before any code changes start.
How we build
- Move javax.servlet imports to jakarta.servlet and remove null defaultValue() calls from property descriptors.
- Convert additionalDetails.html to additionalDetails.md and move custom Advanced UI paths off /configure.
- Build against the NiFi 2 API on Java 21, replacing any VARIABLE_REGISTRY scope with ENVIRONMENT-based designs.
How we hand over
- Deliver rebuilt NARs with source changes, build instructions and a record of each API change made.
- Provide test results from a non-production NiFi 2 instance, including provenance and flow-level checks.
- Document the rollback path and the deployment steps your team needs to repeat the rebuild.
How we support
- Engagements are fixed-scope, so changes after sign-off are priced through a written change request.
- Ongoing support, upgrades and continuous testing for custom extensions are available as a retainer.
- Ask for the support boundaries, response expectations and retainer terms in the written quote.

