diff --git a/nifi-framework-bundle/nifi-framework-extensions/nifi-py4j-framework-bundle/nifi-python-framework-api/src/main/java/org/apache/nifi/python/processor/PythonProcessorBridge.java b/nifi-framework-bundle/nifi-framework-extensions/nifi-py4j-framework-bundle/nifi-python-framework-api/src/main/java/org/apache/nifi/python/processor/PythonProcessorBridge.java index fbf891e8e0a8..fd992cf61d05 100644 --- a/nifi-framework-bundle/nifi-framework-extensions/nifi-py4j-framework-bundle/nifi-python-framework-api/src/main/java/org/apache/nifi/python/processor/PythonProcessorBridge.java +++ b/nifi-framework-bundle/nifi-framework-extensions/nifi-py4j-framework-bundle/nifi-python-framework-api/src/main/java/org/apache/nifi/python/processor/PythonProcessorBridge.java @@ -36,7 +36,7 @@ public interface PythonProcessorBridge { void replaceController(PythonController controller); /** - * @return the name of the Processor implementation. This will not contain a 'python.' prefix. + * @return the name of the Processor implementation. */ String getProcessorType(); diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java index fb7760f4f821..1cdf10c21e29 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java @@ -263,7 +263,7 @@ public ProcessorNode buildProcessor() { final String componentType; if (PythonBundle.isPythonCoordinate(bundleCoordinate)) { - componentType = type.substring("python.".length()); + componentType = type; } else if (creationSuccessful) { componentType = loggableComponent.getComponent().getClass().getSimpleName(); } else { @@ -896,9 +896,7 @@ private LoggableComponent createLoggablePythonProcessor() { classloaderIsolationKey); Thread.currentThread().setContextClassLoader(detectedClassLoader); - // TODO: This is a hack because there's a bug in the UI that causes it to not load extensions that don't have a `.` in the type. - final String processorType = type.startsWith("python.") ? type.substring("python.".length()) : type; - final Processor processor = pythonBridge.createProcessor(identifier, processorType, bundleCoordinate.getVersion(), true, true); + final Processor processor = pythonBridge.createProcessor(identifier, type, bundleCoordinate.getVersion(), true, true); final ComponentLog componentLog = new SimpleProcessLogger(identifier, processor, new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLog); diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicate.java b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicate.java index 8f2ed91ef1d7..fe6d400c0c6e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicate.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicate.java @@ -50,8 +50,7 @@ private boolean isComponentFromType(final T componentN if (PythonBundle.isPythonCoordinate(componentCoordinate)) { final String componentType = componentNode.getComponentType(); - final String pythonComponentType = "python." + componentType; - return pythonComponentType.equals(extensionDefinitionClassName) && componentCoordinate.equals(extensionDefinitionCoordinate); + return componentType.equals(extensionDefinitionClassName) && componentCoordinate.equals(extensionDefinitionCoordinate); } else if (componentNode.isExtensionMissing()) { return componentClassName.equals(extensionDefinitionClassName) && componentCoordinate.getGroup().equals(extensionDefinitionCoordinate.getGroup()) diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicateTest.java b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicateTest.java index 8c185b8c4a7d..84003cc76f46 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicateTest.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/nar/ComponentNodeDefinitionPredicateTest.java @@ -40,7 +40,6 @@ public class ComponentNodeDefinitionPredicateTest { private static final BundleCoordinate STANDARD_BUNDLE_COORDINATE_V2 = new BundleCoordinate("org.apache.nifi", "my-processors-nar", "2.0.0"); private static final String PYTHON_PROCESSOR_TYPE = "PythonProcessor"; - private static final String FULL_PYTHON_PROCESSOR_TYPE = "python." + PYTHON_PROCESSOR_TYPE; private static final String OTHER_PYTHON_PROCESSOR_TYPE = "OtherPythonProcessor"; private static final BundleCoordinate PYTHON_BUNDLE_COORDINATE = new BundleCoordinate(PythonBundle.GROUP_ID, PythonBundle.ARTIFACT_ID, "0.0.1"); @@ -66,7 +65,7 @@ public void setup() { when(pythonBundle.getBundleDetails()).thenReturn(pythonBundleDetails); pythonProcessorDefinition = mock(ExtensionDefinition.class); - when(pythonProcessorDefinition.getImplementationClassName()).thenReturn(FULL_PYTHON_PROCESSOR_TYPE); + when(pythonProcessorDefinition.getImplementationClassName()).thenReturn(PYTHON_PROCESSOR_TYPE); when(pythonProcessorDefinition.getBundle()).thenReturn(pythonBundle); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java b/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java index ba208c5a61ba..f76f8d208412 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java @@ -87,7 +87,6 @@ public class StandardExtensionDiscoveringManager implements ExtensionDiscoveringManager { private static final Logger logger = LoggerFactory.getLogger(StandardExtensionDiscoveringManager.class); - private static final String PYTHON_TYPE_PREFIX = "python."; // Maps a service definition (interface) to those classes that implement the interface private final Map, Set> definitionMap = new HashMap<>(); @@ -234,8 +233,7 @@ private void loadPythonExtensions(final Bundle pythonBundle, final long startTim final BundleDetails bundleDetails = createBundleDetailsWithOverriddenVersion(pythonBundle.getBundleDetails(), details.getProcessorVersion()); final Bundle bundle = new Bundle(bundleDetails, pythonBundle.getClassLoader()); - // TODO: This is a workaround because the UI has a bug that causes it not to work properly if the type doesn't have a '.' in it - final String className = PYTHON_TYPE_PREFIX + details.getProcessorType(); + final String className = details.getProcessorType(); final ExtensionDefinition extensionDefinition = new ExtensionDefinition.Builder() .implementationClassName(className) .runtime(ExtensionRuntime.PYTHON) @@ -274,8 +272,7 @@ private void loadPythonExtensions(final Bundle pythonBundle, final long startTim @Override public synchronized PythonProcessorDetails getPythonProcessorDetails(final String processorType, final String version) { - final String canonicalProcessorType = stripPythonTypePrefix(processorType); - final List detailsList = this.pythonProcessorDetails.get(canonicalProcessorType); + final List detailsList = this.pythonProcessorDetails.get(processorType); if (detailsList == null) { return null; } @@ -785,19 +782,18 @@ private void removeExtensionDefinition(final ExtensionDefinition extensionDefini final String tempComponentKey = getClassBundleKey(removeExtensionClassName, extensionDefinitionCoordinate); final ConfigurableComponent removedTempComponent = tempComponentLookup.remove(tempComponentKey); - if (removeExtensionClassName.startsWith(PYTHON_TYPE_PREFIX)) { - final String strippedClassName = stripPythonTypePrefix(removeExtensionClassName); - logger.debug("Removing Python processor type {} - {}", strippedClassName, extensionDefinition.getVersion()); + if (PythonBundle.isPythonCoordinate(extensionDefinitionCoordinate)) { + logger.debug("Removing Python processor type {} - {}", removeExtensionClassName, extensionDefinition.getVersion()); - final List processorDetailsList = Optional.ofNullable(pythonProcessorDetails.get(strippedClassName)).orElse(Collections.emptyList()); - processorDetailsList.removeIf(processorDetails -> processorDetails.getProcessorType().equals(strippedClassName) + final List processorDetailsList = Optional.ofNullable(pythonProcessorDetails.get(removeExtensionClassName)).orElse(Collections.emptyList()); + processorDetailsList.removeIf(processorDetails -> processorDetails.getProcessorType().equals(removeExtensionClassName) && processorDetails.getProcessorVersion().equals(extensionDefinition.getVersion())); if (removedTempComponent != null) { - final String pythonTempComponentId = getPythonTempComponentId(strippedClassName); - pythonBridge.onProcessorRemoved(pythonTempComponentId, strippedClassName, extensionDefinition.getVersion()); + final String pythonTempComponentId = getPythonTempComponentId(removeExtensionClassName); + pythonBridge.onProcessorRemoved(pythonTempComponentId, removeExtensionClassName, extensionDefinition.getVersion()); } - pythonBridge.removeProcessorType(strippedClassName, extensionDefinition.getVersion()); + pythonBridge.removeProcessorType(removeExtensionClassName, extensionDefinition.getVersion()); } } @@ -861,11 +857,8 @@ public synchronized ConfigurableComponent getTempComponent(final String classTyp try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(bundleClassLoader)) { final ConfigurableComponent tempComponent; if (PythonBundle.isPythonCoordinate(bundle.getBundleDetails().getCoordinate())) { - // TODO: This is a workaround due to bug in UI. Fix bug in UI. - final String type = stripPythonTypePrefix(classType); - - final String procId = getPythonTempComponentId(type); - tempComponent = pythonBridge.createProcessor(procId, type, bundleCoordinate.getVersion(), false, false); + final String procId = getPythonTempComponentId(classType); + tempComponent = pythonBridge.createProcessor(procId, classType, bundleCoordinate.getVersion(), false, false); } else { final Class componentClass = Class.forName(classType, true, bundleClassLoader); tempComponent = (ConfigurableComponent) componentClass.getDeclaredConstructor().newInstance(); @@ -890,17 +883,6 @@ private static String getPythonTempComponentId(final String type) { return "temp-component-" + type; } - private static String stripPythonTypePrefix(final String value) { - if (value == null) { - return null; - } - if (value.startsWith(PYTHON_TYPE_PREFIX)) { - return value.substring(PYTHON_TYPE_PREFIX.length()); - } - - return value; - } - private static String getClassBundleKey(final String classType, final BundleCoordinate bundleCoordinate) { return classType + "_" + bundleCoordinate.getCoordinate(); } diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/connection/prioritizers/prioritizers.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/connection/prioritizers/prioritizers.component.ts index 2c58b812f745..fc64d7e298df 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/connection/prioritizers/prioritizers.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/connection/prioritizers/prioritizers.component.ts @@ -125,7 +125,7 @@ export class Prioritizers implements ControlValueAccessor { } getPrioritizerLabel(entity: DocumentedType): string { - return this.nifiCommon.substringAfterLast(entity.type, '.'); + return this.nifiCommon.getComponentTypeLabel(entity.type); } hasDescription(entity: DocumentedType): boolean { diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/registry-clients/create-registry-client/create-registry-client.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/registry-clients/create-registry-client/create-registry-client.component.ts index 08e91d2a7e0c..46390617bba0 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/registry-clients/create-registry-client/create-registry-client.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/registry-clients/create-registry-client/create-registry-client.component.ts @@ -80,7 +80,7 @@ export class CreateRegistryClient extends CloseOnEscapeDialog { } formatType(option: DocumentedType): string { - return this.nifiCommon.substringAfterLast(option.type, '.'); + return this.nifiCommon.getComponentTypeLabel(option.type); } createRegistryClientClicked() { diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/change-component-version-dialog/change-component-version-dialog.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/change-component-version-dialog/change-component-version-dialog.ts index 6b74153c3003..aa2e2535ee71 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/change-component-version-dialog/change-component-version-dialog.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/change-component-version-dialog/change-component-version-dialog.ts @@ -77,7 +77,7 @@ export class ChangeComponentVersionDialog extends CloseOnEscapeDialog { } getName(selected: DocumentedType | null): string { - return this.nifiCommon.substringAfterLast(selected?.type || '', '.'); + return this.nifiCommon.getComponentTypeLabel(selected?.type || ''); } protected readonly TextTip = TextTip; diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts index d4549bfae5f3..1cf6910f5669 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts @@ -82,7 +82,7 @@ export class ExtensionCreation extends CloseOnEscapeDialog { formatType(documentedType: DocumentedType): string { if (documentedType) { - return this.nifiCommon.substringAfterLast(documentedType.type, '.'); + return this.nifiCommon.getComponentTypeLabel(documentedType.type); } return ''; } diff --git a/nifi-frontend/src/main/frontend/libs/shared/src/services/nifi-common.service.ts b/nifi-frontend/src/main/frontend/libs/shared/src/services/nifi-common.service.ts index 7813e97f2799..4c36cea5504f 100644 --- a/nifi-frontend/src/main/frontend/libs/shared/src/services/nifi-common.service.ts +++ b/nifi-frontend/src/main/frontend/libs/shared/src/services/nifi-common.service.ts @@ -40,6 +40,8 @@ export class NiFiCommon { public static readonly BYTES_IN_GIGABYTE: number = 1073741824; public static readonly BYTES_IN_TERABYTE: number = 1099511627776; + public static readonly PACKAGE_SEPARATOR: string = '.'; + private policyTypeListing: SelectOption[] = [ { text: 'view the user interface', @@ -173,6 +175,22 @@ export class NiFiCommon { return result; } + /** + * Get the label for a Component Type using the simple name from a qualified class + * + * @argument {string} componentType Qualified class name or simple name + */ + public getComponentTypeLabel(componentType: string): string { + let label = componentType; + + const separatorIndex = componentType.indexOf(NiFiCommon.PACKAGE_SEPARATOR); + if (separatorIndex >= 0) { + label = this.substringAfterLast(componentType, NiFiCommon.PACKAGE_SEPARATOR); + } + + return label; + } + /** * Determines whether the specified string is blank (or null or undefined). * @@ -268,7 +286,7 @@ export class NiFiCommon { * @param dataContext component datum */ public formatClassName(dataContext: any): string { - return this.substringAfterLast(dataContext.type, '.'); + return this.getComponentTypeLabel(dataContext.type); } /** diff --git a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/NiFiClientUtil.java b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/NiFiClientUtil.java index c8dbcbebf522..c9cd2ae701da 100644 --- a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/NiFiClientUtil.java +++ b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/NiFiClientUtil.java @@ -177,7 +177,7 @@ public void stopProcessor(final ProcessorEntity currentEntity) throws NiFiClient } public ProcessorEntity createPythonProcessor(final String typeName) throws NiFiClientException, IOException { - return createProcessor( "python." + typeName, NiFiSystemIT.NIFI_GROUP_ID, NiFiSystemIT.TEST_PYTHON_EXTENSIONS_ARTIFACT_ID, "0.0.1-SNAPSHOT"); + return createProcessor(typeName, NiFiSystemIT.NIFI_GROUP_ID, NiFiSystemIT.TEST_PYTHON_EXTENSIONS_ARTIFACT_ID, "0.0.1-SNAPSHOT"); } public ProcessorEntity createProcessor(final String simpleTypeName) throws NiFiClientException, IOException { diff --git a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/nar/NarUploadPythonIT.java b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/nar/NarUploadPythonIT.java index 387c4baafa4e..a5ce3af00d78 100644 --- a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/nar/NarUploadPythonIT.java +++ b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/nar/NarUploadPythonIT.java @@ -47,7 +47,7 @@ public class NarUploadPythonIT extends NiFiSystemIT { private static final Logger logger = LoggerFactory.getLogger(NarUploadPythonIT.class); private static final String PYTHON_TEXT_EXTENSIONS_NAR_ID = "nifi-python-test-extensions-nar"; - private static final String PYTHON_WRITE_BECH_32_CHARSET = "python.WriteBech32Charset"; + private static final String PYTHON_WRITE_BECH_32_CHARSET = "WriteBech32Charset"; private static final String EXPECTED_FLOW_FILE_CONTENT = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; @Override