Java Code Examples for org.apache.nifi.controller.service.ControllerServiceNode#getControllerServiceImplementation()

The following examples show how to use org.apache.nifi.controller.service.ControllerServiceNode#getControllerServiceImplementation() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: FlowController.java    From localization_nifi with Apache License 2.0 6 votes vote down vote up
private void notifyComponentsConfigurationRestored() {
    for (final ProcessorNode procNode : getGroup(getRootGroupId()).findAllProcessors()) {
        final Processor processor = procNode.getProcessor();
        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, processor);
        }
    }

    for (final ControllerServiceNode serviceNode : getAllControllerServices()) {
        final ControllerService service = serviceNode.getControllerServiceImplementation();

        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(service.getClass(), service.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, service);
        }
    }

    for (final ReportingTaskNode taskNode : getAllReportingTasks()) {
        final ReportingTask task = taskNode.getReportingTask();

        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(task.getClass(), task.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, task);
        }
    }
}
 
Example 2
Source File: FlowController.java    From localization_nifi with Apache License 2.0 6 votes vote down vote up
@Override
public ControllerServiceNode createControllerService(final String type, final String id, final boolean firstTimeAdded) {
    final ControllerServiceNode serviceNode = controllerServiceProvider.createControllerService(type, id, firstTimeAdded);

    // Register log observer to provide bulletins when reporting task logs anything at WARN level or above
    final LogRepository logRepository = LogRepositoryFactory.getRepository(id);
    logRepository.addObserver(StandardProcessorNode.BULLETIN_OBSERVER_ID, LogLevel.WARN,
            new ControllerServiceLogObserver(getBulletinRepository(), serviceNode));

    if (firstTimeAdded) {
        final ControllerService service = serviceNode.getControllerServiceImplementation();

        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(service.getClass(), service.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, service);
        }
    }

    return serviceNode;
}
 
Example 3
Source File: TestStandardProcessScheduler.java    From localization_nifi with Apache License 2.0 6 votes vote down vote up
/**
 * Validates that service that is infinitely blocking in @OnEnabled can
 * still have DISABLE operation initiated. The service itself will be set to
 * DISABLING state at which point UI and all will know that such service can
 * not be transitioned any more into any other state until it finishes
 * enabling (which will never happen in our case thus should be addressed by
 * user). However, regardless of user's mistake NiFi will remain
 * functioning.
 */
@Test
public void validateNeverEnablingServiceCanStillBeDisabled() throws Exception {
    final ProcessScheduler scheduler = createScheduler();
    final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(controller, scheduler, null, stateMgrProvider, variableRegistry, nifiProperties);
    final ControllerServiceNode serviceNode = provider.createControllerService(LongEnablingService.class.getName(),
            "1", false);
    final LongEnablingService ts = (LongEnablingService) serviceNode.getControllerServiceImplementation();
    ts.setLimit(Long.MAX_VALUE);
    scheduler.enableControllerService(serviceNode);
    Thread.sleep(100);
    assertTrue(serviceNode.isActive());
    assertEquals(1, ts.enableInvocationCount());

    Thread.sleep(1000);
    scheduler.disableControllerService(serviceNode);
    assertFalse(serviceNode.isActive());
    assertEquals(ControllerServiceState.DISABLING, serviceNode.getState());
    assertEquals(0, ts.disableInvocationCount());
}
 
Example 4
Source File: TestStandardProcessScheduler.java    From localization_nifi with Apache License 2.0 6 votes vote down vote up
/**
 * Validates that the service that is currently in ENABLING state can be
 * disabled and that its @OnDisabled operation will be invoked as soon as
 *
 * @OnEnable finishes.
 */
@Test
public void validateLongEnablingServiceCanStillBeDisabled() throws Exception {
    final ProcessScheduler scheduler = createScheduler();
    final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(controller, scheduler, null, stateMgrProvider, variableRegistry, nifiProperties);
    final ControllerServiceNode serviceNode = provider.createControllerService(LongEnablingService.class.getName(),
            "1", false);
    final LongEnablingService ts = (LongEnablingService) serviceNode.getControllerServiceImplementation();
    ts.setLimit(3000);
    scheduler.enableControllerService(serviceNode);
    Thread.sleep(2000);
    assertTrue(serviceNode.isActive());
    assertEquals(1, ts.enableInvocationCount());

    Thread.sleep(500);
    scheduler.disableControllerService(serviceNode);
    assertFalse(serviceNode.isActive());
    assertEquals(ControllerServiceState.DISABLING, serviceNode.getState());
    assertEquals(0, ts.disableInvocationCount());
    // wait a bit. . . Enabling will finish and @OnDisabled will be invoked
    // automatically
    Thread.sleep(4000);
    assertEquals(ControllerServiceState.DISABLED, serviceNode.getState());
    assertEquals(1, ts.disableInvocationCount());
}
 
Example 5
Source File: TestFlowController.java    From localization_nifi with Apache License 2.0 6 votes vote down vote up
@Test
public void testCreateMissingControllerService() throws ProcessorInstantiationException {
    final ControllerServiceNode serviceNode = controller.createControllerService("org.apache.nifi.NonExistingControllerService", "1234-Controller-Service", false);
    assertNotNull(serviceNode);
    assertEquals("org.apache.nifi.NonExistingControllerService", serviceNode.getCanonicalClassName());
    assertEquals("(Missing) NonExistingControllerService", serviceNode.getComponentType());

    final ControllerService service = serviceNode.getControllerServiceImplementation();
    final PropertyDescriptor descriptor = service.getPropertyDescriptor("my descriptor");
    assertNotNull(descriptor);
    assertEquals("my descriptor", descriptor.getName());
    assertTrue(descriptor.isRequired());
    assertTrue(descriptor.isSensitive());
    assertEquals("GhostControllerService[id=1234-Controller-Service, type=org.apache.nifi.NonExistingControllerService]", service.toString());
    service.hashCode(); // just make sure that an Exception is not thrown
    assertTrue(service.equals(service));
    assertFalse(service.equals(serviceNode));
}
 
Example 6
Source File: FlowController.java    From nifi with Apache License 2.0 6 votes vote down vote up
private void notifyComponentsConfigurationRestored() {
    for (final ProcessorNode procNode : flowManager.getRootGroup().findAllProcessors()) {
        final Processor processor = procNode.getProcessor();
        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(extensionManager, processor.getClass(), processor.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, processor);
        }
    }

    for (final ControllerServiceNode serviceNode : flowManager.getAllControllerServices()) {
        final ControllerService service = serviceNode.getControllerServiceImplementation();

        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(extensionManager, service.getClass(), service.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, service);
        }
    }

    for (final ReportingTaskNode taskNode : getAllReportingTasks()) {
        final ReportingTask task = taskNode.getReportingTask();

        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(extensionManager, task.getClass(), task.getIdentifier())) {
            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, task);
        }
    }
}
 
Example 7
Source File: TestStandardProcessScheduler.java    From nifi with Apache License 2.0 6 votes vote down vote up
/**
 * Validates that service that is infinitely blocking in @OnEnabled can
 * still have DISABLE operation initiated. The service itself will be set to
 * DISABLING state at which point UI and all will know that such service can
 * not be transitioned any more into any other state until it finishes
 * enabling (which will never happen in our case thus should be addressed by
 * user). However, regardless of user's mistake NiFi will remain
 * functioning.
 */
@Test
public void validateNeverEnablingServiceCanStillBeDisabled() throws Exception {
    final StandardProcessScheduler scheduler = createScheduler();

    final ControllerServiceNode serviceNode = flowManager.createControllerService(LongEnablingService.class.getName(),
            "1", systemBundle.getBundleDetails().getCoordinate(), null, false, true);

    final LongEnablingService ts = (LongEnablingService) serviceNode.getControllerServiceImplementation();
    ts.setLimit(Long.MAX_VALUE);

    serviceNode.performValidation();
    scheduler.enableControllerService(serviceNode);

    assertTrue(serviceNode.isActive());
    final long maxTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(10);
    while (ts.enableInvocationCount() != 1 && System.nanoTime() <= maxTime) {
        Thread.sleep(1L);
    }
    assertEquals(1, ts.enableInvocationCount());

    scheduler.disableControllerService(serviceNode);
    assertFalse(serviceNode.isActive());
    assertEquals(ControllerServiceState.DISABLING, serviceNode.getState());
    assertEquals(0, ts.disableInvocationCount());
}
 
Example 8
Source File: TestFlowController.java    From nifi with Apache License 2.0 6 votes vote down vote up
@Test
public void testCreateMissingControllerService() throws ProcessorInstantiationException {
    final ControllerServiceNode serviceNode = controller.getFlowManager().createControllerService("org.apache.nifi.NonExistingControllerService", "1234-Controller-Service",
            systemBundle.getBundleDetails().getCoordinate(), null, false, true);
    assertNotNull(serviceNode);
    assertEquals("org.apache.nifi.NonExistingControllerService", serviceNode.getCanonicalClassName());
    assertEquals("(Missing) NonExistingControllerService", serviceNode.getComponentType());

    final ControllerService service = serviceNode.getControllerServiceImplementation();
    final PropertyDescriptor descriptor = service.getPropertyDescriptor("my descriptor");
    assertNotNull(descriptor);
    assertEquals("my descriptor", descriptor.getName());
    assertTrue(descriptor.isRequired());
    assertTrue(descriptor.isSensitive());
    assertEquals("GhostControllerService[id=1234-Controller-Service, type=org.apache.nifi.NonExistingControllerService]", service.toString());
    service.hashCode(); // just make sure that an Exception is not thrown
    assertTrue(service.equals(service));
    assertFalse(service.equals(serviceNode));
}
 
Example 9
Source File: TestStandardProcessScheduler.java    From localization_nifi with Apache License 2.0 5 votes vote down vote up
/**
 * Validates the atomic nature of ControllerServiceNode.enable() method
 * which must only trigger @OnEnabled once, regardless of how many threads
 * may have a reference to the underlying ProcessScheduler and
 * ControllerServiceNode.
 */
@Test
public void validateServiceEnablementLogicHappensOnlyOnce() throws Exception {
    final ProcessScheduler scheduler = createScheduler();
    final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(controller, scheduler, null, stateMgrProvider, variableRegistry, nifiProperties);
    final ControllerServiceNode serviceNode = provider.createControllerService(SimpleTestService.class.getName(),
            "1", false);
    assertFalse(serviceNode.isActive());
    final SimpleTestService ts = (SimpleTestService) serviceNode.getControllerServiceImplementation();
    final ExecutorService executor = Executors.newCachedThreadPool();

    final AtomicBoolean asyncFailed = new AtomicBoolean();
    for (int i = 0; i < 1000; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    scheduler.enableControllerService(serviceNode);
                    assertTrue(serviceNode.isActive());
                } catch (final Exception e) {
                    e.printStackTrace();
                    asyncFailed.set(true);
                }
            }
        });
    }
    // need to sleep a while since we are emulating async invocations on
    // method that is also internally async
    Thread.sleep(500);
    executor.shutdown();
    assertFalse(asyncFailed.get());
    assertEquals(1, ts.enableInvocationCount());
}
 
Example 10
Source File: TestStandardProcessScheduler.java    From localization_nifi with Apache License 2.0 5 votes vote down vote up
/**
 * Validates the atomic nature of ControllerServiceNode.disable(..) method
 * which must never trigger @OnDisabled, regardless of how many threads may
 * have a reference to the underlying ProcessScheduler and
 * ControllerServiceNode.
 */
@Test
public void validateDisabledServiceCantBeDisabled() throws Exception {
    final ProcessScheduler scheduler = createScheduler();
    final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(controller, scheduler, null, stateMgrProvider, variableRegistry, nifiProperties);
    final ControllerServiceNode serviceNode = provider.createControllerService(SimpleTestService.class.getName(),
            "1", false);
    final SimpleTestService ts = (SimpleTestService) serviceNode.getControllerServiceImplementation();
    final ExecutorService executor = Executors.newCachedThreadPool();

    final AtomicBoolean asyncFailed = new AtomicBoolean();
    for (int i = 0; i < 1000; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    scheduler.disableControllerService(serviceNode);
                    assertFalse(serviceNode.isActive());
                } catch (final Exception e) {
                    e.printStackTrace();
                    asyncFailed.set(true);
                }
            }
        });
    }
    // need to sleep a while since we are emulating async invocations on
    // method that is also internally async
    Thread.sleep(500);
    executor.shutdown();
    assertFalse(asyncFailed.get());
    assertEquals(0, ts.disableInvocationCount());
}
 
Example 11
Source File: TestStandardProcessScheduler.java    From localization_nifi with Apache License 2.0 5 votes vote down vote up
/**
 * Validates the atomic nature of ControllerServiceNode.disable() method
 * which must only trigger @OnDisabled once, regardless of how many threads
 * may have a reference to the underlying ProcessScheduler and
 * ControllerServiceNode.
 */
@Test
public void validateEnabledServiceCanOnlyBeDisabledOnce() throws Exception {
    final ProcessScheduler scheduler = createScheduler();
    final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(controller, scheduler, null, stateMgrProvider, variableRegistry, nifiProperties);
    final ControllerServiceNode serviceNode = provider.createControllerService(SimpleTestService.class.getName(),
            "1", false);
    final SimpleTestService ts = (SimpleTestService) serviceNode.getControllerServiceImplementation();
    scheduler.enableControllerService(serviceNode);
    assertTrue(serviceNode.isActive());
    final ExecutorService executor = Executors.newCachedThreadPool();

    final AtomicBoolean asyncFailed = new AtomicBoolean();
    for (int i = 0; i < 1000; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    scheduler.disableControllerService(serviceNode);
                    assertFalse(serviceNode.isActive());
                } catch (final Exception e) {
                    e.printStackTrace();
                    asyncFailed.set(true);
                }
            }
        });
    }
    // need to sleep a while since we are emulating async invocations on
    // method that is also internally async
    Thread.sleep(500);
    executor.shutdown();
    assertFalse(asyncFailed.get());
    assertEquals(1, ts.disableInvocationCount());
}
 
Example 12
Source File: TestStandardProcessScheduler.java    From nifi with Apache License 2.0 5 votes vote down vote up
/**
 * Validates the atomic nature of ControllerServiceNode.enable() method
 * which must only trigger @OnEnabled once, regardless of how many threads
 * may have a reference to the underlying ProcessScheduler and
 * ControllerServiceNode.
 */
@Test
public void validateServiceEnablementLogicHappensOnlyOnce() throws Exception {
    final StandardProcessScheduler scheduler = createScheduler();

    final ControllerServiceNode serviceNode = flowManager.createControllerService(SimpleTestService.class.getName(),
            "1", systemBundle.getBundleDetails().getCoordinate(), null, false, true);

    serviceNode.performValidation();

    assertFalse(serviceNode.isActive());
    final SimpleTestService ts = (SimpleTestService) serviceNode.getControllerServiceImplementation();
    final ExecutorService executor = Executors.newCachedThreadPool();

    final AtomicBoolean asyncFailed = new AtomicBoolean();
    for (int i = 0; i < 1000; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    scheduler.enableControllerService(serviceNode).get();
                    assertTrue(serviceNode.isActive());
                } catch (final Exception e) {
                    e.printStackTrace();
                    asyncFailed.set(true);
                }
            }
        });
    }

    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.SECONDS);

    assertFalse(asyncFailed.get());
    assertEquals(1, ts.enableInvocationCount());
}
 
Example 13
Source File: TestStandardProcessScheduler.java    From nifi with Apache License 2.0 5 votes vote down vote up
/**
 * Validates the atomic nature of ControllerServiceNode.disable(..) method
 * which must never trigger @OnDisabled, regardless of how many threads may
 * have a reference to the underlying ProcessScheduler and
 * ControllerServiceNode.
 */
@Test
public void validateDisabledServiceCantBeDisabled() throws Exception {
    final StandardProcessScheduler scheduler = createScheduler();

    final ControllerServiceNode serviceNode = flowManager.createControllerService(SimpleTestService.class.getName(),
            "1", systemBundle.getBundleDetails().getCoordinate(), null, false, true);
    final SimpleTestService ts = (SimpleTestService) serviceNode.getControllerServiceImplementation();
    final ExecutorService executor = Executors.newCachedThreadPool();

    final AtomicBoolean asyncFailed = new AtomicBoolean();
    for (int i = 0; i < 1000; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    scheduler.disableControllerService(serviceNode);
                    assertFalse(serviceNode.isActive());
                } catch (final Exception e) {
                    e.printStackTrace();
                    asyncFailed.set(true);
                }
            }
        });
    }

    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.SECONDS);
    assertFalse(asyncFailed.get());
    assertEquals(0, ts.disableInvocationCount());
}
 
Example 14
Source File: TestStandardProcessScheduler.java    From nifi with Apache License 2.0 5 votes vote down vote up
/**
 * Validates the atomic nature of ControllerServiceNode.disable() method
 * which must only trigger @OnDisabled once, regardless of how many threads
 * may have a reference to the underlying ProcessScheduler and
 * ControllerServiceNode.
 */
@Test
public void validateEnabledServiceCanOnlyBeDisabledOnce() throws Exception {
    final StandardProcessScheduler scheduler = createScheduler();
    final ControllerServiceNode serviceNode = flowManager.createControllerService(SimpleTestService.class.getName(),
            "1", systemBundle.getBundleDetails().getCoordinate(), null, false, true);

    assertSame(ValidationStatus.VALID, serviceNode.performValidation());

    final SimpleTestService ts = (SimpleTestService) serviceNode.getControllerServiceImplementation();
    scheduler.enableControllerService(serviceNode).get();
    assertTrue(serviceNode.isActive());
    final ExecutorService executor = Executors.newCachedThreadPool();

    final AtomicBoolean asyncFailed = new AtomicBoolean();
    for (int i = 0; i < 1000; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    scheduler.disableControllerService(serviceNode);
                    assertFalse(serviceNode.isActive());
                } catch (final Exception e) {
                    e.printStackTrace();
                    asyncFailed.set(true);
                }
            }
        });
    }
    // need to sleep a while since we are emulating async invocations on
    // method that is also internally async
    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.SECONDS); // change to seconds.
    assertFalse(asyncFailed.get());
    assertEquals(1, ts.disableInvocationCount());
}
 
Example 15
Source File: StandardFlowManager.java    From nifi with Apache License 2.0 4 votes vote down vote up
public ControllerServiceNode createControllerService(final String type, final String id, final BundleCoordinate bundleCoordinate, final Set<URL> additionalUrls, final boolean firstTimeAdded,
                                                     final boolean registerLogObserver) {
    // make sure the first reference to LogRepository happens outside of a NarCloseable so that we use the framework's ClassLoader
    final LogRepository logRepository = LogRepositoryFactory.getRepository(id);
    final ExtensionManager extensionManager = flowController.getExtensionManager();
    final ControllerServiceProvider controllerServiceProvider = flowController.getControllerServiceProvider();

    final ControllerServiceNode serviceNode = new ExtensionBuilder()
        .identifier(id)
        .type(type)
        .bundleCoordinate(bundleCoordinate)
        .controllerServiceProvider(flowController.getControllerServiceProvider())
        .processScheduler(processScheduler)
        .nodeTypeProvider(flowController)
        .validationTrigger(flowController.getValidationTrigger())
        .reloadComponent(flowController.getReloadComponent())
        .variableRegistry(flowController.getVariableRegistry())
        .addClasspathUrls(additionalUrls)
        .kerberosConfig(flowController.createKerberosConfig(nifiProperties))
        .stateManagerProvider(flowController.getStateManagerProvider())
        .extensionManager(extensionManager)
        .buildControllerService();

    LogRepositoryFactory.getRepository(serviceNode.getIdentifier()).setLogger(serviceNode.getLogger());
    if (registerLogObserver) {
        // Register log observer to provide bulletins when reporting task logs anything at WARN level or above
        logRepository.addObserver(StandardProcessorNode.BULLETIN_OBSERVER_ID, LogLevel.WARN, new ControllerServiceLogObserver(bulletinRepository, serviceNode));
    }

    if (firstTimeAdded) {
        final ControllerService service = serviceNode.getControllerServiceImplementation();

        if (flowController.isInitialized()) {
            try (final NarCloseable nc = NarCloseable.withComponentNarLoader(extensionManager, service.getClass(), service.getIdentifier())) {
                ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnConfigurationRestored.class, service);
            }
        }

        final ControllerService serviceImpl = serviceNode.getControllerServiceImplementation();
        try (final NarCloseable x = NarCloseable.withComponentNarLoader(extensionManager, serviceImpl.getClass(), serviceImpl.getIdentifier())) {
            ReflectionUtils.invokeMethodsWithAnnotation(OnAdded.class, serviceImpl);
        } catch (final Exception e) {
            throw new ComponentLifeCycleException("Failed to invoke On-Added Lifecycle methods of " + serviceImpl, e);
        }
    }

    controllerServiceProvider.onControllerServiceAdded(serviceNode);

    return serviceNode;
}
 
Example 16
Source File: StandardReloadComponent.java    From nifi with Apache License 2.0 4 votes vote down vote up
@Override
public void reload(final ControllerServiceNode existingNode, final String newType, final BundleCoordinate bundleCoordinate, final Set<URL> additionalUrls)
    throws ControllerServiceInstantiationException {
    if (existingNode == null) {
        throw new IllegalStateException("Existing ControllerServiceNode cannot be null");
    }

    final String id = existingNode.getIdentifier();

    // ghost components will have a null logger
    if (existingNode.getLogger() != null) {
        existingNode.getLogger().debug("Reloading component {} to type {} from bundle {}", new Object[]{id, newType, bundleCoordinate});
    }

    final ExtensionManager extensionManager = flowController.getExtensionManager();

    // createControllerService will create a new instance class loader for the same id so
    // save the instance class loader to use it for calling OnRemoved on the existing service
    final ClassLoader existingInstanceClassLoader = extensionManager.getInstanceClassLoader(id);

    // create a new node with firstTimeAdded as true so lifecycle methods get called
    // attempt the creation to make sure it works before firing the OnRemoved methods below
    final ControllerServiceNode newNode = flowController.getFlowManager().createControllerService(newType, id, bundleCoordinate, additionalUrls, true, false);

    // call OnRemoved for the existing service using the previous instance class loader
    try (final NarCloseable x = NarCloseable.withComponentNarLoader(existingInstanceClassLoader)) {
        final ConfigurationContext configurationContext = new StandardConfigurationContext(existingNode, flowController.getControllerServiceProvider(),
            null, flowController.getVariableRegistry());

        ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnRemoved.class, existingNode.getControllerServiceImplementation(), configurationContext);
    } finally {
        extensionManager.closeURLClassLoader(id, existingInstanceClassLoader);
    }

    // take the invocation handler that was created for new proxy and is set to look at the new node,
    // and set it to look at the existing node
    final ControllerServiceInvocationHandler invocationHandler = newNode.getInvocationHandler();
    invocationHandler.setServiceNode(existingNode);

    // create LoggableComponents for the proxy and implementation
    final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getControllerServiceImplementation());
    final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger);
    LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger);

    final LoggableComponent<ControllerService> loggableProxy = new LoggableComponent<>(newNode.getProxiedControllerService(), bundleCoordinate, terminationAwareLogger);
    final LoggableComponent<ControllerService> loggableImplementation = new LoggableComponent<>(newNode.getControllerServiceImplementation(), bundleCoordinate, terminationAwareLogger);

    // set the new impl, proxy, and invocation handler into the existing node
    existingNode.setControllerServiceAndProxy(loggableImplementation, loggableProxy, invocationHandler);
    existingNode.setExtensionMissing(newNode.isExtensionMissing());

    // need to refresh the properties in case we are changing from ghost component to real component
    existingNode.refreshProperties();

    logger.debug("Triggering async validation of {} due to controller service reload", existingNode);
    flowController.getValidationTrigger().triggerAsync(existingNode);
}