diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/manifest/RuntimeManifestService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/manifest/RuntimeManifestService.java new file mode 100644 index 0000000000..7f021255f9 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/manifest/RuntimeManifestService.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +package org.apache.nifi.manifest; + +import org.apache.nifi.c2.protocol.component.api.RuntimeManifest; + +/** + * Produces a RuntimeManifest for the current NiFi instance. + */ +public interface RuntimeManifestService { + + /** + * @return the RuntimeManifest + */ + RuntimeManifest getManifest(); + +} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/manifest/StandardRuntimeManifestService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/manifest/StandardRuntimeManifestService.java new file mode 100644 index 0000000000..74473a2d05 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/manifest/StandardRuntimeManifestService.java @@ -0,0 +1,111 @@ +/* + * 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. + */ +package org.apache.nifi.manifest; + +import org.apache.nifi.bundle.Bundle; +import org.apache.nifi.bundle.BundleDetails; +import org.apache.nifi.c2.protocol.component.api.BuildInfo; +import org.apache.nifi.c2.protocol.component.api.RuntimeManifest; +import org.apache.nifi.extension.manifest.ExtensionManifest; +import org.apache.nifi.extension.manifest.parser.ExtensionManifestParser; +import org.apache.nifi.nar.ExtensionManager; +import org.apache.nifi.nar.NarClassLoadersHolder; +import org.apache.nifi.runtime.manifest.RuntimeManifestBuilder; +import org.apache.nifi.runtime.manifest.impl.SchedulingDefaultsFactory; +import org.apache.nifi.runtime.manifest.impl.StandardRuntimeManifestBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; +import java.util.Optional; +import java.util.Set; + +public class StandardRuntimeManifestService implements RuntimeManifestService { + + private static final Logger LOGGER = LoggerFactory.getLogger(StandardRuntimeManifestService.class); + + private static final String RUNTIME_MANIFEST_IDENTIFIER = "nifi"; + private static final String RUNTIME_TYPE = "nifi"; + + private final ExtensionManager extensionManager; + private final ExtensionManifestParser extensionManifestParser; + + public StandardRuntimeManifestService(final ExtensionManager extensionManager, final ExtensionManifestParser extensionManifestParser) { + this.extensionManager = extensionManager; + this.extensionManifestParser = extensionManifestParser; + } + + @Override + public RuntimeManifest getManifest() { + final Set allBundles = extensionManager.getAllBundles(); + + final Bundle frameworkBundle = getFrameworkBundle(); + final BundleDetails frameworkDetails = frameworkBundle.getBundleDetails(); + final Date frameworkBuildDate = frameworkDetails.getBuildTimestampDate(); + + final BuildInfo buildInfo = new BuildInfo(); + buildInfo.setVersion(frameworkDetails.getCoordinate().getVersion()); + buildInfo.setRevision(frameworkDetails.getBuildRevision()); + buildInfo.setCompiler(frameworkDetails.getBuildJdk()); + buildInfo.setTimestamp(frameworkBuildDate == null ? null : frameworkBuildDate.getTime()); + + final RuntimeManifestBuilder manifestBuilder = new StandardRuntimeManifestBuilder() + .identifier(RUNTIME_MANIFEST_IDENTIFIER) + .runtimeType(RUNTIME_TYPE) + .version(buildInfo.getVersion()) + .schedulingDefaults(SchedulingDefaultsFactory.getNifiSchedulingDefaults()) + .buildInfo(buildInfo); + + for (final Bundle bundle : allBundles) { + getExtensionManifest(bundle).ifPresent(em -> manifestBuilder.addBundle(em)); + } + + return manifestBuilder.build(); + } + + private Optional getExtensionManifest(final Bundle bundle) { + final BundleDetails bundleDetails = bundle.getBundleDetails(); + final File manifestFile = new File(bundleDetails.getWorkingDirectory(), "META-INF/docs/extension-manifest.xml"); + if (!manifestFile.exists()) { + LOGGER.warn("Unable to find extension manifest for [{}] at [{}]...", bundleDetails.getCoordinate(), manifestFile.getAbsolutePath()); + return Optional.empty(); + } + + try (final InputStream inputStream = new FileInputStream(manifestFile)) { + final ExtensionManifest extensionManifest = extensionManifestParser.parse(inputStream); + // Newer NARs will have these fields populated in extension-manifest.xml, but older NARs will not, so we can + // set the values from the BundleCoordinate which already has the group, artifact id, and version + extensionManifest.setGroupId(bundleDetails.getCoordinate().getGroup()); + extensionManifest.setArtifactId(bundleDetails.getCoordinate().getId()); + extensionManifest.setVersion(bundleDetails.getCoordinate().getVersion()); + return Optional.of(extensionManifest); + } catch (final IOException e) { + LOGGER.error("Unable to load extension manifest for bundle [{}]", bundleDetails.getCoordinate(), e); + return Optional.empty(); + } + } + + // Visible for overriding from tests + Bundle getFrameworkBundle() { + return NarClassLoadersHolder.getInstance().getFrameworkBundle(); + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/nifi-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/nifi-context.xml index 040329ba0c..fe8058e834 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/nifi-context.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/nifi-context.xml @@ -67,6 +67,15 @@ + + + + + + + + + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/manifest/StandardRuntimeManifestServiceTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/manifest/StandardRuntimeManifestServiceTest.java new file mode 100644 index 0000000000..d644f646f9 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/manifest/StandardRuntimeManifestServiceTest.java @@ -0,0 +1,125 @@ +/* + * 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. + */ +package org.apache.nifi.manifest; + +import org.apache.nifi.bundle.Bundle; +import org.apache.nifi.bundle.BundleCoordinate; +import org.apache.nifi.bundle.BundleDetails; +import org.apache.nifi.c2.protocol.component.api.ComponentManifest; +import org.apache.nifi.c2.protocol.component.api.ControllerServiceDefinition; +import org.apache.nifi.c2.protocol.component.api.ProcessorDefinition; +import org.apache.nifi.c2.protocol.component.api.RuntimeManifest; +import org.apache.nifi.extension.manifest.parser.ExtensionManifestParser; +import org.apache.nifi.extension.manifest.parser.jaxb.JAXBExtensionManifestParser; +import org.apache.nifi.nar.ExtensionManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class StandardRuntimeManifestServiceTest { + + private Bundle frameworkBundle; + private Bundle testComponentsBundle; + private ExtensionManager extensionManager; + private ExtensionManifestParser extensionManifestParser; + private RuntimeManifestService runtimeManifestService; + + @BeforeEach + public void setup() { + final BundleDetails frameworkBundleDetails = new BundleDetails.Builder() + .coordinate(new BundleCoordinate("org.apache.nifi", "nifi-framework-nar", "1.16.0")) + .buildJdk("1.8.0") + .buildRevision("revision1") + .buildTimestamp("2022-03-07T08:54:46Z") + .workingDir(new File("src/test/resources/TestRuntimeManifest/nifi-framework-nar")) + .build(); + + frameworkBundle = new Bundle(frameworkBundleDetails, this.getClass().getClassLoader()); + + final BundleDetails testComponentsBundleDetails = new BundleDetails.Builder() + .coordinate(new BundleCoordinate("org.apache.nifi", "nifi-test-components-nar", "1.16.0")) + .buildJdk("1.8.0") + .buildRevision("revision1") + .buildTimestamp("2022-03-07T08:54:46Z") + .workingDir(new File("src/test/resources/TestRuntimeManifest/nifi-test-components-nar")) + .build(); + + testComponentsBundle = new Bundle(testComponentsBundleDetails, this.getClass().getClassLoader()); + + extensionManager = mock(ExtensionManager.class); + extensionManifestParser = new JAXBExtensionManifestParser(); + runtimeManifestService = new TestableRuntimeManifestService(extensionManager, extensionManifestParser, frameworkBundle); + } + + @Test + public void testGetRuntimeManifest() { + when(extensionManager.getAllBundles()).thenReturn(new HashSet<>(Arrays.asList(testComponentsBundle))); + + final RuntimeManifest runtimeManifest = runtimeManifestService.getManifest(); + assertNotNull(runtimeManifest); + assertEquals(frameworkBundle.getBundleDetails().getCoordinate().getVersion(), runtimeManifest.getVersion()); + + assertEquals(frameworkBundle.getBundleDetails().getCoordinate().getVersion(), runtimeManifest.getBuildInfo().getVersion()); + assertEquals(frameworkBundle.getBundleDetails().getBuildRevision(), runtimeManifest.getBuildInfo().getRevision()); + assertEquals(frameworkBundle.getBundleDetails().getBuildJdk(), runtimeManifest.getBuildInfo().getCompiler()); + + final List bundles = runtimeManifest.getBundles(); + assertNotNull(bundles); + assertEquals(1, bundles.size()); + + final org.apache.nifi.c2.protocol.component.api.Bundle testComponentsManifestBundle = bundles.get(0); + assertEquals(testComponentsBundle.getBundleDetails().getCoordinate().getGroup(), testComponentsManifestBundle.getGroup()); + assertEquals(testComponentsBundle.getBundleDetails().getCoordinate().getId(), testComponentsManifestBundle.getArtifact()); + assertEquals(testComponentsBundle.getBundleDetails().getCoordinate().getVersion(), testComponentsManifestBundle.getVersion()); + + final ComponentManifest testComponentsManifest = testComponentsManifestBundle.getComponentManifest(); + assertNotNull(testComponentsManifest); + + final List processorDefinitions = testComponentsManifest.getProcessors(); + assertEquals(3, processorDefinitions.size()); + + final List controllerServiceDefinitions = testComponentsManifest.getControllerServices(); + assertEquals(1, controllerServiceDefinitions.size()); + } + + /** + * Override getFrameworkBundle to provide a mocked Bundle. + */ + private static class TestableRuntimeManifestService extends StandardRuntimeManifestService { + + private Bundle frameworkBundle; + + public TestableRuntimeManifestService(final ExtensionManager extensionManager, final ExtensionManifestParser extensionManifestParser, final Bundle frameworkBundle) { + super(extensionManager, extensionManifestParser); + this.frameworkBundle = frameworkBundle; + } + + @Override + Bundle getFrameworkBundle() { + return frameworkBundle; + } + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/TestRuntimeManifest/nifi-framework-nar/META-INF/docs/extension-manifest.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/TestRuntimeManifest/nifi-framework-nar/META-INF/docs/extension-manifest.xml new file mode 100644 index 0000000000..a67c2d28ec --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/TestRuntimeManifest/nifi-framework-nar/META-INF/docs/extension-manifest.xml @@ -0,0 +1,19 @@ + + + 1.8.0 + + + \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/TestRuntimeManifest/nifi-test-components-nar/META-INF/docs/extension-manifest.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/TestRuntimeManifest/nifi-test-components-nar/META-INF/docs/extension-manifest.xml new file mode 100644 index 0000000000..d2d99a0d0e --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/TestRuntimeManifest/nifi-test-components-nar/META-INF/docs/extension-manifest.xml @@ -0,0 +1,87 @@ + + + 1.8.0 + + + org.apache.nifi.processors.TestProcessor1 + PROCESSOR + Test processor 1. + + test + processor + + true + true + true + true + true + true + true + + 10 secs + 20 secs + DEBUG + + + CRON_DRIVEN + * 1 * * * + 5 + + + + org.apache.nifi.processors.TestProcessor2 + PROCESSOR + Test processor 2. + + test + processor + + + + + write filesystem + Test explanation. + + + + + + org.apache.nifi.processors.TestProcessor3 + PROCESSOR + + + + + + org.apache.nifi.service.TestServiceImpl + CONTROLLER_SERVICE + + Test service. + + test + service + + + + org.apache.nifi.service.TestService + org.apache.nifi + nifi-test-service-api-nar + 1.0.0 + + + + + \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java index 4a34aa6631..a762d8a8a1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java @@ -31,8 +31,6 @@ import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.bundle.Bundle; import org.apache.nifi.bundle.BundleCoordinate; -import org.apache.nifi.bundle.BundleDetails; -import org.apache.nifi.c2.protocol.component.api.BuildInfo; import org.apache.nifi.c2.protocol.component.api.RuntimeManifest; import org.apache.nifi.cluster.protocol.NodeIdentifier; import org.apache.nifi.components.ConfigurableComponent; @@ -64,17 +62,15 @@ import org.apache.nifi.controller.status.analytics.StatusAnalytics; import org.apache.nifi.controller.status.analytics.StatusAnalyticsEngine; import org.apache.nifi.controller.status.history.StatusHistoryRepository; import org.apache.nifi.diagnostics.SystemDiagnostics; -import org.apache.nifi.extension.manifest.ExtensionManifest; -import org.apache.nifi.extension.manifest.parser.ExtensionManifestParser; import org.apache.nifi.flow.VersionedProcessGroup; import org.apache.nifi.flowfile.FlowFilePrioritizer; import org.apache.nifi.flowfile.attributes.CoreAttributes; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.ProcessGroupCounts; import org.apache.nifi.groups.RemoteProcessGroup; +import org.apache.nifi.manifest.RuntimeManifestService; import org.apache.nifi.nar.ExtensionDefinition; import org.apache.nifi.nar.ExtensionManager; -import org.apache.nifi.nar.NarClassLoadersHolder; import org.apache.nifi.processor.Processor; import org.apache.nifi.processor.Relationship; import org.apache.nifi.provenance.ProvenanceEventRecord; @@ -91,9 +87,6 @@ import org.apache.nifi.remote.PublicPort; import org.apache.nifi.remote.RemoteGroupPort; import org.apache.nifi.reporting.BulletinRepository; import org.apache.nifi.reporting.ReportingTask; -import org.apache.nifi.runtime.manifest.RuntimeManifestBuilder; -import org.apache.nifi.runtime.manifest.impl.SchedulingDefaultsFactory; -import org.apache.nifi.runtime.manifest.impl.StandardRuntimeManifestBuilder; import org.apache.nifi.services.FlowService; import org.apache.nifi.util.BundleUtils; import org.apache.nifi.util.FormatUtils; @@ -126,8 +119,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.WebApplicationException; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.Collator; @@ -141,7 +132,6 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.SortedSet; import java.util.TimeZone; @@ -155,9 +145,6 @@ public class ControllerFacade implements Authorizable { private static final Logger logger = LoggerFactory.getLogger(ControllerFacade.class); - private static final String RUNTIME_MANIFEST_IDENTIFIER = "nifi"; - private static final String RUNTIME_TYPE = "nifi"; - // nifi components private FlowController flowController; private FlowService flowService; @@ -168,7 +155,7 @@ public class ControllerFacade implements Authorizable { private DtoFactory dtoFactory; private SearchQueryParser searchQueryParser; private ControllerSearchService controllerSearchService; - private ExtensionManifestParser extensionManifestParser; + private RuntimeManifestService runtimeManifestService; private ProcessGroup getRootGroup() { return flowController.getFlowManager().getRootGroup(); @@ -587,53 +574,7 @@ public class ControllerFacade implements Authorizable { * @return the runtime manifest */ public RuntimeManifest getRuntimeManifest() { - final ExtensionManager extensionManager = getExtensionManager(); - final Set allBundles = extensionManager.getAllBundles(); - - final Bundle frameworkBundle = NarClassLoadersHolder.getInstance().getFrameworkBundle(); - final BundleDetails frameworkDetails = frameworkBundle.getBundleDetails(); - final Date frameworkBuildDate = frameworkDetails.getBuildTimestampDate(); - - final BuildInfo buildInfo = new BuildInfo(); - buildInfo.setVersion(frameworkDetails.getCoordinate().getVersion()); - buildInfo.setRevision(frameworkDetails.getBuildRevision()); - buildInfo.setCompiler(frameworkDetails.getBuildJdk()); - buildInfo.setTimestamp(frameworkBuildDate == null ? null : frameworkBuildDate.getTime()); - - final RuntimeManifestBuilder manifestBuilder = new StandardRuntimeManifestBuilder() - .identifier(RUNTIME_MANIFEST_IDENTIFIER) - .runtimeType(RUNTIME_TYPE) - .version(buildInfo.getVersion()) - .schedulingDefaults(SchedulingDefaultsFactory.getNifiSchedulingDefaults()) - .buildInfo(buildInfo); - - for (final Bundle bundle : allBundles) { - getExtensionManifest(bundle).ifPresent(em -> manifestBuilder.addBundle(em)); - } - - return manifestBuilder.build(); - } - - private Optional getExtensionManifest(final Bundle bundle) { - final BundleDetails bundleDetails = bundle.getBundleDetails(); - final File manifestFile = new File(bundleDetails.getWorkingDirectory(), "META-INF/docs/extension-manifest.xml"); - if (!manifestFile.exists()) { - logger.warn("Unable to find extension manifest for [{}] at [{}]...", bundleDetails.getCoordinate(), manifestFile.getAbsolutePath()); - return Optional.empty(); - } - - try (final InputStream inputStream = new FileInputStream(manifestFile)) { - final ExtensionManifest extensionManifest = extensionManifestParser.parse(inputStream); - // Newer NARs will have these fields populated in extension-manifest.xml, but older NARs will not, so we can - // set the values from the BundleCoordinate which already has the group, artifact id, and version - extensionManifest.setGroupId(bundleDetails.getCoordinate().getGroup()); - extensionManifest.setArtifactId(bundleDetails.getCoordinate().getId()); - extensionManifest.setVersion(bundleDetails.getCoordinate().getVersion()); - return Optional.of(extensionManifest); - } catch (final IOException e) { - logger.error("Unable to load extension manifest for bundle [{}]", bundleDetails.getCoordinate(), e); - return Optional.empty(); - } + return runtimeManifestService.getManifest(); } /** @@ -1760,7 +1701,7 @@ public class ControllerFacade implements Authorizable { this.controllerSearchService = controllerSearchService; } - public void setExtensionManifestParser(ExtensionManifestParser extensionManifestParser) { - this.extensionManifestParser = extensionManifestParser; + public void setRuntimeManifestService(RuntimeManifestService runtimeManifestService) { + this.runtimeManifestService = runtimeManifestService; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml index 6ba34799f2..7b06418377 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml @@ -290,7 +290,6 @@ - @@ -299,7 +298,7 @@ - +