You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by fg...@apache.org on 2022/03/08 13:54:11 UTC

[nifi-minifi-cpp] 01/05: MINIFICPP-1686 - Processor destructors are not called

This is an automated email from the ASF dual-hosted git repository.

fgerlits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 61b98e6f9bb2d435a7873959e73ea7f9f2e1e91f
Author: Adam Markovics <nu...@gmail.com>
AuthorDate: Tue Nov 23 08:55:02 2021 +0100

    MINIFICPP-1686 - Processor destructors are not called
    
    Signed-off-by: Ferenc Gerlits <fg...@gmail.com>
    
    This closes #1252
---
 .github/workflows/ci.yml                           |   2 +-
 CMakeLists.txt                                     |   7 +
 cmake/BuildTests.cmake                             |   3 +-
 cmake/DockerConfig.cmake                           |   1 +
 controller/Controller.h                            |  12 +-
 docker/Dockerfile                                  |   3 +-
 .../features/core_functionality.feature            |   6 +
 docker/test/integration/minifi/core/ImageStore.py  |   2 +-
 .../minifi/core/SingleNodeDockerCluster.py         |   3 +
 .../minifi/core/TransientMinifiContainer.py        |  26 ++
 .../minifi/processors/LogOnDestructionProcessor.py |   8 +
 docker/test/integration/steps/steps.py             |  16 +
 extensions/aws/processors/DeleteS3Object.cpp       |   2 +
 extensions/aws/processors/FetchS3Object.cpp        |   2 +
 extensions/aws/processors/FetchS3Object.h          |   1 +
 extensions/aws/processors/ListS3.cpp               |   5 +-
 extensions/aws/processors/PutS3Object.cpp          |   2 +
 extensions/aws/processors/PutS3Object.h            |   1 +
 extensions/aws/processors/S3Processor.cpp          |   1 +
 .../processors/AzureBlobStorageProcessorBase.cpp   |   3 +-
 .../azure/processors/AzureStorageProcessorBase.cpp |   1 +
 .../azure/processors/DeleteAzureBlobStorage.cpp    |   1 +
 .../processors/DeleteAzureDataLakeStorage.cpp      |   1 +
 .../azure/processors/FetchAzureBlobStorage.cpp     |   2 +
 .../azure/processors/FetchAzureDataLakeStorage.cpp |   2 +
 .../azure/processors/FetchAzureDataLakeStorage.h   |   1 +
 .../azure/processors/ListAzureDataLakeStorage.cpp  |   1 +
 .../azure/processors/PutAzureBlobStorage.cpp       |   2 +
 extensions/azure/processors/PutAzureBlobStorage.h  |   1 +
 .../azure/processors/PutAzureDataLakeStorage.cpp   |   1 +
 .../azure/processors/PutAzureDataLakeStorage.h     |   1 +
 extensions/civetweb/protocols/RESTReceiver.cpp     |   4 +-
 extensions/civetweb/protocols/RESTReceiver.h       |   2 +-
 extensions/coap/tests/CoapC2VerifyHeartbeat.cpp    |   4 +-
 extensions/http-curl/protocols/AgentPrinter.cpp    |   2 +-
 extensions/http-curl/protocols/AgentPrinter.h      |   2 +-
 .../tests/C2ClearCoreComponentStateTest.cpp        |   6 +-
 .../tests/C2DescribeCoreComponentStateTest.cpp     |   6 +-
 extensions/http-curl/tests/C2NullConfiguration.cpp |   4 +-
 extensions/http-curl/tests/C2PauseResumeTest.cpp   |   5 +-
 .../http-curl/tests/C2VerifyServeResults.cpp       |   4 +-
 .../tests/ControllerServiceIntegrationTests.cpp    |   4 +-
 extensions/http-curl/tests/VerifyInvokeHTTP.h      |   4 +-
 .../http-curl/tests/unit/InvokeHTTPTests.cpp       |  34 +-
 extensions/jni/ExecuteJavaProcessor.cpp            |   2 +-
 extensions/jni/jvm/JniProcessContext.h             |   2 +-
 extensions/libarchive/BinFiles.cpp                 |   4 +-
 extensions/libarchive/BinFiles.h                   |   2 +-
 extensions/librdkafka/ConsumeKafka.cpp             |   3 +
 extensions/librdkafka/ConsumeKafka.h               |   4 +
 extensions/librdkafka/KafkaProcessorBase.cpp       |   1 +
 extensions/opencv/CaptureRTSPFrame.cpp             |   2 +
 extensions/opencv/CaptureRTSPFrame.h               |   2 +
 extensions/opencv/FrameIO.h                        |   1 +
 extensions/opencv/MotionDetector.cpp               |   2 +
 extensions/opencv/MotionDetector.h                 |   1 +
 .../SourceInitiatedSubscriptionListener.cpp        |   1 +
 .../SourceInitiatedSubscriptionListener.h          |   2 +-
 extensions/pdh/PerformanceDataMonitor.cpp          |   2 +
 extensions/pdh/PerformanceDataMonitor.h            |   1 +
 extensions/rocksdb-repos/FlowFileRepository.cpp    |   8 +-
 extensions/rocksdb-repos/FlowFileRepository.h      |  34 +-
 extensions/rocksdb-repos/ProvenanceRepository.h    |   4 +
 .../script/python/ExecutePythonProcessor.cpp       |   5 +-
 extensions/script/python/PythonObjectFactory.h     |  27 +-
 extensions/script/python/PythonProcessor.cpp       |  22 +-
 extensions/script/python/PythonProcessor.h         |  17 +-
 extensions/script/python/PythonScriptEngine.h      |   6 +-
 extensions/sftp/processors/ListSFTP.h              |   2 +-
 extensions/sftp/tests/ListSFTPTests.cpp            |  16 +-
 extensions/splunk/PutSplunkHTTP.cpp                |   2 +
 extensions/splunk/QuerySplunkIndexingStatus.cpp    |   2 +
 extensions/splunk/SplunkHECProcessor.cpp           |   1 +
 extensions/splunk/SplunkHECProcessor.h             |   1 +
 extensions/sql/processors/QueryDatabaseTable.h     |   2 +-
 .../processors/AttributesToJSON.cpp                |   1 +
 .../processors/AttributesToJSON.h                  |   4 +-
 .../processors/DefragmentText.cpp                  |   6 +-
 .../processors/DefragmentText.h                    |   2 +-
 .../standard-processors/processors/GetTCP.cpp      |   2 +
 extensions/standard-processors/processors/GetTCP.h |  20 +-
 .../standard-processors/processors/PutUDP.cpp      |   4 +-
 .../standard-processors/processors/RouteText.cpp   |   8 +-
 .../standard-processors/processors/TailFile.h      |   2 +-
 .../tests/integration/SecureSocketGetTCPTest.cpp   |   4 +-
 .../tests/integration/TailFileTest.cpp             |   6 +-
 .../tests/integration/TestExecuteProcess.cpp       |  20 +-
 .../standard-processors/tests/unit/GetTCPTests.cpp | 105 +++---
 .../tests/unit/ManifestTests.cpp                   |   2 +-
 .../tests/unit/ProcessGroupTestUtils.h             |   6 +-
 .../tests/unit/ProcessorTests.cpp                  |  32 +-
 .../standard-processors/tests/unit/PutUDPTests.cpp |   1 +
 .../tests/unit/RouteTextTests.cpp                  |   5 +-
 .../tests/unit/TailFileTests.cpp                   |  10 +-
 .../tests/unit/YamlConfigurationTests.cpp          |  18 +-
 .../tests/unit/YamlConnectionParserTest.cpp        |  12 +-
 extensions/systemd/ConsumeJournald.cpp             |   2 +
 extensions/systemd/ConsumeJournald.h               |   4 +-
 extensions/test-processors/CMakeLists.txt          |  31 ++
 .../test-processors}/KamikazeProcessor.cpp         |  12 +-
 .../test-processors}/KamikazeProcessor.h           |  26 +-
 .../test-processors/LogOnDestructionProcessor.cpp  |  34 +-
 .../test-processors/LogOnDestructionProcessor.h    |  32 +-
 extensions/usb-camera/GetUSBCamera.cpp             |   1 +
 extensions/windows-event-log/Bookmark.cpp          |   2 +-
 extensions/windows-event-log/Bookmark.h            |   4 +-
 .../CollectorInitiatedSubscription.cpp             |   1 +
 .../windows-event-log/ConsumeWindowsEventLog.h     |   2 +-
 .../windows-event-log/tests/BookmarkTests.cpp      |  48 ++-
 libminifi/include/Connection.h                     |  23 +-
 libminifi/include/CronDrivenSchedulingAgent.h      |   4 +-
 libminifi/include/EventDrivenSchedulingAgent.h     |   4 +-
 libminifi/include/FlowController.h                 |  31 +-
 libminifi/include/SchedulingAgent.h                |  12 +-
 libminifi/include/ThreadedSchedulingAgent.h        |   6 +-
 libminifi/include/TimerDrivenSchedulingAgent.h     |   2 +-
 libminifi/include/agent/build_description.h        |  18 +-
 libminifi/include/c2/C2Agent.h                     |   8 +-
 libminifi/include/c2/C2Client.h                    |   2 +-
 libminifi/include/c2/ControllerSocketProtocol.h    |   6 +-
 libminifi/include/c2/HeartbeatLogger.h             |   2 +-
 libminifi/include/c2/HeartbeatReporter.h           |   4 +-
 .../AbstractCoreComponentStateManagerProvider.h    |  17 +-
 libminifi/include/core/ClassLoader.h               |  12 +-
 libminifi/include/core/Connectable.h               |  18 +-
 libminifi/include/core/Core.h                      |   8 +-
 libminifi/include/core/CoreComponentState.h        |   4 +-
 libminifi/include/core/Flow.h                      |   2 +-
 libminifi/include/core/FlowConfiguration.h         |   8 +-
 libminifi/include/core/FlowFile.h                  |   6 +-
 libminifi/include/core/Funnel.h                    |   1 +
 libminifi/include/core/ObjectFactory.h             |  30 +-
 libminifi/include/core/ProcessContext.h            |   6 +-
 libminifi/include/core/ProcessGroup.h              |  87 +++--
 libminifi/include/core/ProcessSession.h            |   6 +-
 libminifi/include/core/Processor.h                 |  53 +--
 libminifi/include/core/ProcessorNode.h             |  38 +-
 libminifi/include/core/Repository.h                |  14 +-
 libminifi/include/core/RepositoryFactory.h         |   4 +-
 .../controller/StandardControllerServiceNode.h     |   7 -
 .../controller/StandardControllerServiceProvider.h |   8 +-
 .../include/core/repository/VolatileRepository.h   |  41 +--
 libminifi/include/core/state/ProcessorController.h |   8 +-
 libminifi/include/core/state/UpdateController.h    |   4 +-
 .../include/core/state/nodes/AgentInformation.h    |   4 +-
 .../include/core/state/nodes/FlowInformation.h     |   4 +-
 libminifi/include/core/state/nodes/QueueMetrics.h  |   9 +-
 libminifi/include/core/state/nodes/StateMonitor.h  |   4 +-
 libminifi/include/core/yaml/YamlConfiguration.h    |  10 +-
 libminifi/include/core/yaml/YamlConnectionParser.h |   6 +-
 libminifi/include/processors/ProcessorUtils.h      |  28 +-
 libminifi/include/utils/GeneralUtils.h             |  10 +
 libminifi/include/utils/ListingStateManager.h      |   8 +-
 libminifi/include/utils/ThreadPool.h               |  10 +-
 libminifi/src/Connection.cpp                       |  10 +-
 libminifi/src/CronDrivenSchedulingAgent.cpp        |   2 +-
 libminifi/src/EventDrivenSchedulingAgent.cpp       |   4 +-
 libminifi/src/FlowController.cpp                   | 122 ++++---
 libminifi/src/SchedulingAgent.cpp                  |  21 +-
 libminifi/src/ThreadedSchedulingAgent.cpp          |   6 +-
 libminifi/src/TimerDrivenSchedulingAgent.cpp       |   2 +-
 libminifi/src/c2/C2Agent.cpp                       |  20 +-
 libminifi/src/c2/C2Client.cpp                      |  30 +-
 libminifi/src/c2/ControllerSocketProtocol.cpp      |   2 +-
 libminifi/src/c2/HeartbeatLogger.cpp               |   2 +-
 .../AbstractCoreComponentStateManagerProvider.cpp  |  31 +-
 libminifi/src/core/Connectable.cpp                 |  28 +-
 libminifi/src/core/FlowConfiguration.cpp           |  13 +-
 libminifi/src/core/FlowFile.cpp                    |   4 +-
 libminifi/src/core/Funnel.cpp                      |   2 +
 libminifi/src/core/ProcessGroup.cpp                | 152 ++++----
 libminifi/src/core/ProcessSession.cpp              |  51 +--
 libminifi/src/core/Processor.cpp                   | 128 +++----
 libminifi/src/core/ProcessorNode.cpp               |   2 +-
 libminifi/src/core/RepositoryFactory.cpp           |  33 +-
 .../controller/StandardControllerServiceNode.cpp   |   9 -
 libminifi/src/core/state/ProcessorController.cpp   |   2 +-
 libminifi/src/core/yaml/YamlConfiguration.cpp      | 139 ++++----
 libminifi/src/core/yaml/YamlConnectionParser.cpp   |  10 +-
 libminifi/test/SingleInputTestController.h         |   7 +-
 libminifi/test/StatefulProcessor.cpp               |   1 +
 libminifi/test/StatefulProcessor.h                 |   3 +-
 libminifi/test/TestBase.cpp                        |  51 +--
 libminifi/test/TestBase.h                          |   6 +-
 .../test/archive-tests/CompressContentTests.cpp    |  10 +-
 libminifi/test/archive-tests/MergeFileTests.cpp    | 386 +++++++++++----------
 libminifi/test/flow-tests/CycleTest.cpp            |   6 +-
 libminifi/test/flow-tests/FlowControllerTests.cpp  |  16 +-
 libminifi/test/flow-tests/LoopTest.cpp             |   4 +-
 libminifi/test/flow-tests/MultiLoopTest.cpp        |   6 +-
 libminifi/test/flow-tests/SessionTests.cpp         |   7 +-
 libminifi/test/flow-tests/TestControllerWithFlow.h |   7 +-
 libminifi/test/integration/IntegrationBase.h       |   8 +-
 .../integration/OnScheduleErrorHandlingTests.cpp   |   9 +-
 .../integration/StateTransactionalityTests.cpp     |  10 +-
 libminifi/test/pcap-tests/PcapTest.cpp             |   6 +-
 .../test/persistence-tests/PersistenceTests.cpp    |  67 ++--
 libminifi/test/rocksdb-tests/EncryptionTests.cpp   |  10 +-
 libminifi/test/rocksdb-tests/RepoTests.cpp         |  27 +-
 libminifi/test/sensors-tests/SensorTests.cpp       |   4 +-
 libminifi/test/sql-tests/SQLTestPlan.h             |   4 +-
 libminifi/test/unit/C2MetricsTests.cpp             |   6 +-
 libminifi/test/unit/ControllerTests.cpp            |  24 +-
 libminifi/test/unit/ProcessorConfigUtilsTests.cpp  |   2 +-
 libminifi/test/unit/ProvenanceTestHelper.h         |  18 +-
 main/MiNiFiMain.cpp                                |   2 +-
 nanofi/include/cxx/C2CallbackAgent.h               |   2 +-
 nanofi/include/cxx/Instance.h                      |   2 +-
 nanofi/include/cxx/Plan.h                          |   2 +-
 nanofi/src/api/nanofi.cpp                          |   2 +-
 nanofi/src/cxx/C2CallbackAgent.cpp                 |   2 +-
 nanofi/src/cxx/Plan.cpp                            |  19 +-
 212 files changed, 1495 insertions(+), 1514 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1c2e75e..fec1e24 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -202,7 +202,7 @@ jobs:
           if [ -d ~/.ccache ]; then mv ~/.ccache .; fi
           mkdir build
           cd build
-          cmake -DUSE_SHARED_LIBS= -DSTRICT_GSL_CHECKS=AUDIT -DENABLE_JNI=OFF -DDISABLE_JEMALLOC=ON -DENABLE_AWS=ON -DENABLE_LIBRDKAFKA=ON -DENABLE_MQTT=ON -DENABLE_AZURE=ON -DENABLE_SQL=ON -DENABLE_SPLUNK=ON -DENABLE_OPC=ON -DENABLE_SCRIPTING=ON -DENABLE_LUA_SCRIPTING=ON -DENABLE_KUBERNETES=ON -DDOCKER_BUILD_ONLY=ON -DDOCKER_CCACHE_DUMP_LOCATION=$HOME/.ccache ..
+          cmake -DUSE_SHARED_LIBS= -DSTRICT_GSL_CHECKS=AUDIT -DENABLE_JNI=OFF -DDISABLE_JEMALLOC=ON -DENABLE_AWS=ON -DENABLE_LIBRDKAFKA=ON -DENABLE_MQTT=ON -DENABLE_AZURE=ON -DENABLE_SQL=ON -DENABLE_SPLUNK=ON -DENABLE_OPC=ON -DENABLE_SCRIPTING=ON -DENABLE_LUA_SCRIPTING=ON -DENABLE_KUBERNETES=ON -DENABLE_TEST_PROCESSORS=ON -DDOCKER_BUILD_ONLY=ON -DDOCKER_CCACHE_DUMP_LOCATION=$HOME/.ccache ..
           make docker
       - id: install_deps
         run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 43b68db..5284a66 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,6 +118,7 @@ option(ENABLE_ENCRYPT_CONFIG "Enables build of encrypt-config binary." ON)
 option(ENABLE_SPLUNK "Enable Splunk support" OFF)
 option(DOCKER_BUILD_ONLY "Disables all targets except docker build scripts. Ideal for systems without an up-to-date compiler." OFF)
 option(ENABLE_KUBERNETES "Enables the Kubernetes extensions." OFF)
+option(ENABLE_TEST_PROCESSORS "Enables test processors" OFF)
 
 ## Keep all option definitions above this line
 
@@ -611,6 +612,12 @@ if (ENABLE_KUBERNETES)
   createExtension(KUBERNETES-EXTENSIONS "KUBERNETES EXTENSIONS" "This enables Kubernetes support" "extensions/kubernetes")
 endif()
 
+## Add the test-processors extension
+# ENABLE_TEST_PROCESSORS option is to only build test processors but not unit tests in docker integration tests.
+if (NOT SKIP_TESTS OR ENABLE_TEST_PROCESSORS)
+	createExtension(TEST-PROCESSORS-EXTENSION "TEST-PROCESSORS EXTENSION" "This enables processors purely for testing purposes" "extensions/test-processors")
+endif()
+
 ## NOW WE CAN ADD LIBRARIES AND EXTENSIONS TO MAIN
 add_subdirectory(main)
 
diff --git a/cmake/BuildTests.cmake b/cmake/BuildTests.cmake
index 6f8db36..043fc50 100644
--- a/cmake/BuildTests.cmake
+++ b/cmake/BuildTests.cmake
@@ -84,7 +84,7 @@ endfunction()
 enable_testing(test)
 
 SET(TEST_BASE_LIB test_base)
-set(TEST_BASE_SOURCES "TestBase.cpp" "RandomServerSocket.cpp" "KamikazeProcessor.cpp" "StatefulProcessor.cpp" "WriteToFlowFileTestProcessor.cpp" "ReadFromFlowFileTestProcessor.cpp")
+set(TEST_BASE_SOURCES "TestBase.cpp" "RandomServerSocket.cpp" "StatefulProcessor.cpp" "WriteToFlowFileTestProcessor.cpp" "ReadFromFlowFileTestProcessor.cpp")
 list(TRANSFORM TEST_BASE_SOURCES PREPEND "${TEST_DIR}/")
 add_library(${TEST_BASE_LIB} STATIC "${TEST_BASE_SOURCES}")
 target_link_libraries(${TEST_BASE_LIB} core-minifi)
@@ -166,6 +166,7 @@ FOREACH(testfile ${INTEGRATION_TESTS})
   MATH(EXPR INT_TEST_COUNT "${INT_TEST_COUNT}+1")
 ENDFOREACH()
 
+target_link_libraries(OnScheduleErrorHandlingTests minifi-test-processors)
 target_wholearchive_library(StateTransactionalityTests minifi-standard-processors)
 
 add_test(NAME OnScheduleErrorHandlingTests COMMAND OnScheduleErrorHandlingTests "${TEST_RESOURCES}/TestOnScheduleRetry.yml"  "${TEST_RESOURCES}/")
diff --git a/cmake/DockerConfig.cmake b/cmake/DockerConfig.cmake
index 226439f..d49bccf 100644
--- a/cmake/DockerConfig.cmake
+++ b/cmake/DockerConfig.cmake
@@ -48,6 +48,7 @@ add_custom_target(
         -c ENABLE_SCRIPTING=${ENABLE_SCRIPTING}
         -c ENABLE_LUA_SCRIPTING=${ENABLE_LUA_SCRIPTING}
         -c ENABLE_KUBERNETES=${ENABLE_KUBERNETES}
+        -c ENABLE_TEST_PROCESSORS=${ENABLE_TEST_PROCESSORS}
         -c DISABLE_CURL=${DISABLE_CURL}
         -c DISABLE_JEMALLOC=${DISABLE_JEMALLOC}
         -c DISABLE_CIVET=${DISABLE_CIVET}
diff --git a/controller/Controller.h b/controller/Controller.h
index 6e2492c..b31bd14 100644
--- a/controller/Controller.h
+++ b/controller/Controller.h
@@ -246,18 +246,18 @@ std::shared_ptr<org::apache::nifi::minifi::core::controller::ControllerService>
 
   configuration->get(org::apache::nifi::minifi::Configure::nifi_provenance_repository_class_name, prov_repo_class);
   // Create repos for flow record and provenance
-  const auto prov_repo = org::apache::nifi::minifi::core::createRepository(prov_repo_class, true, "provenance");
+  const std::shared_ptr prov_repo = org::apache::nifi::minifi::core::createRepository(prov_repo_class, true, "provenance");
   prov_repo->initialize(configuration);
 
   configuration->get(org::apache::nifi::minifi::Configure::nifi_flow_repository_class_name, flow_repo_class);
 
-  const auto flow_repo = org::apache::nifi::minifi::core::createRepository(flow_repo_class, true, "flowfile");
+  const std::shared_ptr flow_repo = org::apache::nifi::minifi::core::createRepository(flow_repo_class, true, "flowfile");
 
   flow_repo->initialize(configuration);
 
   configuration->get(org::apache::nifi::minifi::Configure::nifi_content_repository_class_name, content_repo_class);
 
-  const auto content_repo = org::apache::nifi::minifi::core::createContentRepository(content_repo_class, true, "content");
+  const std::shared_ptr content_repo = org::apache::nifi::minifi::core::createContentRepository(content_repo_class, true, "content");
 
   content_repo->initialize(configuration);
 
@@ -295,18 +295,18 @@ void printManifest(const std::shared_ptr<org::apache::nifi::minifi::Configure> &
 
   configuration->get(org::apache::nifi::minifi::Configure::nifi_provenance_repository_class_name, prov_repo_class);
   // Create repos for flow record and provenance
-  const auto prov_repo = org::apache::nifi::minifi::core::createRepository(prov_repo_class, true, "provenance");
+  const std::shared_ptr prov_repo = org::apache::nifi::minifi::core::createRepository(prov_repo_class, true, "provenance");
   prov_repo->initialize(configuration);
 
   configuration->get(org::apache::nifi::minifi::Configure::nifi_flow_repository_class_name, flow_repo_class);
 
-  const auto flow_repo = org::apache::nifi::minifi::core::createRepository(flow_repo_class, true, "flowfile");
+  const std::shared_ptr flow_repo = org::apache::nifi::minifi::core::createRepository(flow_repo_class, true, "flowfile");
 
   flow_repo->initialize(configuration);
 
   configuration->get(org::apache::nifi::minifi::Configure::nifi_content_repository_class_name, content_repo_class);
 
-  const auto content_repo = org::apache::nifi::minifi::core::createContentRepository(content_repo_class, true, "content");
+  const std::shared_ptr content_repo = org::apache::nifi::minifi::core::createContentRepository(content_repo_class, true, "content");
 
   content_repo->initialize(configuration);
 
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 3ec9856..6eea15d 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -51,6 +51,7 @@ ARG ENABLE_AZURE=OFF
 ARG ENABLE_ENCRYPT_CONFIG=ON
 ARG ENABLE_NANOFI=OFF
 ARG ENABLE_SPLUNK=OFF
+ARG ENABLE_TEST_PROCESSORS=OFF
 ARG DISABLE_CURL=OFF
 ARG DISABLE_JEMALLOC=ON
 ARG DISABLE_CIVET=OFF
@@ -119,7 +120,7 @@ RUN cmake -DSTATIC_BUILD= -DSKIP_TESTS=true -DENABLE_ALL="${ENABLE_ALL}" -DENABL
     -DENABLE_TENSORFLOW="${ENABLE_TENSORFLOW}" -DENABLE_AWS="${ENABLE_AWS}" -DENABLE_BUSTACHE="${ENABLE_BUSTACHE}" -DENABLE_SFTP="${ENABLE_SFTP}" \
     -DENABLE_OPENWSMAN="${ENABLE_OPENWSMAN}" -DENABLE_AZURE="${ENABLE_AZURE}" -DENABLE_NANOFI=${ENABLE_NANOFI} -DENABLE_SYSTEMD=OFF \
     -DDISABLE_CURL="${DISABLE_CURL}" -DDISABLE_JEMALLOC="${DISABLE_JEMALLOC}" -DDISABLE_CIVET="${DISABLE_CIVET}" -DENABLE_SPLUNK=${ENABLE_SPLUNK} \
-    -DDISABLE_EXPRESSION_LANGUAGE="${DISABLE_EXPRESSION_LANGUAGE}" -DDISABLE_ROCKSDB="${DISABLE_ROCKSDB}" \
+    -DENABLE_TEST_PROCESSORS="${ENABLE_TEST_PROCESSORS}" -DDISABLE_EXPRESSION_LANGUAGE="${DISABLE_EXPRESSION_LANGUAGE}" -DDISABLE_ROCKSDB="${DISABLE_ROCKSDB}" \
     -DDISABLE_LIBARCHIVE="${DISABLE_LIBARCHIVE}" -DDISABLE_LZMA="${DISABLE_LZMA}" -DDISABLE_BZIP2="${DISABLE_BZIP2}" \
     -DENABLE_SCRIPTING="${ENABLE_SCRIPTING}" -DDISABLE_PYTHON_SCRIPTING="${DISABLE_PYTHON_SCRIPTING}" -DENABLE_LUA_SCRIPTING="${ENABLE_LUA_SCRIPTING}" \
     -DENABLE_KUBERNETES="${ENABLE_KUBERNETES}" \
diff --git a/docker/test/integration/features/core_functionality.feature b/docker/test/integration/features/core_functionality.feature
index b29a537..54e0e76 100644
--- a/docker/test/integration/features/core_functionality.feature
+++ b/docker/test/integration/features/core_functionality.feature
@@ -29,3 +29,9 @@ Feature: Core flow functionalities
     When the MiNiFi instance starts up
     Then the Minifi logs contain the following message: "Using plaintext FlowFileRepository" in less than 5 seconds
     And the Minifi logs contain the following message: "Using plaintext DatabaseContentRepository" in less than 1 second
+
+
+  Scenario: Processors are destructed when agent is stopped
+    Given a LogOnDestructionProcessor processor with the name "logOnDestruction" in the "transient-minifi" flow with engine "transient-minifi"
+    When the MiNiFi instance starts up
+    Then the Minifi logs contain the following message: "LogOnDestructionProcessor is being destructed" in less than 100 seconds
diff --git a/docker/test/integration/minifi/core/ImageStore.py b/docker/test/integration/minifi/core/ImageStore.py
index 28e003c..56d81eb 100644
--- a/docker/test/integration/minifi/core/ImageStore.py
+++ b/docker/test/integration/minifi/core/ImageStore.py
@@ -43,7 +43,7 @@ class ImageStore:
         if container_engine in self.images:
             return self.images[container_engine]
 
-        if container_engine == "minifi-cpp":
+        if container_engine == "minifi-cpp" or container_engine == "transient-minifi":
             image = self.__build_minifi_cpp_image()
         elif container_engine == "minifi-cpp-in-kubernetes":
             image = self.__build_simple_minifi_cpp_image_with_root()
diff --git a/docker/test/integration/minifi/core/SingleNodeDockerCluster.py b/docker/test/integration/minifi/core/SingleNodeDockerCluster.py
index d1cbb6b..2cdffd5 100644
--- a/docker/test/integration/minifi/core/SingleNodeDockerCluster.py
+++ b/docker/test/integration/minifi/core/SingleNodeDockerCluster.py
@@ -20,6 +20,7 @@ import uuid
 
 from .Cluster import Cluster
 from .MinifiContainer import MinifiContainer
+from .TransientMinifiContainer import TransientMinifiContainer
 from .NifiContainer import NifiContainer
 from .ZookeeperContainer import ZookeeperContainer
 from .KafkaBrokerContainer import KafkaBrokerContainer
@@ -87,6 +88,8 @@ class SingleNodeDockerCluster(Cluster):
             return self.containers.setdefault(name, MinifiContainer(self.data_directories["minifi_config_dir"], name, self.vols, self.network, self.image_store, command))
         elif engine == 'kubernetes':
             return self.containers.setdefault(name, MinifiAsPodInKubernetesCluster(self.data_directories["minifi_config_dir"], name, self.vols, self.network, self.image_store, command))
+        elif engine == 'transient-minifi':
+            return self.containers.setdefault(name, TransientMinifiContainer(self.data_directories["minifi_config_dir"], name, self.vols, self.network, self.image_store, command))
         elif engine == 'kafka-broker':
             if 'zookeeper' not in self.containers:
                 self.containers.setdefault('zookeeper', ZookeeperContainer('zookeeper', self.vols, self.network, self.image_store, command))
diff --git a/docker/test/integration/minifi/core/TransientMinifiContainer.py b/docker/test/integration/minifi/core/TransientMinifiContainer.py
new file mode 100644
index 0000000..9c93a08
--- /dev/null
+++ b/docker/test/integration/minifi/core/TransientMinifiContainer.py
@@ -0,0 +1,26 @@
+# @file TransientMinifiContainer.py
+#
+# 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.
+
+from .MinifiContainer import MinifiContainer
+
+
+class TransientMinifiContainer(MinifiContainer):
+    def __init__(self, config_dir, name, vols, network, image_store, command=None):
+        if not command:
+            command = ["/bin/sh", "-c",
+                       "cp /tmp/minifi_config/config.yml ./conf/ && ./bin/minifi.sh start && sleep 10 && ./bin/minifi.sh stop && sleep 100"]
+        super().__init__(config_dir, name, vols, network, image_store, command)
diff --git a/docker/test/integration/minifi/processors/LogOnDestructionProcessor.py b/docker/test/integration/minifi/processors/LogOnDestructionProcessor.py
new file mode 100644
index 0000000..79c1daf
--- /dev/null
+++ b/docker/test/integration/minifi/processors/LogOnDestructionProcessor.py
@@ -0,0 +1,8 @@
+from ..core.Processor import Processor
+
+
+class LogOnDestructionProcessor(Processor):
+    def __init__(self, schedule={'scheduling period': '2 sec'}):
+        super(LogOnDestructionProcessor, self).__init__(
+            'LogOnDestructionProcessor',
+            schedule=schedule)
diff --git a/docker/test/integration/steps/steps.py b/docker/test/integration/steps/steps.py
index cc56a70..870af59 100644
--- a/docker/test/integration/steps/steps.py
+++ b/docker/test/integration/steps/steps.py
@@ -65,12 +65,23 @@ def step_impl(context, processor_type, processor_name, property_name, property_v
     __create_processor(context, processor_type, processor_name, property_name, property_value, minifi_container_name)
 
 
+@given("a {processor_type} processor with the name \"{processor_name}\" and the \"{property_name}\" property set to \"{property_value}\" in a \"{minifi_container_name}\" flow with engine \"{engine_name}\"")
+@given("a {processor_type} processor with the name \"{processor_name}\" and the \"{property_name}\" property set to \"{property_value}\" in the \"{minifi_container_name}\" flow with engine \"{engine_name}\"")
+def step_impl(context, processor_type, processor_name, property_name, property_value, minifi_container_name, engine_name):
+    __create_processor(context, processor_type, processor_name, property_name, property_value, minifi_container_name, engine_name)
+
+
 @given("a {processor_type} processor with the \"{property_name}\" property set to \"{property_value}\" in a \"{minifi_container_name}\" flow")
 @given("a {processor_type} processor with the \"{property_name}\" property set to \"{property_value}\" in the \"{minifi_container_name}\" flow")
 def step_impl(context, processor_type, property_name, property_value, minifi_container_name):
     __create_processor(context, processor_type, processor_type, property_name, property_value, minifi_container_name)
 
 
+@given("a {processor_type} processor the \"{property_name}\" property set to \"{property_value}\" in the \"{minifi_container_name}\" flow with engine \"{engine_name}\"")
+def step_impl(context, processor_type, property_name, property_value, minifi_container_name, engine_name):
+    __create_processor(context, processor_type, processor_type, property_name, property_value, minifi_container_name, engine_name)
+
+
 @given("a {processor_type} processor with the \"{property_name}\" property set to \"{property_value}\"")
 def step_impl(context, processor_type, property_name, property_value):
     __create_processor(context, processor_type, processor_type, property_name, property_value, "minifi-cpp-flow")
@@ -86,6 +97,11 @@ def step_impl(context, processor_type, processor_name, minifi_container_name):
     __create_processor(context, processor_type, processor_name, None, None, minifi_container_name)
 
 
+@given("a {processor_type} processor with the name \"{processor_name}\" in the \"{minifi_container_name}\" flow with engine \"{engine_name}\"")
+def step_impl(context, processor_type, processor_name, minifi_container_name, engine_name):
+    __create_processor(context, processor_type, processor_name, None, None, minifi_container_name, engine_name)
+
+
 @given("a {processor_type} processor with the name \"{processor_name}\"")
 def step_impl(context, processor_type, processor_name):
     __create_processor(context, processor_type, processor_name, None, None, "minifi-cpp-flow")
diff --git a/extensions/aws/processors/DeleteS3Object.cpp b/extensions/aws/processors/DeleteS3Object.cpp
index c16a28a..873346e 100644
--- a/extensions/aws/processors/DeleteS3Object.cpp
+++ b/extensions/aws/processors/DeleteS3Object.cpp
@@ -23,6 +23,8 @@
 #include <set>
 #include <memory>
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/aws/processors/FetchS3Object.cpp b/extensions/aws/processors/FetchS3Object.cpp
index d0099b4..7667d52 100644
--- a/extensions/aws/processors/FetchS3Object.cpp
+++ b/extensions/aws/processors/FetchS3Object.cpp
@@ -23,6 +23,8 @@
 #include <set>
 #include <memory>
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/aws/processors/FetchS3Object.h b/extensions/aws/processors/FetchS3Object.h
index 23f2dca..4a2411d 100644
--- a/extensions/aws/processors/FetchS3Object.h
+++ b/extensions/aws/processors/FetchS3Object.h
@@ -27,6 +27,7 @@
 #include <utility>
 #include <vector>
 
+#include "io/StreamPipe.h"
 #include "S3Processor.h"
 #include "utils/GeneralUtils.h"
 
diff --git a/extensions/aws/processors/ListS3.cpp b/extensions/aws/processors/ListS3.cpp
index 9573aa4..61410ed 100644
--- a/extensions/aws/processors/ListS3.cpp
+++ b/extensions/aws/processors/ListS3.cpp
@@ -20,13 +20,12 @@
 
 #include "ListS3.h"
 
-#include <tuple>
 #include <algorithm>
-#include <set>
 #include <utility>
 #include <memory>
 
-#include "utils/StringUtils.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/aws/processors/PutS3Object.cpp b/extensions/aws/processors/PutS3Object.cpp
index f20d5b5..9370947 100644
--- a/extensions/aws/processors/PutS3Object.cpp
+++ b/extensions/aws/processors/PutS3Object.cpp
@@ -29,6 +29,8 @@
 #include "properties/Properties.h"
 #include "utils/StringUtils.h"
 #include "utils/MapUtils.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/aws/processors/PutS3Object.h b/extensions/aws/processors/PutS3Object.h
index 6f92bf0..0ba71b1 100644
--- a/extensions/aws/processors/PutS3Object.h
+++ b/extensions/aws/processors/PutS3Object.h
@@ -30,6 +30,7 @@
 #include <utility>
 #include <vector>
 
+#include "io/StreamPipe.h"
 #include "S3Processor.h"
 #include "utils/gsl.h"
 #include "utils/Id.h"
diff --git a/extensions/aws/processors/S3Processor.cpp b/extensions/aws/processors/S3Processor.cpp
index f143618..ff44a89 100644
--- a/extensions/aws/processors/S3Processor.cpp
+++ b/extensions/aws/processors/S3Processor.cpp
@@ -25,6 +25,7 @@
 #include <memory>
 #include <utility>
 
+#include "core/ProcessContext.h"
 #include "S3Wrapper.h"
 #include "AWSCredentialsService.h"
 #include "properties/Properties.h"
diff --git a/extensions/azure/processors/AzureBlobStorageProcessorBase.cpp b/extensions/azure/processors/AzureBlobStorageProcessorBase.cpp
index 433c9d6..bd26637 100644
--- a/extensions/azure/processors/AzureBlobStorageProcessorBase.cpp
+++ b/extensions/azure/processors/AzureBlobStorageProcessorBase.cpp
@@ -20,8 +20,7 @@
 
 #include "AzureBlobStorageProcessorBase.h"
 
-#include <memory>
-#include <string>
+#include "core/ProcessContext.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
 
diff --git a/extensions/azure/processors/AzureStorageProcessorBase.cpp b/extensions/azure/processors/AzureStorageProcessorBase.cpp
index a5a2426..7411617 100644
--- a/extensions/azure/processors/AzureStorageProcessorBase.cpp
+++ b/extensions/azure/processors/AzureStorageProcessorBase.cpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 
+#include "core/ProcessContext.h"
 #include "controllerservices/AzureStorageCredentialsService.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/DeleteAzureBlobStorage.cpp b/extensions/azure/processors/DeleteAzureBlobStorage.cpp
index c391b8f..590f930 100644
--- a/extensions/azure/processors/DeleteAzureBlobStorage.cpp
+++ b/extensions/azure/processors/DeleteAzureBlobStorage.cpp
@@ -20,6 +20,7 @@
 
 #include "DeleteAzureBlobStorage.h"
 
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 #include "utils/ProcessorConfigUtils.h"
 
diff --git a/extensions/azure/processors/DeleteAzureDataLakeStorage.cpp b/extensions/azure/processors/DeleteAzureDataLakeStorage.cpp
index c43e327..eb71d24 100644
--- a/extensions/azure/processors/DeleteAzureDataLakeStorage.cpp
+++ b/extensions/azure/processors/DeleteAzureDataLakeStorage.cpp
@@ -22,6 +22,7 @@
 
 #include "utils/ProcessorConfigUtils.h"
 #include "utils/gsl.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/FetchAzureBlobStorage.cpp b/extensions/azure/processors/FetchAzureBlobStorage.cpp
index 73ac27c..31f987d 100644
--- a/extensions/azure/processors/FetchAzureBlobStorage.cpp
+++ b/extensions/azure/processors/FetchAzureBlobStorage.cpp
@@ -20,7 +20,9 @@
 
 #include "FetchAzureBlobStorage.h"
 
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
+#include "io/StreamPipe.h"
 #include "utils/ProcessorConfigUtils.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/FetchAzureDataLakeStorage.cpp b/extensions/azure/processors/FetchAzureDataLakeStorage.cpp
index b41aede..0071477 100644
--- a/extensions/azure/processors/FetchAzureDataLakeStorage.cpp
+++ b/extensions/azure/processors/FetchAzureDataLakeStorage.cpp
@@ -20,6 +20,8 @@
 
 #include "FetchAzureDataLakeStorage.h"
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/FetchAzureDataLakeStorage.h b/extensions/azure/processors/FetchAzureDataLakeStorage.h
index 74a2917..3c2d083 100644
--- a/extensions/azure/processors/FetchAzureDataLakeStorage.h
+++ b/extensions/azure/processors/FetchAzureDataLakeStorage.h
@@ -24,6 +24,7 @@
 #include <utility>
 #include <memory>
 
+#include "io/StreamPipe.h"
 #include "AzureDataLakeStorageFileProcessorBase.h"
 
 template<typename AzureDataLakeStorageProcessor>
diff --git a/extensions/azure/processors/ListAzureDataLakeStorage.cpp b/extensions/azure/processors/ListAzureDataLakeStorage.cpp
index 4ee4e3d..187dbf3 100644
--- a/extensions/azure/processors/ListAzureDataLakeStorage.cpp
+++ b/extensions/azure/processors/ListAzureDataLakeStorage.cpp
@@ -21,6 +21,7 @@
 #include "ListAzureDataLakeStorage.h"
 
 #include "utils/ProcessorConfigUtils.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/PutAzureBlobStorage.cpp b/extensions/azure/processors/PutAzureBlobStorage.cpp
index 2ebb4de..2e741b9 100644
--- a/extensions/azure/processors/PutAzureBlobStorage.cpp
+++ b/extensions/azure/processors/PutAzureBlobStorage.cpp
@@ -20,6 +20,8 @@
 
 #include "PutAzureBlobStorage.h"
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/PutAzureBlobStorage.h b/extensions/azure/processors/PutAzureBlobStorage.h
index 5d2079d..52e0ca2 100644
--- a/extensions/azure/processors/PutAzureBlobStorage.h
+++ b/extensions/azure/processors/PutAzureBlobStorage.h
@@ -29,6 +29,7 @@
 #include "core/Property.h"
 #include "core/logging/LoggerConfiguration.h"
 #include "AzureBlobStorageProcessorBase.h"
+#include "io/StreamPipe.h"
 
 template<typename T>
 class AzureBlobStorageTestsFixture;
diff --git a/extensions/azure/processors/PutAzureDataLakeStorage.cpp b/extensions/azure/processors/PutAzureDataLakeStorage.cpp
index ef2d5b3..bf53088 100644
--- a/extensions/azure/processors/PutAzureDataLakeStorage.cpp
+++ b/extensions/azure/processors/PutAzureDataLakeStorage.cpp
@@ -24,6 +24,7 @@
 
 #include "utils/ProcessorConfigUtils.h"
 #include "utils/gsl.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org::apache::nifi::minifi::azure::processors {
diff --git a/extensions/azure/processors/PutAzureDataLakeStorage.h b/extensions/azure/processors/PutAzureDataLakeStorage.h
index 79bff78..4dddcf6 100644
--- a/extensions/azure/processors/PutAzureDataLakeStorage.h
+++ b/extensions/azure/processors/PutAzureDataLakeStorage.h
@@ -25,6 +25,7 @@
 #include <memory>
 
 #include "AzureDataLakeStorageFileProcessorBase.h"
+#include "io/StreamPipe.h"
 
 #include "utils/Enum.h"
 #include "utils/Export.h"
diff --git a/extensions/civetweb/protocols/RESTReceiver.cpp b/extensions/civetweb/protocols/RESTReceiver.cpp
index 305ea36..a3ecc1b 100644
--- a/extensions/civetweb/protocols/RESTReceiver.cpp
+++ b/extensions/civetweb/protocols/RESTReceiver.cpp
@@ -46,7 +46,7 @@ RESTReceiver::RESTReceiver(const std::string& name, const utils::Identifier& uui
     : HeartbeatReporter(name, uuid) {
 }
 
-void RESTReceiver::initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink, const std::shared_ptr<Configure> &configure) {
+void RESTReceiver::initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink, const std::shared_ptr<Configure> &configure) {
   HeartbeatReporter::initialize(controller, updateSink, configure);
   logger_->log_trace("Initializing rest receiver");
   if (nullptr != configuration_) {
@@ -54,7 +54,7 @@ void RESTReceiver::initialize(core::controller::ControllerServiceProvider* contr
     configuration_->get("nifi.c2.rest.listener.port", "c2.rest.listener.port", listeningPort);
     configuration_->get("nifi.c2.rest.listener.cacert", "c2.rest.listener.cacert", caCert);
     if (!listeningPort.empty() && !rootUri.empty()) {
-      handler = std::unique_ptr<ListeningProtocol>(new ListeningProtocol());
+      handler = std::make_unique<ListeningProtocol>();
       if (!caCert.empty()) {
         listener = start_webserver(listeningPort, rootUri, dynamic_cast<CivetHandler*>(handler.get()), caCert);
       } else {
diff --git a/extensions/civetweb/protocols/RESTReceiver.h b/extensions/civetweb/protocols/RESTReceiver.h
index 903c3bb..349f021 100644
--- a/extensions/civetweb/protocols/RESTReceiver.h
+++ b/extensions/civetweb/protocols/RESTReceiver.h
@@ -46,7 +46,7 @@ class RESTReceiver : public RESTProtocol, public HeartbeatReporter {
  public:
   explicit RESTReceiver(const std::string& name, const utils::Identifier& uuid = {});
 
-  void initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink,
+  void initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink,
                           const std::shared_ptr<Configure> &configure) override;
   int16_t heartbeat(const C2Payload &heartbeat) override;
 
diff --git a/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp b/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp
index 15704f6..4d587cb 100644
--- a/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp
+++ b/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp
@@ -93,10 +93,10 @@ class VerifyCoAPServer : public CoapIntegrationBase {
   }
 
   void queryRootProcessGroup(std::shared_ptr<core::ProcessGroup> pg) override {
-    std::shared_ptr<core::Processor> proc = pg->findProcessorByName("invoke");
+    auto proc = pg->findProcessorByName("invoke");
     assert(proc != nullptr);
 
-    std::shared_ptr<minifi::processors::InvokeHTTP> inv = std::dynamic_pointer_cast<minifi::processors::InvokeHTTP>(proc);
+    const auto* const inv = dynamic_cast<minifi::processors::InvokeHTTP*>(proc);
 
     assert(inv != nullptr);
     std::string url = "";
diff --git a/extensions/http-curl/protocols/AgentPrinter.cpp b/extensions/http-curl/protocols/AgentPrinter.cpp
index c0ecaf5..7e15715 100644
--- a/extensions/http-curl/protocols/AgentPrinter.cpp
+++ b/extensions/http-curl/protocols/AgentPrinter.cpp
@@ -35,7 +35,7 @@ AgentPrinter::AgentPrinter(const std::string& name, const utils::Identifier& uui
     : HeartbeatReporter(name, uuid) {
 }
 
-void AgentPrinter::initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink,
+void AgentPrinter::initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink,
                               const std::shared_ptr<Configure> &configure) {
   HeartbeatReporter::initialize(controller, updateSink, configure);
 }
diff --git a/extensions/http-curl/protocols/AgentPrinter.h b/extensions/http-curl/protocols/AgentPrinter.h
index 67d57ca..fa36805 100644
--- a/extensions/http-curl/protocols/AgentPrinter.h
+++ b/extensions/http-curl/protocols/AgentPrinter.h
@@ -41,7 +41,7 @@ class AgentPrinter : public HeartbeatJsonSerializer, public HeartbeatReporter {
   /**
    * Initialize agent printer.
    */
-  void initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink,
+  void initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink,
                           const std::shared_ptr<Configure> &configure) override;
 
   /**
diff --git a/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp b/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp
index c0f4006..569fb77 100644
--- a/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp
+++ b/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp
@@ -50,10 +50,10 @@ class VerifyC2ClearCoreComponentState : public VerifyC2Base {
   }
 
  protected:
-  void updateProperties(std::shared_ptr<minifi::FlowController> flow_controller) override {
-    std::dynamic_pointer_cast<minifi::state::ProcessorController>(flow_controller->getComponents("TailFile1")[0])
+  void updateProperties(minifi::FlowController& flow_controller) override {
+    dynamic_cast<minifi::state::ProcessorController*>(flow_controller.getComponents("TailFile1")[0])
         ->getProcessor()->setProperty(minifi::processors::TailFile::FileName, test_file_1_);
-    std::dynamic_pointer_cast<minifi::state::ProcessorController>(flow_controller->getComponents("TailFile2")[0])
+    dynamic_cast<minifi::state::ProcessorController*>(flow_controller.getComponents("TailFile2")[0])
         ->getProcessor()->setProperty(minifi::processors::TailFile::FileName, test_file_2_);
   }
 
diff --git a/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp b/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp
index a0a1783..354e732 100644
--- a/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp
+++ b/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp
@@ -42,10 +42,10 @@ class VerifyC2DescribeCoreComponentState : public VerifyC2Describe {
   }
 
  protected:
-  void updateProperties(std::shared_ptr<minifi::FlowController> flow_controller) override {
-    std::dynamic_pointer_cast<minifi::state::ProcessorController>(flow_controller->getComponents("TailFile1")[0])
+  void updateProperties(minifi::FlowController& flow_controller) override {
+    dynamic_cast<minifi::state::ProcessorController*>(flow_controller.getComponents("TailFile1")[0])
         ->getProcessor()->setProperty(minifi::processors::TailFile::FileName, test_file_1_);
-    std::dynamic_pointer_cast<minifi::state::ProcessorController>(flow_controller->getComponents("TailFile2")[0])
+    dynamic_cast<minifi::state::ProcessorController*>(flow_controller.getComponents("TailFile2")[0])
         ->getProcessor()->setProperty(minifi::processors::TailFile::FileName, test_file_2_);
   }
 
diff --git a/extensions/http-curl/tests/C2NullConfiguration.cpp b/extensions/http-curl/tests/C2NullConfiguration.cpp
index d0fda77..ca12f31 100644
--- a/extensions/http-curl/tests/C2NullConfiguration.cpp
+++ b/extensions/http-curl/tests/C2NullConfiguration.cpp
@@ -62,10 +62,10 @@ class VerifyC2Server : public HTTPIntegrationBase {
   }
 
   void queryRootProcessGroup(std::shared_ptr<core::ProcessGroup> pg) override {
-    std::shared_ptr<core::Processor> proc = pg->findProcessorByName("invoke");
+    auto* const proc = pg->findProcessorByName("invoke");
     assert(proc != nullptr);
 
-    std::shared_ptr<minifi::processors::InvokeHTTP> inv = std::dynamic_pointer_cast<minifi::processors::InvokeHTTP>(proc);
+    const auto* const inv = dynamic_cast<minifi::processors::InvokeHTTP*>(proc);
 
     assert(inv != nullptr);
     std::string url;
diff --git a/extensions/http-curl/tests/C2PauseResumeTest.cpp b/extensions/http-curl/tests/C2PauseResumeTest.cpp
index ccd99d8..905e18d 100644
--- a/extensions/http-curl/tests/C2PauseResumeTest.cpp
+++ b/extensions/http-curl/tests/C2PauseResumeTest.cpp
@@ -133,10 +133,11 @@ int main(int argc, char **argv) {
 
   core::YamlConfiguration yaml_config(test_repo, test_repo, content_repo, stream_factory, configuration, args.test_file);
 
-  std::shared_ptr<core::Processor> proc = yaml_config.getRoot()->findProcessorByName("invoke");
+  auto root = yaml_config.getRoot();
+  const auto proc = root->findProcessorByName("invoke");
   assert(proc != nullptr);
 
-  const auto inv = std::dynamic_pointer_cast<minifi::processors::InvokeHTTP>(proc);
+  const auto inv = dynamic_cast<minifi::processors::InvokeHTTP*>(proc);
   assert(inv != nullptr);
   std::string url;
   inv->getProperty(minifi::processors::InvokeHTTP::URL.getName(), url);
diff --git a/extensions/http-curl/tests/C2VerifyServeResults.cpp b/extensions/http-curl/tests/C2VerifyServeResults.cpp
index 67097dd..5763964 100644
--- a/extensions/http-curl/tests/C2VerifyServeResults.cpp
+++ b/extensions/http-curl/tests/C2VerifyServeResults.cpp
@@ -59,10 +59,10 @@ class VerifyC2Server : public HTTPIntegrationBase {
   }
 
   void queryRootProcessGroup(std::shared_ptr<core::ProcessGroup> pg) override {
-    std::shared_ptr<core::Processor> proc = pg->findProcessorByName("invoke");
+    auto proc = pg->findProcessorByName("invoke");
     assert(proc != nullptr);
 
-    std::shared_ptr<minifi::processors::InvokeHTTP> inv = std::dynamic_pointer_cast<minifi::processors::InvokeHTTP>(proc);
+    auto inv = dynamic_cast<minifi::processors::InvokeHTTP*>(proc);
 
     assert(inv != nullptr);
     std::string url;
diff --git a/extensions/http-curl/tests/ControllerServiceIntegrationTests.cpp b/extensions/http-curl/tests/ControllerServiceIntegrationTests.cpp
index 0a00fec..8397697 100644
--- a/extensions/http-curl/tests/ControllerServiceIntegrationTests.cpp
+++ b/extensions/http-curl/tests/ControllerServiceIntegrationTests.cpp
@@ -82,9 +82,9 @@ int main(int argc, char **argv) {
 
   core::YamlConfiguration yaml_config(test_repo, test_repo, content_repo, stream_factory, configuration, args.test_file);
 
-  std::shared_ptr<core::ProcessGroup> pg(yaml_config.getRoot());
+  auto pg = yaml_config.getRoot();
 
-  std::shared_ptr<core::controller::StandardControllerServiceProvider> provider = std::make_shared<core::controller::StandardControllerServiceProvider>(map, pg, std::make_shared<minifi::Configure>());
+  auto provider = std::make_shared<core::controller::StandardControllerServiceProvider>(map, pg.get(), std::make_shared<minifi::Configure>());
   std::shared_ptr<core::controller::ControllerServiceNode> mockNode = pg->findControllerService("MockItLikeIts1995");
   assert(mockNode != nullptr);
   mockNode->enable();
diff --git a/extensions/http-curl/tests/VerifyInvokeHTTP.h b/extensions/http-curl/tests/VerifyInvokeHTTP.h
index aec25b1..b9c2a3d 100644
--- a/extensions/http-curl/tests/VerifyInvokeHTTP.h
+++ b/extensions/http-curl/tests/VerifyInvokeHTTP.h
@@ -69,7 +69,7 @@ class VerifyInvokeHTTP : public HTTPIntegrationBase {
 
     const auto stateController = components[0];
     assert(stateController);
-    const auto processorController = std::dynamic_pointer_cast<minifi::state::ProcessorController>(stateController);
+    const auto processorController = dynamic_cast<minifi::state::ProcessorController*>(stateController);
     assert(processorController);
     auto proc = processorController->getProcessor();
     proc->setProperty(property, value);
@@ -89,7 +89,7 @@ class VerifyInvokeHTTP : public HTTPIntegrationBase {
     content_repo->initialize(configuration);
     std::shared_ptr<minifi::io::StreamFactory> stream_factory = minifi::io::StreamFactory::getInstance(configuration);
     auto yaml_ptr = std::make_unique<core::YamlConfiguration>(test_repo, test_repo, content_repo, stream_factory, configuration, flow_yml_path);
-    flowController_ = std::make_shared<minifi::FlowController>(test_repo, test_flow_repo, configuration, std::move(yaml_ptr), content_repo, DEFAULT_ROOT_GROUP_NAME);
+    flowController_ = std::make_unique<minifi::FlowController>(test_repo, test_flow_repo, configuration, std::move(yaml_ptr), content_repo, DEFAULT_ROOT_GROUP_NAME);
     flowController_->load();
 
     std::string url = scheme + "://localhost:" + getWebPort() + *path_;
diff --git a/extensions/http-curl/tests/unit/InvokeHTTPTests.cpp b/extensions/http-curl/tests/unit/InvokeHTTPTests.cpp
index 489efd3..b8213c5 100644
--- a/extensions/http-curl/tests/unit/InvokeHTTPTests.cpp
+++ b/extensions/http-curl/tests/unit/InvokeHTTPTests.cpp
@@ -71,8 +71,8 @@ TEST_CASE("HTTPTestsWithNoResourceClaimPOST", "[httptest1]") {
   utils::Identifier invokehttp_uuid = invokehttp->getUUID();
   REQUIRE(invokehttp_uuid);
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(invokehttp);
-  std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
+  auto node = std::make_shared<core::ProcessorNode>(invokehttp.get());
+  auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
 
   context->setProperty(org::apache::nifi::minifi::processors::InvokeHTTP::Method, "POST");
   context->setProperty(org::apache::nifi::minifi::processors::InvokeHTTP::URL, TestHTTPServer::URL);
@@ -81,13 +81,13 @@ TEST_CASE("HTTPTestsWithNoResourceClaimPOST", "[httptest1]") {
 
   invokehttp->incrementActiveTasks();
   invokehttp->setScheduledState(core::ScheduledState::RUNNING);
-  std::shared_ptr<core::ProcessSessionFactory> factory2 = std::make_shared<core::ProcessSessionFactory>(context);
+  auto factory2 = std::make_shared<core::ProcessSessionFactory>(context);
   invokehttp->onSchedule(context, factory2);
   invokehttp->onTrigger(context, session);
 
   auto reporter = session->getProvenanceReporter();
   auto records = reporter->getEvents();
-  std::shared_ptr<core::FlowFile> record = session->get();
+  auto record = session->get();
   REQUIRE(record == nullptr);
   REQUIRE(records.size() == 0);
 
@@ -115,7 +115,7 @@ TEST_CASE("HTTPTestsWithResourceClaimPOST", "[httptest1]") {
 
   LogTestController::getInstance().setDebug<org::apache::nifi::minifi::processors::InvokeHTTP>();
 
-  std::shared_ptr<TestRepository> repo = std::make_shared<TestRepository>();
+  auto repo = std::make_shared<TestRepository>();
 
   std::shared_ptr<core::Processor> listenhttp = std::make_shared<org::apache::nifi::minifi::processors::ListenHTTP>("listenhttp");
   listenhttp->initialize();
@@ -133,27 +133,27 @@ TEST_CASE("HTTPTestsWithResourceClaimPOST", "[httptest1]") {
   std::shared_ptr<core::ContentRepository> content_repo = std::make_shared<core::repository::VolatileContentRepository>();
   content_repo->initialize(configuration);
 
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(repo, content_repo, "getfileCreate2Connection");
+  auto connection = std::make_shared<minifi::Connection>(repo, content_repo, "getfileCreate2Connection");
   connection->addRelationship(core::Relationship("success", "description"));
 
-  std::shared_ptr<minifi::Connection> connection2 = std::make_shared<minifi::Connection>(repo, content_repo, "listenhttp");
+  auto connection2 = std::make_shared<minifi::Connection>(repo, content_repo, "listenhttp");
 
   connection2->addRelationship(core::Relationship("No Retry", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(listenhttp);
+  connection->setSource(listenhttp.get());
   connection->setSourceUUID(invokehttp_uuid);
   connection->setDestinationUUID(processoruuid);
   connection2->setSourceUUID(processoruuid);
 
-  listenhttp->addConnection(connection);
-  invokehttp->addConnection(connection);
-  invokehttp->addConnection(connection2);
+  listenhttp->addConnection(connection.get());
+  invokehttp->addConnection(connection.get());
+  invokehttp->addConnection(connection2.get());
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(listenhttp);
-  std::shared_ptr<core::ProcessorNode> node2 = std::make_shared<core::ProcessorNode>(invokehttp);
-  std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
-  std::shared_ptr<core::ProcessContext> context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
+  auto node = std::make_shared<core::ProcessorNode>(listenhttp.get());
+  auto node2 = std::make_shared<core::ProcessorNode>(invokehttp.get());
+  auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
+  auto context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
   context->setProperty(org::apache::nifi::minifi::processors::ListenHTTP::Port, "8680");
   context->setProperty(org::apache::nifi::minifi::processors::ListenHTTP::BasePath, "/testytesttest");
 
@@ -164,13 +164,13 @@ TEST_CASE("HTTPTestsWithResourceClaimPOST", "[httptest1]") {
 
   REQUIRE(listenhttp->getName() == "listenhttp");
 
-  std::shared_ptr<core::ProcessSessionFactory> factory = std::make_shared<core::ProcessSessionFactory>(context);
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
 
   std::shared_ptr<core::FlowFile> record;
 
   invokehttp->incrementActiveTasks();
   invokehttp->setScheduledState(core::ScheduledState::RUNNING);
-  std::shared_ptr<core::ProcessSessionFactory> factory2 = std::make_shared<core::ProcessSessionFactory>(context2);
+  auto factory2 = std::make_shared<core::ProcessSessionFactory>(context2);
   invokehttp->onSchedule(context2, factory2);
   invokehttp->onTrigger(context2, session2);
 
diff --git a/extensions/jni/ExecuteJavaProcessor.cpp b/extensions/jni/ExecuteJavaProcessor.cpp
index 2f09213..5f16a75 100644
--- a/extensions/jni/ExecuteJavaProcessor.cpp
+++ b/extensions/jni/ExecuteJavaProcessor.cpp
@@ -155,7 +155,7 @@ void ExecuteJavaProcessor::onSchedule(const std::shared_ptr<core::ProcessContext
   jpc.nifi_processor_ = clazzInstance;
   jpc.context_ = context;
   jpc.clazz_ = spn.getReference();
-  jpc.processor_ = shared_from_this();
+  jpc.processor_ = this;
   jpc.cslookup_ = init_context_.lookup_ref_;
 
   java_servicer_->setReference<minifi::jni::JniProcessContext>(env, context_instance_, &jpc);
diff --git a/extensions/jni/jvm/JniProcessContext.h b/extensions/jni/jvm/JniProcessContext.h
index c1a05ff..b618489 100644
--- a/extensions/jni/jvm/JniProcessContext.h
+++ b/extensions/jni/jvm/JniProcessContext.h
@@ -47,7 +47,7 @@ struct JniProcessContext {
   jclass clazz_;
   jobject nifi_processor_;
   jobject cslookup_;
-  std::shared_ptr<core::Processor> processor_;
+  core::Processor* processor_;
   std::shared_ptr<core::ProcessContext> context_;
 };
 
diff --git a/extensions/libarchive/BinFiles.cpp b/extensions/libarchive/BinFiles.cpp
index 38d617e..e8d6e64 100644
--- a/extensions/libarchive/BinFiles.cpp
+++ b/extensions/libarchive/BinFiles.cpp
@@ -346,10 +346,10 @@ void BinFiles::restore(const std::shared_ptr<core::FlowFile>& flowFile) {
   file_store_.put(flowFile);
 }
 
-std::set<std::shared_ptr<core::Connectable>> BinFiles::getOutGoingConnections(const std::string &relationship) const {
+std::set<core::Connectable*> BinFiles::getOutGoingConnections(const std::string &relationship) {
   auto result = core::Connectable::getOutGoingConnections(relationship);
   if (relationship == Self.getName()) {
-    result.insert(std::static_pointer_cast<core::Connectable>(std::const_pointer_cast<core::Processor>(shared_from_this())));
+    result.insert(this);
   }
   return result;
 }
diff --git a/extensions/libarchive/BinFiles.h b/extensions/libarchive/BinFiles.h
index e23e622..6ca4497 100644
--- a/extensions/libarchive/BinFiles.h
+++ b/extensions/libarchive/BinFiles.h
@@ -244,7 +244,7 @@ class BinFiles : public core::Processor {
 
   void restore(const std::shared_ptr<core::FlowFile>& flowFile) override;
 
-  std::set<std::shared_ptr<core::Connectable>> getOutGoingConnections(const std::string &relationship) const override;
+  std::set<core::Connectable*> getOutGoingConnections(const std::string &relationship) override;
 
  protected:
   // Allows general pre-processing of a flow file before it is offered to a bin. This is called before getGroupId().
diff --git a/extensions/librdkafka/ConsumeKafka.cpp b/extensions/librdkafka/ConsumeKafka.cpp
index 7a41d0a..555d6e6 100644
--- a/extensions/librdkafka/ConsumeKafka.cpp
+++ b/extensions/librdkafka/ConsumeKafka.cpp
@@ -20,8 +20,11 @@
 #include <algorithm>
 #include <limits>
 
+#include "controllers/SSLContextService.h"
+#include "core/ProcessSession.h"
 #include "core/PropertyValidation.h"
 #include "core/Resource.h"
+#include "FlowFileRecord.h"
 #include "utils/ProcessorConfigUtils.h"
 #include "utils/gsl.h"
 
diff --git a/extensions/librdkafka/ConsumeKafka.h b/extensions/librdkafka/ConsumeKafka.h
index e8610e0..bb7ebee 100644
--- a/extensions/librdkafka/ConsumeKafka.h
+++ b/extensions/librdkafka/ConsumeKafka.h
@@ -25,6 +25,7 @@
 
 #include "KafkaProcessorBase.h"
 #include "core/logging/LoggerConfiguration.h"
+#include "io/StreamPipe.h"
 #include "rdkafka.h"
 #include "rdkafka_utils.h"
 #include "KafkaConnection.h"
@@ -33,6 +34,9 @@ namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
+
+class FlowFileRecord;
+
 namespace processors {
 
 class ConsumeKafka : public KafkaProcessorBase {
diff --git a/extensions/librdkafka/KafkaProcessorBase.cpp b/extensions/librdkafka/KafkaProcessorBase.cpp
index d54404c..0273288 100644
--- a/extensions/librdkafka/KafkaProcessorBase.cpp
+++ b/extensions/librdkafka/KafkaProcessorBase.cpp
@@ -21,6 +21,7 @@
 
 #include "rdkafka_utils.h"
 #include "utils/ProcessorConfigUtils.h"
+#include "controllers/SSLContextService.h"
 
 namespace org::apache::nifi::minifi::processors {
 
diff --git a/extensions/opencv/CaptureRTSPFrame.cpp b/extensions/opencv/CaptureRTSPFrame.cpp
index ca4b676..5b11ab7 100644
--- a/extensions/opencv/CaptureRTSPFrame.cpp
+++ b/extensions/opencv/CaptureRTSPFrame.cpp
@@ -17,6 +17,8 @@
 #include <set>
 
 #include "CaptureRTSPFrame.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/opencv/CaptureRTSPFrame.h b/extensions/opencv/CaptureRTSPFrame.h
index d9d6463..3b9c72a 100644
--- a/extensions/opencv/CaptureRTSPFrame.h
+++ b/extensions/opencv/CaptureRTSPFrame.h
@@ -26,7 +26,9 @@
 #include <string>
 #include <opencv2/opencv.hpp>
 
+#include "core/logging/LoggerConfiguration.h"
 #include "core/Processor.h"
+#include "io/StreamPipe.h"
 #include "utils/gsl.h"
 #include "utils/Export.h"
 
diff --git a/extensions/opencv/FrameIO.h b/extensions/opencv/FrameIO.h
index 87e971d..75c6a90 100644
--- a/extensions/opencv/FrameIO.h
+++ b/extensions/opencv/FrameIO.h
@@ -22,6 +22,7 @@
 #include <memory>
 #include <string>
 
+#include "io/StreamPipe.h"
 #include "utils/gsl.h"
 
 namespace org {
diff --git a/extensions/opencv/MotionDetector.cpp b/extensions/opencv/MotionDetector.cpp
index 201a40e..05f94b0 100644
--- a/extensions/opencv/MotionDetector.cpp
+++ b/extensions/opencv/MotionDetector.cpp
@@ -21,6 +21,8 @@
 
 #include "MotionDetector.h"
 #include "FrameIO.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/opencv/MotionDetector.h b/extensions/opencv/MotionDetector.h
index 0297daf..68ceb6e 100644
--- a/extensions/opencv/MotionDetector.h
+++ b/extensions/opencv/MotionDetector.h
@@ -21,6 +21,7 @@
 #include <memory>
 #include <string>
 
+#include "core/logging/LoggerConfiguration.h"
 #include "core/Processor.h"
 #include "opencv2/opencv.hpp"
 #include "opencv2/imgproc.hpp"
diff --git a/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.cpp b/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.cpp
index 94da82d..5c76d60 100644
--- a/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.cpp
+++ b/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.cpp
@@ -47,6 +47,7 @@ extern "C" {
 #include "core/FlowFile.h"
 #include "core/logging/Logger.h"
 #include "core/ProcessContext.h"
+#include "core/ProcessSessionFactory.h"
 #include "core/Relationship.h"
 #include "core/Resource.h"
 #include "io/BufferStream.h"
diff --git a/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.h b/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.h
index 47d3b71..6b84ef9 100644
--- a/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.h
+++ b/extensions/openwsman/processors/SourceInitiatedSubscriptionListener.h
@@ -119,7 +119,7 @@ class SourceInitiatedSubscriptionListener : public core::Processor {
 
   std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<SourceInitiatedSubscriptionListener>::getLogger();
 
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
 
   std::shared_ptr<core::ProcessSessionFactory> session_factory_;
 
diff --git a/extensions/pdh/PerformanceDataMonitor.cpp b/extensions/pdh/PerformanceDataMonitor.cpp
index b317ec4..71c9618 100644
--- a/extensions/pdh/PerformanceDataMonitor.cpp
+++ b/extensions/pdh/PerformanceDataMonitor.cpp
@@ -26,6 +26,8 @@
 #include "utils/StringUtils.h"
 #include "utils/JsonCallback.h"
 #include "utils/OpenTelemetryLogDataModelUtils.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/pdh/PerformanceDataMonitor.h b/extensions/pdh/PerformanceDataMonitor.h
index 9be771f..a3c5fd2 100644
--- a/extensions/pdh/PerformanceDataMonitor.h
+++ b/extensions/pdh/PerformanceDataMonitor.h
@@ -24,6 +24,7 @@
 #include <utility>
 #include <vector>
 
+#include "core/logging/LoggerConfiguration.h"
 #include "core/Processor.h"
 
 #include "rapidjson/stream.h"
diff --git a/extensions/rocksdb-repos/FlowFileRepository.cpp b/extensions/rocksdb-repos/FlowFileRepository.cpp
index 5628885..1d29e63 100644
--- a/extensions/rocksdb-repos/FlowFileRepository.cpp
+++ b/extensions/rocksdb-repos/FlowFileRepository.cpp
@@ -175,12 +175,12 @@ void FlowFileRepository::prune_stored_flowfiles() {
       auto claim = eventRead->getResourceClaim();
       if (claim) claim->increaseFlowFileRecordOwnedCount();
       bool found = false;
-      auto search = containers.find(containerId.to_string());
-      found = (search != containers.end());
+      auto search = containers_.find(containerId.to_string());
+      found = (search != containers_.end());
       if (!found) {
         // for backward compatibility
-        search = connectionMap.find(containerId.to_string());
-        found = (search != connectionMap.end());
+        search = connection_map_.find(containerId.to_string());
+        found = (search != connection_map_.end());
       }
       if (found) {
         logger_->log_debug("Found connection for %s, path %s ", containerId.to_string(), eventRead->getContentFullPath());
diff --git a/extensions/rocksdb-repos/FlowFileRepository.h b/extensions/rocksdb-repos/FlowFileRepository.h
index e79711e..ef87bed 100644
--- a/extensions/rocksdb-repos/FlowFileRepository.h
+++ b/extensions/rocksdb-repos/FlowFileRepository.h
@@ -59,7 +59,7 @@ constexpr auto FLOWFILE_REPOSITORY_RETRY_INTERVAL_INCREMENTS = std::chrono::mill
  * Flow File repository
  * Design: Extends Repository and implements the run function, using rocksdb as the primary substrate.
  */
-class FlowFileRepository : public core::Repository, public std::enable_shared_from_this<FlowFileRepository> {
+class FlowFileRepository : public core::Repository {
  public:
   static constexpr const char* ENCRYPTION_KEY_NAME = "nifi.flowfile.repository.encryption.key";
   // Constructor
@@ -75,24 +75,28 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
                      int64_t maxPartitionBytes = MAX_FLOWFILE_REPOSITORY_STORAGE_SIZE,
                      std::chrono::milliseconds purgePeriod = FLOWFILE_REPOSITORY_PURGE_PERIOD)
       : core::SerializableComponent(repo_name),
-        Repository(repo_name.length() > 0 ? repo_name : core::getClassName<FlowFileRepository>(), directory, maxPartitionMillis, maxPartitionBytes, purgePeriod),
-        checkpoint_dir_(checkpoint_dir),
+        Repository(repo_name.length() > 0 ? repo_name : core::getClassName<FlowFileRepository>(), std::move(directory), maxPartitionMillis, maxPartitionBytes, purgePeriod),
+        checkpoint_dir_(std::move(checkpoint_dir)),
         content_repo_(nullptr),
         checkpoint_(nullptr),
         logger_(logging::LoggerFactory<FlowFileRepository>::getLogger()) {
-    db_ = NULL;
+    db_ = nullptr;
   }
 
-  virtual bool isNoop() {
+  ~FlowFileRepository() override {
+    stop();
+  }
+
+  bool isNoop() override {
     return false;
   }
 
-  virtual void flush();
+  void flush() override;
 
   virtual void printStats();
 
   // initialize
-  virtual bool initialize(const std::shared_ptr<Configure> &configure) {
+  bool initialize(const std::shared_ptr<Configure> &configure) override {
     config_ = configure;
     std::string value;
 
@@ -145,9 +149,9 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
     }
   }
 
-  virtual void run();
+  void run() override;
 
-  virtual bool Put(std::string key, const uint8_t *buf, size_t bufLen) {
+  bool Put(std::string key, const uint8_t *buf, size_t bufLen) override {
     // persistent to the DB
     auto opendb = db_->open();
     if (!opendb) {
@@ -158,7 +162,7 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
     return ExecuteWithRetry(operation);
   }
 
-  virtual bool MultiPut(const std::vector<std::pair<std::string, std::unique_ptr<minifi::io::BufferStream>>>& data) {
+  bool MultiPut(const std::vector<std::pair<std::string, std::unique_ptr<minifi::io::BufferStream>>>& data) override {
     auto opendb = db_->open();
     if (!opendb) {
       return false;
@@ -182,7 +186,7 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
    * Deletes the key
    * @return status of the delete operation
    */
-  virtual bool Delete(std::string key) {
+  bool Delete(std::string key) override {
     keys_to_delete.enqueue(key);
     return true;
   }
@@ -190,7 +194,7 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
    * Sets the value from the provided key
    * @return status of the get operation.
    */
-  virtual bool Get(const std::string &key, std::string &value) {
+  bool Get(const std::string &key, std::string &value) override {
     auto opendb = db_->open();
     if (!opendb) {
       return false;
@@ -198,9 +202,9 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
     return opendb->Get(rocksdb::ReadOptions(), key, &value).ok();
   }
 
-  virtual void loadComponent(const std::shared_ptr<core::ContentRepository> &content_repo);
+  void loadComponent(const std::shared_ptr<core::ContentRepository> &content_repo) override;
 
-  void start() {
+  void start() override {
     if (this->purge_period_ <= std::chrono::milliseconds(0)) {
       return;
     }
@@ -208,7 +212,7 @@ class FlowFileRepository : public core::Repository, public std::enable_shared_fr
       return;
     }
     running_ = true;
-    thread_ = std::thread(&FlowFileRepository::run, shared_from_this());
+    thread_ = std::thread(&FlowFileRepository::run, this);
     logger_->log_debug("%s Repository Monitor Thread Start", getName());
   }
 
diff --git a/extensions/rocksdb-repos/ProvenanceRepository.h b/extensions/rocksdb-repos/ProvenanceRepository.h
index 27bc7f1..068d14c 100644
--- a/extensions/rocksdb-repos/ProvenanceRepository.h
+++ b/extensions/rocksdb-repos/ProvenanceRepository.h
@@ -58,6 +58,10 @@ class ProvenanceRepository : public core::Repository, public std::enable_shared_
     db_ = nullptr;
   }
 
+  ~ProvenanceRepository() override {
+    stop();
+  }
+
   void printStats();
 
   bool isNoop() override {
diff --git a/extensions/script/python/ExecutePythonProcessor.cpp b/extensions/script/python/ExecutePythonProcessor.cpp
index 0c537e9..bc96168 100644
--- a/extensions/script/python/ExecutePythonProcessor.cpp
+++ b/extensions/script/python/ExecutePythonProcessor.cpp
@@ -92,9 +92,8 @@ void ExecutePythonProcessor::initialize() {
 void ExecutePythonProcessor::initalizeThroughScriptEngine() {
   appendPathForImportModules();
   python_script_engine_->eval(script_to_exec_);
-  auto shared_this = shared_from_this();
-  python_script_engine_->describe(shared_this);
-  python_script_engine_->onInitialize(shared_this);
+  python_script_engine_->describe(this);
+  python_script_engine_->onInitialize(this);
   processor_initialized_ = true;
 }
 
diff --git a/extensions/script/python/PythonObjectFactory.h b/extensions/script/python/PythonObjectFactory.h
index 1c4ac42..d6e84cf 100644
--- a/extensions/script/python/PythonObjectFactory.h
+++ b/extensions/script/python/PythonObjectFactory.h
@@ -21,6 +21,7 @@
 #include <vector>
 #include <string>
 #include <memory>
+#include <utility>
 
 #include "core/ClassLoader.h"
 #include "ExecutePythonProcessor.h"
@@ -30,23 +31,31 @@
 
 class PythonObjectFactory : public org::apache::nifi::minifi::core::DefautObjectFactory<org::apache::nifi::minifi::python::processors::ExecutePythonProcessor> {
  public:
-  explicit PythonObjectFactory(const std::string &file, const std::string &name)
-      : file_(file),
-        name_(name) {
+  explicit PythonObjectFactory(std::string file, std::string name)
+      : file_(std::move(file)),
+        name_(std::move(name)) {
   }
 
-  std::shared_ptr<org::apache::nifi::minifi::core::CoreComponent> create(const std::string &name) override {
-    auto ptr = std::static_pointer_cast<org::apache::nifi::minifi::python::processors::ExecutePythonProcessor>(DefautObjectFactory::create(name));
+  std::unique_ptr<org::apache::nifi::minifi::core::CoreComponent> create(const std::string &name) override {
+    auto obj = DefautObjectFactory::create(name);
+    auto ptr = org::apache::nifi::minifi::utils::dynamic_unique_cast<org::apache::nifi::minifi::python::processors::ExecutePythonProcessor>(std::move(obj));
+    if (ptr == nullptr) {
+      return nullptr;
+    }
     ptr->initialize();
     ptr->setProperty(org::apache::nifi::minifi::python::processors::ExecutePythonProcessor::ScriptFile, file_);
-    return std::static_pointer_cast<org::apache::nifi::minifi::core::CoreComponent>(ptr);
+    return ptr;
   }
 
-  std::shared_ptr<org::apache::nifi::minifi::core::CoreComponent> create(const std::string &name, const org::apache::nifi::minifi::utils::Identifier &uuid) override {
-    auto ptr = std::static_pointer_cast<org::apache::nifi::minifi::python::processors::ExecutePythonProcessor>(DefautObjectFactory::create(name, uuid));
+  std::unique_ptr<org::apache::nifi::minifi::core::CoreComponent> create(const std::string &name, const org::apache::nifi::minifi::utils::Identifier &uuid) override {
+    auto obj = DefautObjectFactory::create(name, uuid);
+    auto ptr = org::apache::nifi::minifi::utils::dynamic_unique_cast<org::apache::nifi::minifi::python::processors::ExecutePythonProcessor>(std::move(obj));
+    if (ptr == nullptr) {
+      return nullptr;
+    }
     ptr->initialize();
     ptr->setProperty(org::apache::nifi::minifi::python::processors::ExecutePythonProcessor::ScriptFile, file_);
-    return std::static_pointer_cast<org::apache::nifi::minifi::core::CoreComponent>(ptr);
+    return ptr;
   }
 
   org::apache::nifi::minifi::core::CoreComponent* createRaw(const std::string &name) override {
diff --git a/extensions/script/python/PythonProcessor.cpp b/extensions/script/python/PythonProcessor.cpp
index c681231..88d6d3f 100644
--- a/extensions/script/python/PythonProcessor.cpp
+++ b/extensions/script/python/PythonProcessor.cpp
@@ -32,33 +32,23 @@ namespace python {
 namespace py = pybind11;
 namespace core = org::apache::nifi::minifi::core;
 
-PythonProcessor::PythonProcessor(std::shared_ptr<core::Processor> proc) {
-  processor_ = std::dynamic_pointer_cast<python::processors::ExecutePythonProcessor>(proc);
+PythonProcessor::PythonProcessor(core::Processor* proc) {
+  processor_ = dynamic_cast<python::processors::ExecutePythonProcessor*>(proc);
+  gsl_Expects(processor_);
 }
 
 void PythonProcessor::setSupportsDynamicProperties() {
-  if (!processor_) {
-    throw std::runtime_error("Access of Processor after it has been released");
-  }
-
-  std::dynamic_pointer_cast<python::processors::ExecutePythonProcessor>(processor_)->setSupportsDynamicProperties();
+  processor_->setSupportsDynamicProperties();
 }
 
 void PythonProcessor::setDecription(const std::string &desc) {
-  if (!processor_) {
-    throw std::runtime_error("Access of Processor after it has been released");
-  }
-
-  std::dynamic_pointer_cast<python::processors::ExecutePythonProcessor>(processor_)->setDescription(desc);
+  processor_->setDescription(desc);
 }
 
 void PythonProcessor::addProperty(const std::string &name, const std::string &description, const std::string &defaultvalue, bool required, bool el) {
-  std::dynamic_pointer_cast<python::processors::ExecutePythonProcessor>(processor_)->addProperty(name, description, defaultvalue, required, el);
+  processor_->addProperty(name, description, defaultvalue, required, el);
 }
 
-void PythonProcessor::releaseCoreResources() {
-  processor_.reset();
-}
 } /* namespace python */
 } /* namespace minifi */
 } /* namespace nifi */
diff --git a/extensions/script/python/PythonProcessor.h b/extensions/script/python/PythonProcessor.h
index bb6026a..f8616f1 100644
--- a/extensions/script/python/PythonProcessor.h
+++ b/extensions/script/python/PythonProcessor.h
@@ -29,6 +29,10 @@ namespace nifi {
 namespace minifi {
 namespace python {
 
+namespace processors {
+class ExecutePythonProcessor;
+}
+
 namespace py = pybind11;
 
 /**
@@ -36,25 +40,16 @@ namespace py = pybind11;
  */
 class PythonProcessor {
  public:
-  explicit PythonProcessor(std::shared_ptr<core::Processor> proc);
+  explicit PythonProcessor(core::Processor* proc);
 
   void setSupportsDynamicProperties();
 
   void setDecription(const std::string &desc);
 
   void addProperty(const std::string &name, const std::string &description, const std::string &defaultvalue, bool required, bool el);
-  /**
-   * Sometimes we want to release shared pointers to core resources when
-   * we know they are no longer in need. This method is for those times.
-   *
-   * For example, we do not want to hold on to shared pointers to FlowFiles
-   * after an onTrigger call, because doing so can be very expensive in terms
-   * of repository resources.
-   */
-  void releaseCoreResources();
 
  private:
-  std::shared_ptr<core::Processor> processor_;
+  python::processors::ExecutePythonProcessor* processor_;
 };
 
 } /* namespace python */
diff --git a/extensions/script/python/PythonScriptEngine.h b/extensions/script/python/PythonScriptEngine.h
index cf3cbf8..f9a5070 100644
--- a/extensions/script/python/PythonScriptEngine.h
+++ b/extensions/script/python/PythonScriptEngine.h
@@ -172,13 +172,13 @@ class __attribute__((visibility("default"))) PythonScriptEngine : public script:
     std::shared_ptr<script::ScriptProcessContext> script_context_;
   };
 
-  void onInitialize(const std::shared_ptr<core::Processor> &proc) {
+  void onInitialize(core::Processor* proc) {
     TriggerInit trigger_session;
     auto newproc = convertProcessor(proc);
     call("onInitialize", newproc);
   }
 
-  void describe(const std::shared_ptr<core::Processor> &proc) {
+  void describe(core::Processor* proc) {
     TriggerInit trigger_session;
     auto newproc = convertProcessor(proc);
     callRequiredFunction("describe", newproc);
@@ -223,7 +223,7 @@ class __attribute__((visibility("default"))) PythonScriptEngine : public script:
     return std::make_shared<script::ScriptProcessContext>(context);
   }
 
-  std::shared_ptr<python::PythonProcessor> convertProcessor(const std::shared_ptr<core::Processor> &proc) {
+  std::shared_ptr<python::PythonProcessor> convertProcessor(core::Processor* proc) {
     return std::make_shared<python::PythonProcessor>(proc);
   }
 
diff --git a/extensions/sftp/processors/ListSFTP.h b/extensions/sftp/processors/ListSFTP.h
index 91e196b..d2f7ac5 100644
--- a/extensions/sftp/processors/ListSFTP.h
+++ b/extensions/sftp/processors/ListSFTP.h
@@ -106,7 +106,7 @@ class ListSFTP : public SFTPProcessorBase {
     return true;
   }
 
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   std::string listing_strategy_;
   bool search_recursively_;
   bool follow_symlink_;
diff --git a/extensions/sftp/tests/ListSFTPTests.cpp b/extensions/sftp/tests/ListSFTPTests.cpp
index 9732d87..dc7765c 100644
--- a/extensions/sftp/tests/ListSFTPTests.cpp
+++ b/extensions/sftp/tests/ListSFTPTests.cpp
@@ -555,7 +555,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Timestamps r
   testController.runSession(plan, true);
 
   std::unordered_map<std::string, std::string> state;
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("nifi_test" == state.at("remote_path"));
@@ -577,7 +577,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Timestamps r
 
   testController.runSession(plan, true);
 
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("nifi_test" == state.at("remote_path"));
@@ -603,7 +603,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Timestamps r
   REQUIRE(LogTestController::getInstance().contains("key:filename value:file1.ext"));
 
   std::unordered_map<std::string, std::string> state;
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("nifi_test" == state.at("remote_path"));
@@ -620,7 +620,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Timestamps r
 
   testController.runSession(plan, true);
 
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("/nifi_test" == state.at("remote_path"));
@@ -857,7 +857,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Entities res
   LogTestController::getInstance().resetStream(LogTestController::getInstance().log_output);
 
   std::unordered_map<std::string, std::string> state;
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("nifi_test" == state.at("remote_path"));
@@ -870,7 +870,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Entities res
 
   testController.runSession(plan, true);
 
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("nifi_test" == state.at("remote_path"));
@@ -904,7 +904,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Entities res
   REQUIRE(LogTestController::getInstance().contains("key:filename value:file1.ext"));
 
   std::unordered_map<std::string, std::string> state;
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("nifi_test" == state.at("remote_path"));
@@ -921,7 +921,7 @@ TEST_CASE_METHOD(PersistentListSFTPTestsFixture, "ListSFTP Tracking Entities res
 
   testController.runSession(plan, true);
 
-  REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*list_sftp)->get(state));
+  REQUIRE(plan->getProcessContextForProcessor(list_sftp)->getStateManager()->get(state));
   REQUIRE("localhost" == state.at("hostname"));
   REQUIRE("nifiuser" == state.at("username"));
   REQUIRE("/nifi_test" == state.at("remote_path"));
diff --git a/extensions/splunk/PutSplunkHTTP.cpp b/extensions/splunk/PutSplunkHTTP.cpp
index 85e550a..a58ef71 100644
--- a/extensions/splunk/PutSplunkHTTP.cpp
+++ b/extensions/splunk/PutSplunkHTTP.cpp
@@ -23,6 +23,8 @@
 
 #include "SplunkAttributes.h"
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 #include "utils/StringUtils.h"
 #include "client/HTTPClient.h"
diff --git a/extensions/splunk/QuerySplunkIndexingStatus.cpp b/extensions/splunk/QuerySplunkIndexingStatus.cpp
index 8eebb0f..91f174a 100644
--- a/extensions/splunk/QuerySplunkIndexingStatus.cpp
+++ b/extensions/splunk/QuerySplunkIndexingStatus.cpp
@@ -24,6 +24,8 @@
 
 #include "SplunkAttributes.h"
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 #include "client/HTTPClient.h"
 #include "utils/HTTPClient.h"
diff --git a/extensions/splunk/SplunkHECProcessor.cpp b/extensions/splunk/SplunkHECProcessor.cpp
index 4e315d0..bf7702b 100644
--- a/extensions/splunk/SplunkHECProcessor.cpp
+++ b/extensions/splunk/SplunkHECProcessor.cpp
@@ -16,6 +16,7 @@
  */
 
 #include "SplunkHECProcessor.h"
+#include "core/ProcessContext.h"
 #include "client/HTTPClient.h"
 #include "utils/HTTPClient.h"
 
diff --git a/extensions/splunk/SplunkHECProcessor.h b/extensions/splunk/SplunkHECProcessor.h
index f931b26..ab56f00 100644
--- a/extensions/splunk/SplunkHECProcessor.h
+++ b/extensions/splunk/SplunkHECProcessor.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <memory>
 
+#include "controllers/SSLContextService.h"
 #include "core/Processor.h"
 
 
diff --git a/extensions/sql/processors/QueryDatabaseTable.h b/extensions/sql/processors/QueryDatabaseTable.h
index 70a9004..1e298cd 100644
--- a/extensions/sql/processors/QueryDatabaseTable.h
+++ b/extensions/sql/processors/QueryDatabaseTable.h
@@ -81,7 +81,7 @@ class QueryDatabaseTable: public SQLProcessor, public FlowFileSource {
 
   bool saveState();
 
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   std::string table_name_;
   std::unordered_set<sql::SQLColumnIdentifier> return_columns_;
   std::string queried_columns_;
diff --git a/extensions/standard-processors/processors/AttributesToJSON.cpp b/extensions/standard-processors/processors/AttributesToJSON.cpp
index ec6c0ff..7f8b350 100644
--- a/extensions/standard-processors/processors/AttributesToJSON.cpp
+++ b/extensions/standard-processors/processors/AttributesToJSON.cpp
@@ -25,6 +25,7 @@
 #include "utils/StringUtils.h"
 #include "utils/ProcessorConfigUtils.h"
 #include "range/v3/algorithm/find.hpp"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/standard-processors/processors/AttributesToJSON.h b/extensions/standard-processors/processors/AttributesToJSON.h
index e5014ba..d04cd2c 100644
--- a/extensions/standard-processors/processors/AttributesToJSON.h
+++ b/extensions/standard-processors/processors/AttributesToJSON.h
@@ -28,9 +28,11 @@
 #include <regex>
 
 #include "rapidjson/document.h"
+#include "core/FlowFile.h"
+#include "core/logging/LoggerConfiguration.h"
 #include "core/Processor.h"
 #include "core/Property.h"
-#include "core/logging/Logger.h"
+#include "io/StreamPipe.h"
 #include "utils/Enum.h"
 #include "utils/Export.h"
 
diff --git a/extensions/standard-processors/processors/DefragmentText.cpp b/extensions/standard-processors/processors/DefragmentText.cpp
index 0c5d0ae..fda9dc0 100644
--- a/extensions/standard-processors/processors/DefragmentText.cpp
+++ b/extensions/standard-processors/processors/DefragmentText.cpp
@@ -20,6 +20,8 @@
 #include <vector>
 #include <utility>
 
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 #include "serialization/PayloadSerializer.h"
 #include "TextFragmentUtils.h"
@@ -241,10 +243,10 @@ void DefragmentText::restore(const std::shared_ptr<core::FlowFile>& flowFile) {
   flow_file_store_.put(flowFile);
 }
 
-std::set<std::shared_ptr<core::Connectable>> DefragmentText::getOutGoingConnections(const std::string &relationship) const {
+std::set<core::Connectable*> DefragmentText::getOutGoingConnections(const std::string &relationship) {
   auto result = core::Connectable::getOutGoingConnections(relationship);
   if (relationship == Self.getName()) {
-    result.insert(std::static_pointer_cast<core::Connectable>(std::const_pointer_cast<core::Processor>(shared_from_this())));
+    result.insert(this);
   }
   return result;
 }
diff --git a/extensions/standard-processors/processors/DefragmentText.h b/extensions/standard-processors/processors/DefragmentText.h
index a508c73..eef7272 100644
--- a/extensions/standard-processors/processors/DefragmentText.h
+++ b/extensions/standard-processors/processors/DefragmentText.h
@@ -50,7 +50,7 @@ class DefragmentText : public core::Processor {
   void onSchedule(core::ProcessContext* context, core::ProcessSessionFactory* sessionFactory) override;
   void onTrigger(core::ProcessContext* context, core::ProcessSession* session) override;
   void restore(const std::shared_ptr<core::FlowFile>& flowFile) override;
-  std::set<std::shared_ptr<core::Connectable>> getOutGoingConnections(const std::string &relationship) const override;
+  std::set<core::Connectable*> getOutGoingConnections(const std::string &relationship) override;
 
   SMART_ENUM(PatternLocation,
              (END_OF_MESSAGE, "End of Message"),
diff --git a/extensions/standard-processors/processors/GetTCP.cpp b/extensions/standard-processors/processors/GetTCP.cpp
index 56cecaa..0e3e422 100644
--- a/extensions/standard-processors/processors/GetTCP.cpp
+++ b/extensions/standard-processors/processors/GetTCP.cpp
@@ -31,11 +31,13 @@
 #include <string>
 
 #include "io/ClientSocket.h"
+#include "io/StreamFactory.h"
 #include "utils/gsl.h"
 #include "utils/StringUtils.h"
 #include "utils/TimeUtil.h"
 #include "core/ProcessContext.h"
 #include "core/ProcessSession.h"
+#include "core/ProcessSessionFactory.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/standard-processors/processors/GetTCP.h b/extensions/standard-processors/processors/GetTCP.h
index 6e60ed3..5ab1630 100644
--- a/extensions/standard-processors/processors/GetTCP.h
+++ b/extensions/standard-processors/processors/GetTCP.h
@@ -31,6 +31,7 @@
 #include "core/ProcessSession.h"
 #include "core/Core.h"
 #include "concurrentqueue.h"
+#include "io/ClientSocket.h"
 #include "utils/ThreadPool.h"
 #include "core/logging/LoggerConfiguration.h"
 #include "controllers/SSLContextService.h"
@@ -169,10 +170,6 @@ class GetTCPMetrics : public state::response::ResponseNode {
 // GetTCP Class
 class GetTCP : public core::Processor, public state::response::MetricsNodeSource {
  public:
-// Constructor
-  /*!
-   * Create a new processor
-   */
   explicit GetTCP(const std::string& name, const utils::Identifier& uuid = {})
       : Processor(name, uuid),
         running_(false),
@@ -184,8 +181,12 @@ class GetTCP : public core::Processor, public state::response::MetricsNodeSource
         ssl_service_(nullptr) {
     metrics_ = std::make_shared<GetTCPMetrics>();
   }
-// Destructor
-  ~GetTCP() override = default;
+
+  ~GetTCP() override {
+    // thread pool must be shut down first before members it is using are destructed, otherwise segfault is possible
+    client_thread_pool_.shutdown();
+  }
+
 // Processor Name
   EXTENSIONAPI static constexpr char const* ProcessorName = "GetTCP";
 
@@ -245,8 +246,6 @@ class GetTCP : public core::Processor, public state::response::MetricsNodeSource
 
   std::map<std::string, std::future<int>*> live_clients_;
 
-  utils::ThreadPool<int> client_thread_pool_;
-
   moodycamel::ConcurrentQueue<std::unique_ptr<io::Socket>> socket_ring_buffer_;
 
   bool stay_connected_;
@@ -269,10 +268,9 @@ class GetTCP : public core::Processor, public state::response::MetricsNodeSource
 
   std::shared_ptr<minifi::controllers::SSLContextService> ssl_service_;
 
-  // last listing time for root directory ( if recursive, we will consider the root
-  // as the top level time.
-
   std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<GetTCP>::getLogger();
+
+  utils::ThreadPool<int> client_thread_pool_;
 };
 
 }  // namespace processors
diff --git a/extensions/standard-processors/processors/PutUDP.cpp b/extensions/standard-processors/processors/PutUDP.cpp
index b6f0e3a..2f0cac6 100644
--- a/extensions/standard-processors/processors/PutUDP.cpp
+++ b/extensions/standard-processors/processors/PutUDP.cpp
@@ -24,7 +24,6 @@
 #else
 #include <netdb.h>
 #endif /* WIN32 */
-#include <tuple>
 #include <utility>
 
 #include "range/v3/view/join.hpp"
@@ -33,8 +32,9 @@
 #include "utils/gsl.h"
 #include "utils/expected.h"
 #include "utils/net/DNS.h"
-#include "utils/StringUtils.h"
 #include "utils/net/Socket.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 #include "core/logging/LoggerConfiguration.h"
 
diff --git a/extensions/standard-processors/processors/RouteText.cpp b/extensions/standard-processors/processors/RouteText.cpp
index 97fb6c8..93eef74 100644
--- a/extensions/standard-processors/processors/RouteText.cpp
+++ b/extensions/standard-processors/processors/RouteText.cpp
@@ -33,15 +33,17 @@ template<typename It, typename Hash, typename Eq>
 using boyer_moore_searcher = std::boyer_moore_searcher<It, Hash, Eq>;
 #endif
 
+#include "core/ProcessSession.h"
+#include "core/Resource.h"
+#include "io/StreamPipe.h"
 #include "logging/LoggerConfiguration.h"
-#include "utils/ProcessorConfigUtils.h"
-#include "utils/OptionalUtils.h"
 #include "range/v3/view/transform.hpp"
 #include "range/v3/range/conversion.hpp"
 #include "range/v3/view/tail.hpp"
 #include "range/v3/view/join.hpp"
 #include "range/v3/view/cache1.hpp"
-#include "core/Resource.h"
+#include "utils/ProcessorConfigUtils.h"
+#include "utils/OptionalUtils.h"
 
 namespace org::apache::nifi::minifi::processors {
 
diff --git a/extensions/standard-processors/processors/TailFile.h b/extensions/standard-processors/processors/TailFile.h
index 91003ba..9d8ef36 100644
--- a/extensions/standard-processors/processors/TailFile.h
+++ b/extensions/standard-processors/processors/TailFile.h
@@ -178,7 +178,7 @@ class TailFile : public core::Processor {
   static const int BUFFER_SIZE = 512;
 
   std::string delimiter_;  // Delimiter for the data incoming from the tailed file.
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   std::map<std::string, TailState> tail_states_;
   Mode tail_mode_ = Mode::UNDEFINED;
   std::string file_to_tail_;
diff --git a/extensions/standard-processors/tests/integration/SecureSocketGetTCPTest.cpp b/extensions/standard-processors/tests/integration/SecureSocketGetTCPTest.cpp
index 8225811..17a8fa0 100644
--- a/extensions/standard-processors/tests/integration/SecureSocketGetTCPTest.cpp
+++ b/extensions/standard-processors/tests/integration/SecureSocketGetTCPTest.cpp
@@ -86,10 +86,10 @@ class SecureSocketTest : public IntegrationBase {
   }
 
   void queryRootProcessGroup(std::shared_ptr<core::ProcessGroup> pg) override {
-    std::shared_ptr<core::Processor> proc = pg->findProcessorByName("invoke");
+    auto proc = pg->findProcessorByName("invoke");
     assert(proc != nullptr);
 
-    std::shared_ptr<minifi::processors::GetTCP> inv = std::dynamic_pointer_cast<minifi::processors::GetTCP>(proc);
+    auto inv = dynamic_cast<minifi::processors::GetTCP*>(proc);
 
     assert(inv != nullptr);
     std::string url;
diff --git a/extensions/standard-processors/tests/integration/TailFileTest.cpp b/extensions/standard-processors/tests/integration/TailFileTest.cpp
index 5a30ec6..d99e117 100644
--- a/extensions/standard-processors/tests/integration/TailFileTest.cpp
+++ b/extensions/standard-processors/tests/integration/TailFileTest.cpp
@@ -70,9 +70,9 @@ class TailFileTestHarness : public IntegrationBase {
   }
 
  protected:
-  void updateProperties(std::shared_ptr<minifi::FlowController> fc) override {
-    for (auto &comp : fc->getComponents("tf")) {
-      std::shared_ptr<minifi::state::ProcessorController> proc = std::dynamic_pointer_cast<minifi::state::ProcessorController>(comp);
+  void updateProperties(minifi::FlowController& fc) override {
+    for (auto comp : fc.getComponents("tf")) {
+      auto proc = dynamic_cast<minifi::state::ProcessorController*>(comp);
       if (nullptr != proc) {
         proc->getProcessor()->setProperty(minifi::processors::TailFile::FileName, ss.str());
         proc->getProcessor()->setProperty(minifi::processors::TailFile::StateFile, statefile);
diff --git a/extensions/standard-processors/tests/integration/TestExecuteProcess.cpp b/extensions/standard-processors/tests/integration/TestExecuteProcess.cpp
index c58456e..c16c59d 100644
--- a/extensions/standard-processors/tests/integration/TestExecuteProcess.cpp
+++ b/extensions/standard-processors/tests/integration/TestExecuteProcess.cpp
@@ -60,17 +60,17 @@ int main(int /*argc*/, char ** /*argv*/) {
 
   utils::Identifier processoruuid = processor->getUUID();
   assert(processoruuid);
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(test_repo, content_repo, "executeProcessConnection");
+  auto connection = std::make_unique<minifi::Connection>(test_repo, content_repo, "executeProcessConnection");
   connection->addRelationship(core::Relationship("success", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
-  connection->setDestination(processor);
+  connection->setSource(processor.get());
+  connection->setDestination(processor.get());
 
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(processoruuid);
 
-  processor->addConnection(connection);
+  processor->addConnection(connection.get());
   assert(processor->getName() == "executeProcess");
 
   std::shared_ptr<core::FlowFile> record;
@@ -82,17 +82,17 @@ int main(int /*argc*/, char ** /*argv*/) {
 
   std::vector<std::thread> processor_workers;
 
-  std::shared_ptr<core::ProcessorNode> node2 = std::make_shared<core::ProcessorNode>(processor);
-  std::shared_ptr<core::ProcessContext> contextset = std::make_shared<core::ProcessContext>(node2, nullptr, test_repo, test_repo);
+  auto node2 = std::make_shared<core::ProcessorNode>(processor.get());
+  auto contextset = std::make_shared<core::ProcessContext>(node2, nullptr, test_repo, test_repo);
   core::ProcessSessionFactory factory(contextset);
   processor->onSchedule(contextset.get(), &factory);
 
   for (int i = 0; i < 1; i++) {
     processor_workers.push_back(std::thread([processor, test_repo, &is_ready]() {
-      std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
-      std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, nullptr, test_repo, test_repo);
+      auto node = std::make_shared<core::ProcessorNode>(processor.get());
+      auto context = std::make_shared<core::ProcessContext>(node, nullptr, test_repo, test_repo);
       context->setProperty(org::apache::nifi::minifi::processors::ExecuteProcess::Command, "sleep 0.5");
-      std::shared_ptr<core::ProcessSession> session = std::make_shared<core::ProcessSession>(context);
+      auto session = std::make_shared<core::ProcessSession>(context);
       while (!is_ready.load(std::memory_order_relaxed)) {
       }
       processor->onTrigger(context.get(), session.get());
@@ -105,6 +105,6 @@ int main(int /*argc*/, char ** /*argv*/) {
     t.join();
   });
 
-  std::shared_ptr<org::apache::nifi::minifi::processors::ExecuteProcess> execp = std::static_pointer_cast<org::apache::nifi::minifi::processors::ExecuteProcess>(processor);
+  auto execp = std::static_pointer_cast<org::apache::nifi::minifi::processors::ExecuteProcess>(processor);
 #endif
 }
diff --git a/extensions/standard-processors/tests/unit/GetTCPTests.cpp b/extensions/standard-processors/tests/unit/GetTCPTests.cpp
index 3f6ce72..a267b67 100644
--- a/extensions/standard-processors/tests/unit/GetTCPTests.cpp
+++ b/extensions/standard-processors/tests/unit/GetTCPTests.cpp
@@ -20,7 +20,6 @@
 #include <string>
 #include <vector>
 #include <set>
-#include <fstream>
 #include "unit/ProvenanceTestHelper.h"
 #include "TestBase.h"
 #include "Catch.h"
@@ -35,7 +34,6 @@
 #include "core/ProcessSession.h"
 #include "core/ProcessorNode.h"
 #include "core/reporting/SiteToSiteProvenanceReportingTask.h"
-#include "utils/gsl.h"
 
 TEST_CASE("GetTCPWithoutEOM", "[GetTCP1]") {
   TestController testController;
@@ -56,9 +54,9 @@ TEST_CASE("GetTCPWithoutEOM", "[GetTCP1]") {
 
   std::shared_ptr<core::Repository> repo = std::make_shared<TestRepository>();
 
-  std::shared_ptr<core::Processor> processor = std::make_shared<org::apache::nifi::minifi::processors::GetTCP>("gettcpexample");
+  auto processor = std::make_unique<org::apache::nifi::minifi::processors::GetTCP>("gettcpexample");
 
-  std::shared_ptr<core::Processor> logAttribute = std::make_shared<org::apache::nifi::minifi::processors::LogAttribute>("logattribute");
+  auto logAttribute = std::make_unique<org::apache::nifi::minifi::processors::LogAttribute>("logattribute");
 
   processor->setStreamFactory(stream_factory);
   processor->initialize();
@@ -71,37 +69,37 @@ TEST_CASE("GetTCPWithoutEOM", "[GetTCP1]") {
 
   REQUIRE(processoruuid.to_string() != logattribute_uuid.to_string());
 
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(repo, content_repo, "gettcpexampleConnection");
+  auto connection = std::make_unique<minifi::Connection>(repo, content_repo, "gettcpexampleConnection");
   connection->addRelationship(core::Relationship("success", "description"));
 
-  std::shared_ptr<minifi::Connection> connection2 = std::make_shared<minifi::Connection>(repo, content_repo, "logattribute");
+  auto connection2 = std::make_unique<minifi::Connection>(repo, content_repo, "logattribute");
   connection2->addRelationship(core::Relationship("success", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
+  connection->setSource(processor.get());
 
   // link the connections so that we can test results at the end for this
-  connection->setDestination(logAttribute);
+  connection->setDestination(logAttribute.get());
 
-  connection2->setSource(logAttribute);
+  connection2->setSource(logAttribute.get());
 
   connection2->setSourceUUID(logattribute_uuid);
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(logattribute_uuid);
 
-  processor->addConnection(connection);
-  logAttribute->addConnection(connection);
-  logAttribute->addConnection(connection2);
+  processor->addConnection(connection.get());
+  logAttribute->addConnection(connection.get());
+  logAttribute->addConnection(connection2.get());
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
-    std::shared_ptr<core::ProcessorNode> node2 = std::make_shared<core::ProcessorNode>(logAttribute);
-    std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
-    std::shared_ptr<core::ProcessContext> context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
+  auto node2 = std::make_shared<core::ProcessorNode>(logAttribute.get());
+  auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
+  auto context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::EndpointList, org::apache::nifi::minifi::io::Socket::getMyHostName() + ":" + std::to_string(server.getPort()));
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::ReconnectInterval, "200 msec");
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::ConnectionAttemptLimit, "10");
   auto session = std::make_shared<core::ProcessSession>(context);
-    auto session2 = std::make_shared<core::ProcessSession>(context2);
+  auto session2 = std::make_shared<core::ProcessSession>(context2);
 
   REQUIRE(processor->getName() == "gettcpexample");
 
@@ -125,22 +123,19 @@ TEST_CASE("GetTCPWithoutEOM", "[GetTCP1]") {
   auto records = reporter->getEvents();
   record = session->get();
   REQUIRE(record == nullptr);
-  REQUIRE(records.size() == 0);
+  REQUIRE(records.empty());
 
   processor->incrementActiveTasks();
   processor->setScheduledState(core::ScheduledState::RUNNING);
   processor->onTrigger(context, session);
   reporter = session->getProvenanceReporter();
 
-  records = reporter->getEvents();
   session->commit();
 
   logAttribute->incrementActiveTasks();
   logAttribute->setScheduledState(core::ScheduledState::RUNNING);
   logAttribute->onTrigger(context2, session2);
 
-  records = reporter->getEvents();
-
   REQUIRE(true == LogTestController::getInstance().contains("Reconnect interval is 200 ms"));
   REQUIRE(true == LogTestController::getInstance().contains("Size:45 Offset:0"));
 
@@ -183,32 +178,32 @@ TEST_CASE("GetTCPWithOEM", "[GetTCP2]") {
   utils::Identifier logattribute_uuid = logAttribute->getUUID();
   REQUIRE(logattribute_uuid);
 
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(repo, content_repo, "gettcpexampleConnection");
+  auto connection = std::make_unique<minifi::Connection>(repo, content_repo, "gettcpexampleConnection");
   connection->addRelationship(core::Relationship("partial", "description"));
 
-  std::shared_ptr<minifi::Connection> connection2 = std::make_shared<minifi::Connection>(repo, content_repo, "logattribute");
+  auto connection2 = std::make_unique<minifi::Connection>(repo, content_repo, "logattribute");
   connection2->addRelationship(core::Relationship("partial", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
+  connection->setSource(processor.get());
 
   // link the connections so that we can test results at the end for this
-  connection->setDestination(logAttribute);
+  connection->setDestination(logAttribute.get());
 
-  connection2->setSource(logAttribute);
+  connection2->setSource(logAttribute.get());
 
   connection2->setSourceUUID(logattribute_uuid);
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(logattribute_uuid);
 
-  processor->addConnection(connection);
-  logAttribute->addConnection(connection);
-  logAttribute->addConnection(connection2);
+  processor->addConnection(connection.get());
+  logAttribute->addConnection(connection.get());
+  logAttribute->addConnection(connection2.get());
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
-    std::shared_ptr<core::ProcessorNode> node2 = std::make_shared<core::ProcessorNode>(logAttribute);
-    std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
-    std::shared_ptr<core::ProcessContext> context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
+  auto node2 = std::make_shared<core::ProcessorNode>(logAttribute.get());
+  auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
+  auto context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::EndpointList, org::apache::nifi::minifi::io::Socket::getMyHostName() + ":" + std::to_string(server.getPort()));
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::ReconnectInterval, "200 msec");
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::ConnectionAttemptLimit, "10");
@@ -240,28 +235,23 @@ TEST_CASE("GetTCPWithOEM", "[GetTCP2]") {
   auto records = reporter->getEvents();
   record = session->get();
   REQUIRE(record == nullptr);
-  REQUIRE(records.size() == 0);
+  REQUIRE(records.empty());
 
   processor->incrementActiveTasks();
   processor->setScheduledState(core::ScheduledState::RUNNING);
   processor->onTrigger(context, session);
   reporter = session->getProvenanceReporter();
 
-  records = reporter->getEvents();
   session->commit();
 
   logAttribute->incrementActiveTasks();
   logAttribute->setScheduledState(core::ScheduledState::RUNNING);
   logAttribute->onTrigger(context2, session2);
 
-  records = reporter->getEvents();
-
   logAttribute->incrementActiveTasks();
   logAttribute->setScheduledState(core::ScheduledState::RUNNING);
   logAttribute->onTrigger(context2, session2);
 
-  records = reporter->getEvents();
-
   REQUIRE(true == LogTestController::getInstance().contains("Reconnect interval is 200 ms"));
   REQUIRE(true == LogTestController::getInstance().contains("Size:11 Offset:0"));
   REQUIRE(true == LogTestController::getInstance().contains("Size:12 Offset:0"));
@@ -307,39 +297,39 @@ TEST_CASE("GetTCPWithOnlyOEM", "[GetTCP3]") {
   utils::Identifier logattribute_uuid = logAttribute->getUUID();
   REQUIRE(logattribute_uuid);
 
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(repo, content_repo, "gettcpexampleConnection");
+  auto connection = std::make_unique<minifi::Connection>(repo, content_repo, "gettcpexampleConnection");
   connection->addRelationship(core::Relationship("success", "description"));
 
-  std::shared_ptr<minifi::Connection> connection2 = std::make_shared<minifi::Connection>(repo, content_repo, "logattribute");
+  auto connection2 = std::make_unique<minifi::Connection>(repo, content_repo, "logattribute");
   connection2->addRelationship(core::Relationship("success", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
+  connection->setSource(processor.get());
 
   // link the connections so that we can test results at the end for this
-  connection->setDestination(logAttribute);
+  connection->setDestination(logAttribute.get());
 
-  connection2->setSource(logAttribute);
+  connection2->setSource(logAttribute.get());
 
   connection2->setSourceUUID(logattribute_uuid);
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(logattribute_uuid);
 
-  processor->addConnection(connection);
-  logAttribute->addConnection(connection);
-  logAttribute->addConnection(connection2);
+  processor->addConnection(connection.get());
+  logAttribute->addConnection(connection.get());
+  logAttribute->addConnection(connection2.get());
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
-    std::shared_ptr<core::ProcessorNode> node2 = std::make_shared<core::ProcessorNode>(logAttribute);
-    std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
-    std::shared_ptr<core::ProcessContext> context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
+  auto node2 = std::make_shared<core::ProcessorNode>(logAttribute.get());
+  auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
+  auto context2 = std::make_shared<core::ProcessContext>(node2, nullptr, repo, repo, content_repo);
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::EndpointList, org::apache::nifi::minifi::io::Socket::getMyHostName() + ":" + std::to_string(server.getPort()));
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::ReconnectInterval, "200 msec");
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::ConnectionAttemptLimit, "10");
   // we're using new lines above
   context->setProperty(org::apache::nifi::minifi::processors::GetTCP::EndOfMessageByte, "10");
   auto session = std::make_shared<core::ProcessSession>(context);
-    auto session2 = std::make_shared<core::ProcessSession>(context2);
+  auto session2 = std::make_shared<core::ProcessSession>(context2);
 
 
   REQUIRE(processor->getName() == "gettcpexample");
@@ -364,28 +354,23 @@ TEST_CASE("GetTCPWithOnlyOEM", "[GetTCP3]") {
   auto records = reporter->getEvents();
   record = session->get();
   REQUIRE(record == nullptr);
-  REQUIRE(records.size() == 0);
+  REQUIRE(records.empty());
 
   processor->incrementActiveTasks();
   processor->setScheduledState(core::ScheduledState::RUNNING);
   processor->onTrigger(context, session);
   reporter = session->getProvenanceReporter();
 
-  records = reporter->getEvents();
   session->commit();
 
   logAttribute->incrementActiveTasks();
   logAttribute->setScheduledState(core::ScheduledState::RUNNING);
   logAttribute->onTrigger(context2, session2);
 
-  records = reporter->getEvents();
-
   logAttribute->incrementActiveTasks();
   logAttribute->setScheduledState(core::ScheduledState::RUNNING);
   logAttribute->onTrigger(context2, session2);
 
-  records = reporter->getEvents();
-
   REQUIRE(true == LogTestController::getInstance().contains("Reconnect interval is 200 ms"));
   REQUIRE(true == LogTestController::getInstance().contains("Size:2 Offset:0"));
   LogTestController::getInstance().reset();
@@ -408,11 +393,11 @@ TEST_CASE("GetTCPEmptyNoConnect", "[GetTCP3]") {
   // we're using new lines above
   plan->setProperty(getfile, org::apache::nifi::minifi::processors::GetTCP::EndOfMessageByte.getName(), "10");
 
-  testController.runSession(plan, false);
+  TestController::runSession(plan, false);
   auto records = plan->getProvenanceRecords();
   std::shared_ptr<core::FlowFile> record = plan->getCurrentFlowFile();
   REQUIRE(record == nullptr);
-  REQUIRE(records.size() == 0);
+  REQUIRE(records.empty());
 
   REQUIRE(true == LogTestController::getInstance().contains("Reconnect interval is 200 ms"));
   REQUIRE(true == LogTestController::getInstance().contains("Could not create socket during initialization for " + org::apache::nifi::minifi::io::Socket::getMyHostName()  + ":9182"));
diff --git a/extensions/standard-processors/tests/unit/ManifestTests.cpp b/extensions/standard-processors/tests/unit/ManifestTests.cpp
index 0057333..1de7960 100644
--- a/extensions/standard-processors/tests/unit/ManifestTests.cpp
+++ b/extensions/standard-processors/tests/unit/ManifestTests.cpp
@@ -66,7 +66,7 @@ TEST_CASE("Test Required", "[required]") {
 }
 
 TEST_CASE("Test Valid Regex", "[validRegex]") {
-  minifi::state::response::ComponentManifest manifest("minifi-system");
+  minifi::state::response::ComponentManifest manifest("minifi-test-processors");
   auto serialized = manifest.serialize();
   REQUIRE(serialized.size() > 0);
   const auto &resp = serialized[0];
diff --git a/extensions/standard-processors/tests/unit/ProcessGroupTestUtils.h b/extensions/standard-processors/tests/unit/ProcessGroupTestUtils.h
index 45f160c..0ed1254 100644
--- a/extensions/standard-processors/tests/unit/ProcessGroupTestUtils.h
+++ b/extensions/standard-processors/tests/unit/ProcessGroupTestUtils.h
@@ -226,7 +226,7 @@ void verifyProcessGroup(core::ProcessGroup& group, const Group& pattern) {
   // verify name
   REQUIRE(group.getName() == pattern.name_);
   // verify connections
-  std::set<std::shared_ptr<minifi::Connection>>& connections = ProcessGroupTestAccessor::get_connections_(group);
+  const auto& connections = ProcessGroupTestAccessor::get_connections_(group);
   REQUIRE(connections.size() == pattern.connections_.size());
   for (auto& expected : pattern.connections_) {
     auto conn = findByName(connections, expected.name);
@@ -252,7 +252,7 @@ void verifyProcessGroup(core::ProcessGroup& group, const Group& pattern) {
   }
 
   // verify processors
-  std::set<std::shared_ptr<core::Processor>>& processors = ProcessGroupTestAccessor::get_processors_(group);
+  const auto& processors = ProcessGroupTestAccessor::get_processors_(group);
   REQUIRE(processors.size() == pattern.processors_.size());
   for (auto& expected : pattern.processors_) {
     REQUIRE(findByName(processors, expected.name));
@@ -272,7 +272,7 @@ void verifyProcessGroup(core::ProcessGroup& group, const Group& pattern) {
   for (auto& expected : pattern.rpgs_) {
     auto rpg = findByName(rpg_subgroups, expected.name);
     REQUIRE(rpg);
-    std::set<std::shared_ptr<core::Processor>>& input_ports = ProcessGroupTestAccessor::get_processors_(*rpg);
+    const auto& input_ports = ProcessGroupTestAccessor::get_processors_(*rpg);
     REQUIRE(input_ports.size() == expected.input_ports.size());
     for (auto& expected_input_port : expected.input_ports) {
       auto input_port = dynamic_cast<minifi::RemoteProcessorGroupPort*>(findByName(input_ports, expected_input_port.name));
diff --git a/extensions/standard-processors/tests/unit/ProcessorTests.cpp b/extensions/standard-processors/tests/unit/ProcessorTests.cpp
index 5096909..624cedb 100644
--- a/extensions/standard-processors/tests/unit/ProcessorTests.cpp
+++ b/extensions/standard-processors/tests/unit/ProcessorTests.cpp
@@ -74,21 +74,21 @@ TEST_CASE("Test GetFileMultiple", "[getfileCreate3]") {
   utils::Identifier processoruuid = processor->getUUID();
   REQUIRE(processoruuid);
 
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(test_repo, content_repo, "getfileCreate2Connection");
+  auto connection = std::make_unique<minifi::Connection>(test_repo, content_repo, "getfileCreate2Connection");
 
   connection->addRelationship(core::Relationship("success", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
-  connection->setDestination(processor);
+  connection->setSource(processor.get());
+  connection->setDestination(processor.get());
 
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(processoruuid);
 
-  processor->addConnection(connection);
+  processor->addConnection(connection.get());
   REQUIRE(!dir.empty());
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
   auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
 
   context->setProperty(org::apache::nifi::minifi::processors::GetFile::Directory, dir);
@@ -163,16 +163,16 @@ TEST_CASE("Test GetFile Ignore", "[getfileCreate3]") {
   connection->addRelationship(core::Relationship("success", "description"));
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
-  connection->setDestination(processor);
+  connection->setSource(processor.get());
+  connection->setDestination(processor.get());
 
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(processoruuid);
 
-  processor->addConnection(connection);
+  processor->addConnection(connection.get());
   REQUIRE(!dir.empty());
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
   auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
 
   context->setProperty(org::apache::nifi::minifi::processors::GetFile::Directory, dir);
@@ -258,16 +258,16 @@ TEST_CASE("TestConnectionFull", "[ConnectionFull]") {
   utils::Identifier processoruuid = processor->getUUID();
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
-  connection->setDestination(processor);
+  connection->setSource(processor.get());
+  connection->setDestination(processor.get());
 
   connection->setSourceUUID(processoruuid);
   connection->setDestinationUUID(processoruuid);
 
-  processor->addConnection(connection);
+  processor->addConnection(connection.get());
   processor->setScheduledState(core::ScheduledState::RUNNING);
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
   auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
 
   auto factory = std::make_shared<core::ProcessSessionFactory>(context);
@@ -571,7 +571,7 @@ void testRPGBypass(const std::string &host, const std::string &port, const std::
   rpg->initialize();
   REQUIRE(rpg->setProperty(minifi::RemoteProcessorGroupPort::hostName, host));
   rpg->setProperty(minifi::RemoteProcessorGroupPort::port, port);
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(rpg);
+  auto node = std::make_shared<core::ProcessorNode>(rpg.get());
   auto context = std::make_shared<core::ProcessContext>(node, nullptr, repo, repo, content_repo);
   auto psf = std::make_shared<core::ProcessSessionFactory>(context);
   if (hasException) {
@@ -639,10 +639,10 @@ ProcessorWithIncomingConnectionTest::ProcessorWithIncomingConnectionTest() {
   incoming_connection_ = std::make_shared<minifi::Connection>(repo, content_repo, "incoming_connection");
   incoming_connection_->addRelationship(core::Relationship{"success", ""});
   incoming_connection_->setDestinationUUID(processor_->getUUID());
-  processor_->addConnection(incoming_connection_);
+  processor_->addConnection(incoming_connection_.get());
   processor_->initialize();
 
-  const auto processor_node = std::make_shared<core::ProcessorNode>(processor_);
+  const auto processor_node = std::make_shared<core::ProcessorNode>(processor_.get());
   const auto context = std::make_shared<core::ProcessContext>(processor_node, nullptr, repo, repo, content_repo);
   const auto session_factory = std::make_shared<core::ProcessSessionFactory>(context);
   session_ = session_factory->createSession();
diff --git a/extensions/standard-processors/tests/unit/PutUDPTests.cpp b/extensions/standard-processors/tests/unit/PutUDPTests.cpp
index 01baa33..52defa3 100644
--- a/extensions/standard-processors/tests/unit/PutUDPTests.cpp
+++ b/extensions/standard-processors/tests/unit/PutUDPTests.cpp
@@ -23,6 +23,7 @@
 #include "SingleInputTestController.h"
 #include "Catch.h"
 #include "PutUDP.h"
+#include "core/ProcessContext.h"
 #include "utils/net/DNS.h"
 #include "utils/net/Socket.h"
 #include "utils/expected.h"
diff --git a/extensions/standard-processors/tests/unit/RouteTextTests.cpp b/extensions/standard-processors/tests/unit/RouteTextTests.cpp
index f76e76c..4e4d1b3 100644
--- a/extensions/standard-processors/tests/unit/RouteTextTests.cpp
+++ b/extensions/standard-processors/tests/unit/RouteTextTests.cpp
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include "FlowFileRecord.h"
 #include "TestBase.h"
 #include "Catch.h"
 #include "processors/RouteText.h"
@@ -124,8 +125,8 @@ struct RouteTextController : public TestController {
 
   std::shared_ptr<TestPlan> plan_ = createPlan();
   std::shared_ptr<core::Processor> proc_ = std::make_shared<processors::RouteText>("RouteText");
-  std::map<std::string, std::shared_ptr<minifi::Connection>> outputs_;
-  std::shared_ptr<minifi::Connection> input_;
+  std::map<std::string, minifi::Connection*> outputs_;
+  minifi::Connection* input_;
 };
 
 TEST_CASE_METHOD(RouteTextController, "RouteText correctly handles Matching Strategies") {
diff --git a/extensions/standard-processors/tests/unit/TailFileTests.cpp b/extensions/standard-processors/tests/unit/TailFileTests.cpp
index 0b630ea..a24d4d3 100644
--- a/extensions/standard-processors/tests/unit/TailFileTests.cpp
+++ b/extensions/standard-processors/tests/unit/TailFileTests.cpp
@@ -198,7 +198,7 @@ TEST_CASE("TailFile re-reads the file if the state is deleted between runs", "[s
   plan->reset(true);  // start a new but with state file
   LogTestController::getInstance().resetStream(LogTestController::getInstance().log_output);
 
-  plan->getStateManagerProvider()->getCoreComponentStateManager(*tailfile)->clear();
+  plan->getProcessContextForProcessor(tailfile)->getStateManager()->clear();
 
   testController.runSession(plan, true);
 
@@ -247,7 +247,7 @@ TEST_CASE("TailFile picks up the state correctly if it is rewritten between runs
     plan->reset(true);  // start a new but with state file
     LogTestController::getInstance().resetStream(LogTestController::getInstance().log_output);
 
-    plan->getStateManagerProvider()->getCoreComponentStateManager(*tailfile)->set({{"file.0.name", fileName},
+    plan->getProcessContextForProcessor(tailfile)->getStateManager()->set({{"file.0.name", fileName},
                                                                                    {"file.0.position", "14"},
                                                                                    {"file.0.current", temp_file.str()}});
 
@@ -259,7 +259,7 @@ TEST_CASE("TailFile picks up the state correctly if it is rewritten between runs
   for (int i = 14; i < 34; i++) {
     plan->reset(true);  // start a new but with state file
 
-    plan->getStateManagerProvider()->getCoreComponentStateManager(*tailfile)->set({{"file.0.name", fileName},
+    plan->getProcessContextForProcessor(tailfile)->getStateManager()->set({{"file.0.name", fileName},
                                                                                    {"file.0.position", std::to_string(i)},
                                                                                    {"file.0.current", temp_file.str()}});
 
@@ -317,7 +317,7 @@ TEST_CASE("TailFile converts the old-style state file to the new-style state", "
     REQUIRE(LogTestController::getInstance().contains("key:filename value:minifi-tmpfile.14-34.txt"));
 
     std::unordered_map<std::string, std::string> state;
-    REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*tailfile)->get(state));
+    REQUIRE(plan->getProcessContextForProcessor(tailfile)->getStateManager()->get(state));
 
     std::string filePath, fileName;
     REQUIRE(utils::file::getFileNameAndPath(temp_file, filePath, fileName));
@@ -361,7 +361,7 @@ TEST_CASE("TailFile converts the old-style state file to the new-style state", "
     REQUIRE(LogTestController::getInstance().contains(file_name_2.substr(0, file_name_2.rfind('.')) + ".15-34.txt"));
 
     std::unordered_map<std::string, std::string> state;
-    REQUIRE(plan->getStateManagerProvider()->getCoreComponentStateManager(*tailfile)->get(state));
+    REQUIRE(plan->getProcessContextForProcessor(tailfile)->getStateManager()->get(state));
 
     std::string filePath1, filePath2, fileName1, fileName2;
     REQUIRE(utils::file::getFileNameAndPath(temp_file_1, filePath1, fileName1));
diff --git a/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp b/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp
index de68694..62b88ce 100644
--- a/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp
+++ b/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp
@@ -159,7 +159,7 @@ Provenance Reporting:
     REQUIRE(1s == rootFlowConfig->findProcessorByName("TailFile")->getYieldPeriodMsec());
     REQUIRE(0s == rootFlowConfig->findProcessorByName("TailFile")->getRunDurationNano());
 
-    std::map<std::string, std::shared_ptr<minifi::Connection>> connectionMap;
+    std::map<std::string, minifi::Connection*> connectionMap;
     rootFlowConfig->getConnections(connectionMap);
     REQUIRE(2 == connectionMap.size());
     // This is a map of UUID->Connection, and we don't know UUID, so just going to loop over it
@@ -484,7 +484,7 @@ NiFi Properties Overrides: {}
   REQUIRE(1s == rootFlowConfig->findProcessorByName("TailFile")->getYieldPeriodMsec());
   REQUIRE(0s == rootFlowConfig->findProcessorByName("TailFile")->getRunDurationNano());
 
-  std::map<std::string, std::shared_ptr<minifi::Connection>> connectionMap;
+  std::map<std::string, minifi::Connection*> connectionMap;
   rootFlowConfig->getConnections(connectionMap);
   REQUIRE(2 == connectionMap.size());
 
@@ -641,7 +641,7 @@ TEST_CASE("Test Dependent Property", "[YamlConfigurationDependentProperty]") {
   props.emplace(core::Property("Prop A", "Prop A desc", "val A", true, "", { }, { }));
   props.emplace(core::Property("Prop B", "Prop B desc", "val B", true, "", { "Prop A" }, { }));
   component->setSupportedProperties(std::move(props));
-  yamlConfig.validateComponentProperties(component, "component A", "section A");
+  yamlConfig.validateComponentProperties(*component, "component A", "section A");
   REQUIRE(true);  // Expected to get here w/o any exceptions
 }
 
@@ -665,7 +665,7 @@ TEST_CASE("Test Dependent Property 2", "[YamlConfigurationDependentProperty2]")
   component->setSupportedProperties(std::move(props));
   bool config_failed = false;
   try {
-    yamlConfig.validateComponentProperties(component, "component A", "section A");
+    yamlConfig.validateComponentProperties(*component, "component A", "section A");
   } catch (const std::exception &e) {
     config_failed = true;
     REQUIRE("Unable to parse configuration file for component named 'component A' because property "
@@ -693,7 +693,7 @@ TEST_CASE("Test Exclusive Property", "[YamlConfigurationExclusiveProperty]") {
   props.emplace(core::Property("Prop A", "Prop A desc", "val A", true, "", { }, { }));
   props.emplace(core::Property("Prop B", "Prop B desc", "val B", true, "", { }, { { "Prop A", "^abcd.*$" } }));
   component->setSupportedProperties(std::move(props));
-  yamlConfig.validateComponentProperties(component, "component A", "section A");
+  yamlConfig.validateComponentProperties(*component, "component A", "section A");
   REQUIRE(true);  // Expected to get here w/o any exceptions
 }
 
@@ -713,7 +713,7 @@ TEST_CASE("Test Regex Property", "[YamlConfigurationRegexProperty]") {
   props.emplace(core::Property("Prop A", "Prop A desc", "val A", true, "", { }, { }));
   props.emplace(core::Property("Prop B", "Prop B desc", "val B", true, "^val.*$", { }, { }));
   component->setSupportedProperties(std::move(props));
-  yamlConfig.validateComponentProperties(component, "component A", "section A");
+  yamlConfig.validateComponentProperties(*component, "component A", "section A");
   REQUIRE(true);  // Expected to get here w/o any exceptions
 }
 
@@ -736,7 +736,7 @@ TEST_CASE("Test Exclusive Property 2", "[YamlConfigurationExclusiveProperty2]")
   component->setSupportedProperties(std::move(props));
   bool config_failed = false;
   try {
-    yamlConfig.validateComponentProperties(component, "component A", "section A");
+    yamlConfig.validateComponentProperties(*component, "component A", "section A");
   } catch (const std::exception &e) {
     config_failed = true;
     REQUIRE("Unable to parse configuration file for component named 'component A' because "
@@ -764,7 +764,7 @@ TEST_CASE("Test Regex Property 2", "[YamlConfigurationRegexProperty2]") {
   component->setSupportedProperties(std::move(props));
   bool config_failed = false;
   try {
-    yamlConfig.validateComponentProperties(component, "component A", "section A");
+    yamlConfig.validateComponentProperties(*component, "component A", "section A");
   } catch (const std::exception &e) {
     config_failed = true;
     REQUIRE("Unable to parse configuration file for component named 'component A' because "
@@ -857,7 +857,7 @@ Remote Process Groups: []
   REQUIRE(rootFlowConfig->findProcessorByName("GenerateFlowFile2"));
   REQUIRE(rootFlowConfig->findProcessorById(utils::Identifier::parse("01a2f910-7050-41c1-8528-942764e7591d").value()));
 
-  std::map<std::string, std::shared_ptr<minifi::Connection>> connectionMap;
+  std::map<std::string, minifi::Connection*> connectionMap;
   rootFlowConfig->getConnections(connectionMap);
   REQUIRE(6 == connectionMap.size());
   for (auto it : connectionMap) {
diff --git a/extensions/standard-processors/tests/unit/YamlConnectionParserTest.cpp b/extensions/standard-processors/tests/unit/YamlConnectionParserTest.cpp
index 1fc691c..434134c 100644
--- a/extensions/standard-processors/tests/unit/YamlConnectionParserTest.cpp
+++ b/extensions/standard-processors/tests/unit/YamlConnectionParserTest.cpp
@@ -55,7 +55,7 @@ TEST_CASE("Connections components are parsed from yaml", "[YamlConfiguration]")
     }
     YAML::Node connection_node = YAML::Load(serialized_yaml);
     YamlConnectionParser yaml_connection_parser(connection_node, "test_node", parent_ptr, logger);
-    yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(connection);
+    yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(*connection);
     const std::set<core::Relationship>& relationships = connection->getRelationships();
     REQUIRE(expectations == relationships);
   }
@@ -71,8 +71,8 @@ TEST_CASE("Connections components are parsed from yaml", "[YamlConfiguration]")
     const utils::Identifier expected_source_id = utils::generateUUID();
     const utils::Identifier expected_destination_id = utils::generateUUID();
     std::string serialized_yaml;
-    parent.addProcessor(std::static_pointer_cast<core::Processor>(std::make_shared<minifi::processors::TailFile>("TailFile_1", expected_source_id)));
-    parent.addProcessor(std::static_pointer_cast<core::Processor>(std::make_shared<minifi::processors::TailFile>("TailFile_2", expected_destination_id)));
+    parent.addProcessor(std::make_unique<minifi::processors::TailFile>("TailFile_1", expected_source_id));
+    parent.addProcessor(std::make_unique<minifi::processors::TailFile>("TailFile_2", expected_destination_id));
     SECTION("Directly from configuration") {
       serialized_yaml = std::string {
           "source id: " + expected_source_id.to_string() + "\n"
@@ -118,7 +118,7 @@ TEST_CASE("Connections components are parsed from yaml", "[YamlConfiguration]")
     SECTION("With empty configuration") {
       YAML::Node connection_node = YAML::Load(std::string(""));
       YamlConnectionParser yaml_connection_parser(connection_node, "test_node", parent_ptr, logger);
-      CHECK_THROWS(yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(connection));
+      CHECK_THROWS(yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(*connection));
       CHECK_NOTHROW(yaml_connection_parser.getWorkQueueSizeFromYaml());
       CHECK_NOTHROW(yaml_connection_parser.getWorkQueueDataSizeFromYaml());
       CHECK_THROWS(yaml_connection_parser.getSourceUUIDFromYaml());
@@ -134,14 +134,14 @@ TEST_CASE("Connections components are parsed from yaml", "[YamlConfiguration]")
             "destination name: \n" });
         YamlConnectionParser yaml_connection_parser(connection_node, "test_node", parent_ptr, logger);
         // This seems incorrect, but we do not want to ruin backward compatibility
-        CHECK_NOTHROW(yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(connection));
+        CHECK_NOTHROW(yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(*connection));
       }
       SECTION("List of relationship names contains empty item") {
         YAML::Node connection_node = YAML::Load(std::string {
             "source relationship names:\n"
             "- \n" });
         YamlConnectionParser yaml_connection_parser(connection_node, "test_node", parent_ptr, logger);
-        CHECK_NOTHROW(yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(connection));
+        CHECK_NOTHROW(yaml_connection_parser.configureConnectionSourceRelationshipsFromYaml(*connection));
       }
       SECTION("Source and destination lookup from via id") {
         YAML::Node connection_node = YAML::Load(std::string {
diff --git a/extensions/systemd/ConsumeJournald.cpp b/extensions/systemd/ConsumeJournald.cpp
index 8334ddb..94f3ca8 100644
--- a/extensions/systemd/ConsumeJournald.cpp
+++ b/extensions/systemd/ConsumeJournald.cpp
@@ -24,6 +24,8 @@
 #include "spdlog/spdlog.h"  // TODO(szaszm): make fmt directly available
 #include "utils/GeneralUtils.h"
 #include "utils/OptionalUtils.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/Resource.h"
 
 namespace org { namespace apache { namespace nifi { namespace minifi { namespace extensions { namespace systemd {
diff --git a/extensions/systemd/ConsumeJournald.h b/extensions/systemd/ConsumeJournald.h
index ed48432..a96c07e 100644
--- a/extensions/systemd/ConsumeJournald.h
+++ b/extensions/systemd/ConsumeJournald.h
@@ -31,7 +31,7 @@
 
 #include "core/CoreComponentState.h"
 #include "core/Processor.h"
-#include "core/logging/Logger.h"
+#include "core/logging/LoggerConfiguration.h"
 #include "libwrapper/LibWrapper.h"
 #include "utils/Deleters.h"
 #include "utils/gsl.h"
@@ -95,7 +95,7 @@ class ConsumeJournald final : public core::Processor {
 
   std::atomic<bool> running_{false};
   std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<ConsumeJournald>::getLogger();
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   std::unique_ptr<libwrapper::LibWrapper> libwrapper_;
   std::unique_ptr<Worker> worker_;
   std::unique_ptr<libwrapper::Journal> journal_;
diff --git a/extensions/test-processors/CMakeLists.txt b/extensions/test-processors/CMakeLists.txt
new file mode 100644
index 0000000..275a2ac
--- /dev/null
+++ b/extensions/test-processors/CMakeLists.txt
@@ -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.
+#
+
+include(../ExtensionHeader.txt)
+
+file(GLOB SOURCES  "*.cpp")
+
+add_library(minifi-test-processors SHARED ${SOURCES})
+
+target_link_libraries(minifi-test-processors ${LIBMINIFI})
+
+SET(TEST-PROCESSORS-EXTENSION minifi-test-processors PARENT_SCOPE)
+register_extension(minifi-test-processors)
+
+register_extension_linter(minifi-test-processors-extensions-linter)
diff --git a/libminifi/test/KamikazeProcessor.cpp b/extensions/test-processors/KamikazeProcessor.cpp
similarity index 93%
rename from libminifi/test/KamikazeProcessor.cpp
rename to extensions/test-processors/KamikazeProcessor.cpp
index a7d957a..24224a2 100644
--- a/libminifi/test/KamikazeProcessor.cpp
+++ b/extensions/test-processors/KamikazeProcessor.cpp
@@ -22,11 +22,7 @@
 #include "Exception.h"
 #include "core/Resource.h"
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace processors {
+namespace org::apache::nifi::minifi::processors {
 
 const std::string KamikazeProcessor::OnScheduleExceptionStr = "This processor was configured to throw exception during onSchedule";
 const std::string KamikazeProcessor::OnTriggerExceptionStr = "This processor was configured to throw exception during onTrigger";
@@ -76,8 +72,4 @@ void KamikazeProcessor::onUnSchedule() {
 
 REGISTER_RESOURCE(KamikazeProcessor, "This processor can throw exceptions in onTrigger and onSchedule calls based on configration. Only for testing purposes.");
 
-}  // namespace processors
-}  // namespace minifi
-}  // namespace nifi
-}  // namespace apache
-}  // namespace org
+}  // namespace org::apache::nifi::minifi::processors
diff --git a/libminifi/test/KamikazeProcessor.h b/extensions/test-processors/KamikazeProcessor.h
similarity index 75%
rename from libminifi/test/KamikazeProcessor.h
rename to extensions/test-processors/KamikazeProcessor.h
index 25346db..f5d686a 100644
--- a/libminifi/test/KamikazeProcessor.h
+++ b/extensions/test-processors/KamikazeProcessor.h
@@ -25,19 +25,15 @@
 
 #pragma once
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace processors {
+namespace org::apache::nifi::minifi::processors {
 
 class KamikazeProcessor : public core::Processor {
  public:
-  static const std::string OnScheduleExceptionStr;
-  static const std::string OnTriggerExceptionStr;
-  static const std::string OnScheduleLogStr;
-  static const std::string OnTriggerLogStr;
-  static const std::string OnUnScheduleLogStr;
+  EXTENSIONAPI static const std::string OnScheduleExceptionStr;
+  EXTENSIONAPI static const std::string OnTriggerExceptionStr;
+  EXTENSIONAPI static const std::string OnScheduleLogStr;
+  EXTENSIONAPI static const std::string OnTriggerLogStr;
+  EXTENSIONAPI static const std::string OnUnScheduleLogStr;
 
   explicit KamikazeProcessor(const std::string& name, const utils::Identifier& uuid = utils::Identifier())
       : Processor(name, uuid) {
@@ -46,8 +42,8 @@ class KamikazeProcessor : public core::Processor {
   // Processor Name
   static constexpr char const* ProcessorName = "KamikazeProcessor";
   // Supported Properties
-  static core::Property ThrowInOnSchedule;
-  static core::Property ThrowInOnTrigger;
+  EXTENSIONAPI static core::Property ThrowInOnSchedule;
+  EXTENSIONAPI static core::Property ThrowInOnTrigger;
 
  public:
   void onSchedule(core::ProcessContext *context, core::ProcessSessionFactory *sessionFactory) override;
@@ -60,8 +56,4 @@ class KamikazeProcessor : public core::Processor {
   std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<KamikazeProcessor>::getLogger();
 };
 
-} /* namespace processors */
-} /* namespace minifi */
-} /* namespace nifi */
-} /* namespace apache */
-} /* namespace org */
+}  // namespace org::apache::nifi::minifi::processors
diff --git a/libminifi/src/core/ProcessorNode.cpp b/extensions/test-processors/LogOnDestructionProcessor.cpp
similarity index 54%
copy from libminifi/src/core/ProcessorNode.cpp
copy to extensions/test-processors/LogOnDestructionProcessor.cpp
index cd0e719..5bae07c 100644
--- a/libminifi/src/core/ProcessorNode.cpp
+++ b/extensions/test-processors/LogOnDestructionProcessor.cpp
@@ -1,4 +1,5 @@
 /**
+ *
  * 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.
@@ -15,34 +16,11 @@
  * limitations under the License.
  */
 
-#include "core/ProcessorNode.h"
-#include <memory>
-#include <utility>
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace core {
-
-ProcessorNode::ProcessorNode(const std::shared_ptr<Connectable> &processor)
-    : ConfigurableComponent(),
-      Connectable(processor->getName()),
-      processor_(processor) {
-  setUUID(processor->getUUID());
-}
-
-ProcessorNode::~ProcessorNode() = default;
+#include "LogOnDestructionProcessor.h"
+#include "core/Resource.h"
 
-bool ProcessorNode::isWorkAvailable() {
-  return processor_->isWorkAvailable();
-}
+namespace org::apache::nifi::minifi::processors {
 
-bool ProcessorNode::isRunning() {
-  return processor_->isRunning();
-}
+REGISTER_RESOURCE(LogOnDestructionProcessor, "This processor logs a message on destruction. Only for testing purposes.");
 
-} /* namespace core */
-} /* namespace minifi */
-} /* namespace nifi */
-} /* namespace apache */
-} /* namespace org */
+}  // namespace org::apache::nifi::minifi::processors
diff --git a/libminifi/include/c2/HeartbeatLogger.h b/extensions/test-processors/LogOnDestructionProcessor.h
similarity index 55%
copy from libminifi/include/c2/HeartbeatLogger.h
copy to extensions/test-processors/LogOnDestructionProcessor.h
index cd4093f..af5d836 100644
--- a/libminifi/include/c2/HeartbeatLogger.h
+++ b/extensions/test-processors/LogOnDestructionProcessor.h
@@ -1,4 +1,5 @@
 /**
+ *
  * 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.
@@ -20,28 +21,23 @@
 #include <memory>
 #include <string>
 
-#include "core/logging/Logger.h"
-#include "HeartbeatReporter.h"
-#include "c2/protocols/RESTProtocol.h"
+#include "core/logging/LoggerConfiguration.h"
+#include "core/Processor.h"
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace c2 {
+namespace org::apache::nifi::minifi::processors {
 
-class HeartbeatLogger : public RESTProtocol, public HeartbeatReporter {
+class LogOnDestructionProcessor : public core::Processor {
  public:
-  explicit HeartbeatLogger(const std::string& name, const utils::Identifier& id = {});
-  int16_t heartbeat(const C2Payload &heartbeat) override;
-  void initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink, const std::shared_ptr<Configure> &configure) override;
+  explicit LogOnDestructionProcessor(const std::string& name, const utils::Identifier& uuid = utils::Identifier())
+    : Processor(name, uuid) {
+  }
+
+  ~LogOnDestructionProcessor() override {
+    logger_->log_info("LogOnDestructionProcessor is being destructed");
+  }
 
  private:
-  std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<HeartbeatLogger>::getLogger();
+  std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<LogOnDestructionProcessor>::getLogger();
 };
 
-}  // namespace c2
-}  // namespace minifi
-}  // namespace nifi
-}  // namespace apache
-}  // namespace org
+}  // namespace org::apache::nifi::minifi::processors
diff --git a/extensions/usb-camera/GetUSBCamera.cpp b/extensions/usb-camera/GetUSBCamera.cpp
index 0d4399f..42e21f5 100644
--- a/extensions/usb-camera/GetUSBCamera.cpp
+++ b/extensions/usb-camera/GetUSBCamera.cpp
@@ -28,6 +28,7 @@
 #include <algorithm>
 
 #include "utils/gsl.h"
+#include "core/ProcessSessionFactory.h"
 #include "core/Resource.h"
 
 namespace org {
diff --git a/extensions/windows-event-log/Bookmark.cpp b/extensions/windows-event-log/Bookmark.cpp
index ae8156b..600ef3a 100644
--- a/extensions/windows-event-log/Bookmark.cpp
+++ b/extensions/windows-event-log/Bookmark.cpp
@@ -39,7 +39,7 @@ Bookmark::Bookmark(const std::wstring& channel,
     const std::string& bookmarkRootDir,
     const utils::Identifier& uuid,
     bool processOldEvents,
-    std::shared_ptr<core::CoreComponentStateManager> state_manager,
+    core::CoreComponentStateManager* state_manager,
     std::shared_ptr<core::logging::Logger> logger)
     : logger_(std::move(logger)),
       state_manager_(state_manager) {
diff --git a/extensions/windows-event-log/Bookmark.h b/extensions/windows-event-log/Bookmark.h
index 34602b2..762710d 100644
--- a/extensions/windows-event-log/Bookmark.h
+++ b/extensions/windows-event-log/Bookmark.h
@@ -44,7 +44,7 @@ class Bookmark {
       const std::string& bookmarkRootDir,
       const utils::Identifier& uuid,
       bool processOldEvents,
-      std::shared_ptr<core::CoreComponentStateManager> state_manager,
+      core::CoreComponentStateManager* state_manager,
       std::shared_ptr<core::logging::Logger> logger);
   ~Bookmark();
   explicit operator bool() const noexcept;
@@ -60,7 +60,7 @@ class Bookmark {
   using unique_evt_handle = wel::unique_evt_handle;
 
   std::shared_ptr<core::logging::Logger> logger_;
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   std::string filePath_;
   bool ok_{};
   unique_evt_handle hBookmark_;
diff --git a/extensions/windows-event-log/CollectorInitiatedSubscription.cpp b/extensions/windows-event-log/CollectorInitiatedSubscription.cpp
index cd10b04..69f5340 100644
--- a/extensions/windows-event-log/CollectorInitiatedSubscription.cpp
+++ b/extensions/windows-event-log/CollectorInitiatedSubscription.cpp
@@ -32,6 +32,7 @@
 #include "io/BufferStream.h"
 #include "core/ProcessContext.h"
 #include "core/ProcessSession.h"
+#include "core/ProcessSessionFactory.h"
 #include "core/Resource.h"
 
 #include "utils/gsl.h"
diff --git a/extensions/windows-event-log/ConsumeWindowsEventLog.h b/extensions/windows-event-log/ConsumeWindowsEventLog.h
index f1f6e54..dd078ef 100644
--- a/extensions/windows-event-log/ConsumeWindowsEventLog.h
+++ b/extensions/windows-event-log/ConsumeWindowsEventLog.h
@@ -148,7 +148,7 @@ class ConsumeWindowsEventLog : public core::Processor {
 
   // Logger
   std::shared_ptr<core::logging::Logger> logger_;
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   wel::METADATA_NAMES header_names_;
   std::string header_delimiter_;
   std::string channel_;
diff --git a/extensions/windows-event-log/tests/BookmarkTests.cpp b/extensions/windows-event-log/tests/BookmarkTests.cpp
index e2b87b1..a05f159 100644
--- a/extensions/windows-event-log/tests/BookmarkTests.cpp
+++ b/extensions/windows-event-log/tests/BookmarkTests.cpp
@@ -39,8 +39,8 @@ constexpr DWORD EVT_NEXT_TIMEOUT_MS = 100;
 
 std::unique_ptr<Bookmark> createBookmark(TestPlan &test_plan,
                                          const std::wstring &channel,
-                                         const utils::Identifier &uuid = IdGenerator::getIdGenerator()->generate()) {
-  const auto state_manager = test_plan.getStateManagerProvider()->getCoreComponentStateManager(uuid);
+                                         const utils::Identifier &uuid,
+                                         core::CoreComponentStateManager* state_manager) {
   const auto logger = test_plan.getLogger();
   return std::make_unique<Bookmark>(channel, L"*", "", uuid, false, state_manager, logger);
 }
@@ -101,7 +101,10 @@ TEST_CASE("Bookmark constructor works", "[create]") {
 
   reportEvent(APPLICATION_CHANNEL, "Publish an event to make sure the event log is not empty");
 
-  std::unique_ptr<Bookmark> bookmark = createBookmark(*test_plan, APPLICATION_CHANNEL);
+
+  const utils::Identifier uuid = IdGenerator::getIdGenerator()->generate();
+  auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid);
+  std::unique_ptr<Bookmark> bookmark = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
   REQUIRE(bookmark);
   REQUIRE(*bookmark);
 
@@ -117,13 +120,14 @@ TEST_CASE("Bookmark is restored from the state", "[create][state]") {
   LogTestController::getInstance().setTrace<TestPlan>();
 
   utils::Identifier uuid = IdGenerator::getIdGenerator()->generate();
-  std::unique_ptr<Bookmark> bookmark_before = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid);
+  auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid);
+  std::unique_ptr<Bookmark> bookmark_before = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
   std::wstring bookmark_xml_before = bookmarkAsXml(bookmark_before);
 
   reportEvent(APPLICATION_CHANNEL, "Something interesting happened");
 
   // same uuid, so the state manager is the same as before
-  std::unique_ptr<Bookmark> bookmark_after = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid);
+  std::unique_ptr<Bookmark> bookmark_after = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
   std::wstring bookmark_xml_after = bookmarkAsXml(bookmark_after);
 
   REQUIRE(bookmark_xml_before == bookmark_xml_after);
@@ -135,13 +139,15 @@ TEST_CASE("Bookmark created after a new event is different", "[create][state]")
   LogTestController::getInstance().setTrace<TestPlan>();
 
   utils::Identifier uuid_one = IdGenerator::getIdGenerator()->generate();
-  std::unique_ptr<Bookmark> bookmark_before = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one);
+  auto state_manager_one = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid_one);
+  std::unique_ptr<Bookmark> bookmark_before = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one, state_manager_one.get());
 
   reportEvent(APPLICATION_CHANNEL, "Something interesting happened");
 
   utils::Identifier uuid_two = IdGenerator::getIdGenerator()->generate();
   // different uuid, so we get a new, empty, state manager
-  std::unique_ptr<Bookmark> bookmark_after = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_two);
+  auto state_manager_two = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid_two);
+  std::unique_ptr<Bookmark> bookmark_after = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_two, state_manager_two.get());
 
   REQUIRE(bookmarkAsXml(bookmark_before) != bookmarkAsXml(bookmark_after));
 }
@@ -152,8 +158,9 @@ TEST_CASE("Bookmark::getBookmarkHandleFromXML() returns the same event from a co
   LogTestController::getInstance().setTrace<TestPlan>();
 
   utils::Identifier uuid = IdGenerator::getIdGenerator()->generate();
-  std::unique_ptr<Bookmark> bookmark_one = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid);
-  std::unique_ptr<Bookmark> bookmark_two = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid);
+  auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid);
+  std::unique_ptr<Bookmark> bookmark_one = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
+  std::unique_ptr<Bookmark> bookmark_two = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
 
   EVT_HANDLE bookmark_handle_one = bookmark_one->getBookmarkHandleFromXML();
   EVT_HANDLE bookmark_handle_two = bookmark_two->getBookmarkHandleFromXML();
@@ -167,18 +174,20 @@ TEST_CASE("Bookmark::getBookmarkHandleFromXML() returns a different event after
 
   GIVEN("We have two different bookmarks") {
     const auto uuid = IdGenerator::getIdGenerator()->generate();
-    std::unique_ptr<Bookmark> bookmark_one = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid);
+    auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid);
+    std::unique_ptr<Bookmark> bookmark_one = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
     std::wstring bookmark_one_xml = bookmarkAsXml(bookmark_one);
 
     reportEvent(APPLICATION_CHANNEL, "Something interesting happened");
 
-    std::unique_ptr<Bookmark> bookmark_two = createBookmark(*test_plan, APPLICATION_CHANNEL);
+    const utils::Identifier uuid_two = IdGenerator::getIdGenerator()->generate();
+    auto state_manager_two = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid_two);
+    std::unique_ptr<Bookmark> bookmark_two = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_two, state_manager_two.get());
     std::wstring bookmark_two_xml = bookmarkAsXml(bookmark_two);
 
     REQUIRE(bookmark_one_xml != bookmark_two_xml);
 
     WHEN("we set the XML of the first bookmark equal to the XML of the second bookmark") {
-      const auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid);
       bookmark_one->saveBookmarkXml(bookmark_two_xml);
 
       THEN("getBookmarkHandleFromXML() will return the updated handle") {
@@ -198,7 +207,9 @@ TEST_CASE("Bookmark::getNewBookmarkXml() updates the bookmark", "[add_event]") {
   std::shared_ptr<TestPlan> test_plan = test_controller.createPlan();
   LogTestController::getInstance().setTrace<TestPlan>();
 
-  std::unique_ptr<Bookmark> bookmark = createBookmark(*test_plan, APPLICATION_CHANNEL);
+  const utils::Identifier uuid = IdGenerator::getIdGenerator()->generate();
+  auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid);
+  std::unique_ptr<Bookmark> bookmark = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid, state_manager.get());
   std::wstring bookmark_xml_before = bookmarkAsXml(bookmark);
 
   reportEvent(APPLICATION_CHANNEL, "Something interesting happened");
@@ -219,17 +230,19 @@ TEST_CASE("Bookmark::saveBookmarkXml() updates the bookmark and saves it to the
 
   GIVEN("We have two different bookmarks with two different state managers") {
     utils::Identifier uuid_one = IdGenerator::getIdGenerator()->generate();
-    std::unique_ptr<Bookmark> bookmark_one = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one);
+    auto state_manager_one = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid_one);
+    std::unique_ptr<Bookmark> bookmark_one = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one, state_manager_one.get());
 
     reportEvent(APPLICATION_CHANNEL, "Something interesting happened");
 
     utils::Identifier uuid_two = IdGenerator::getIdGenerator()->generate();
-    std::unique_ptr<Bookmark> bookmark_two = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_two);
+    auto state_manager_two = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid_two);
+    std::unique_ptr<Bookmark> bookmark_two = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_two, state_manager_two.get());
 
     REQUIRE(bookmarkAsXml(bookmark_one) != bookmarkAsXml(bookmark_two));
 
     WHEN("we create a new bookmark with state manager one") {
-      std::unique_ptr<Bookmark> bookmark_one_same = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one);
+      std::unique_ptr<Bookmark> bookmark_one_same = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one, state_manager_one.get());
 
       THEN("it will be the same as bookmark one.") {
         REQUIRE(bookmarkAsXml(bookmark_one_same) == bookmarkAsXml(bookmark_one));
@@ -238,9 +251,8 @@ TEST_CASE("Bookmark::saveBookmarkXml() updates the bookmark and saves it to the
 
     WHEN("saveBookmarkXml() is called on bookmark one with the XML of bookmark two, "
          "and then we create a new bookmark with state manager one") {
-      const auto state_manager = test_plan->getStateManagerProvider()->getCoreComponentStateManager(uuid_one);
       bookmark_one->saveBookmarkXml(bookmarkAsXml(bookmark_two));
-      std::unique_ptr<Bookmark> bookmark_one_different = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one);
+      std::unique_ptr<Bookmark> bookmark_one_different = createBookmark(*test_plan, APPLICATION_CHANNEL, uuid_one, state_manager_one.get());
 
       THEN("it will be the same as bookmark two.") {
         REQUIRE(bookmarkAsXml(bookmark_one_different) == bookmarkAsXml(bookmark_two));
diff --git a/libminifi/include/Connection.h b/libminifi/include/Connection.h
index e79a384..b41046f 100644
--- a/libminifi/include/Connection.h
+++ b/libminifi/include/Connection.h
@@ -40,14 +40,9 @@ namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
-// Connection Class
 
-class Connection : public core::Connectable, public std::enable_shared_from_this<Connection> {
+class Connection : public core::Connectable {
  public:
-  // Constructor
-  /*
-   * Create a new processor
-   */
   explicit Connection(const std::shared_ptr<core::Repository> &flow_repository, const std::shared_ptr<core::ContentRepository> &content_repo, const std::string &name);
   explicit Connection(const std::shared_ptr<core::Repository> &flow_repository, const std::shared_ptr<core::ContentRepository> &content_repo, const std::string &name, const utils::Identifier &uuid);
   explicit Connection(const std::shared_ptr<core::Repository> &flow_repository, const std::shared_ptr<core::ContentRepository> &content_repo, const std::string &name, const utils::Identifier &uuid,
@@ -55,7 +50,7 @@ class Connection : public core::Connectable, public std::enable_shared_from_this
   explicit Connection(const std::shared_ptr<core::Repository> &flow_repository, const std::shared_ptr<core::ContentRepository> &content_repo, const std::string &name, const utils::Identifier &uuid,
                       const utils::Identifier &srcUUID, const utils::Identifier &destUUID);
   // Destructor
-  virtual ~Connection() = default;
+  ~Connection() override = default;
 
   // Set Source Processor UUID
   void setSourceUUID(const utils::Identifier &uuid) {
@@ -75,19 +70,19 @@ class Connection : public core::Connectable, public std::enable_shared_from_this
   }
 
   // Set Connection Source Processor
-  void setSource(std::shared_ptr<core::Connectable> source) {
+  void setSource(core::Connectable* source) {
     source_connectable_ = source;
   }
   // ! Get Connection Source Processor
-  std::shared_ptr<core::Connectable> getSource() {
+  core::Connectable* getSource() const {
     return source_connectable_;
   }
   // Set Connection Destination Processor
-  void setDestination(std::shared_ptr<core::Connectable> dest) {
+  void setDestination(core::Connectable* dest) {
     dest_connectable_ = dest;
   }
   // ! Get Connection Destination Processor
-  std::shared_ptr<core::Connectable> getDestination() {
+  core::Connectable* getDestination() {
     return dest_connectable_;
   }
 
@@ -143,7 +138,7 @@ class Connection : public core::Connectable, public std::enable_shared_from_this
   // Check whether the queue is empty
   bool isEmpty() const;
   // Check whether the queue is full to apply back pressure
-  bool isFull();
+  bool isFull() const;
   // Get queue size
   uint64_t getQueueSize() {
     std::lock_guard<std::mutex> lock(mutex_);
@@ -183,9 +178,9 @@ class Connection : public core::Connectable, public std::enable_shared_from_this
   // Relationship for this connection
   std::set<core::Relationship> relationships_;
   // Source Processor (ProcessNode/Port)
-  std::shared_ptr<core::Connectable> source_connectable_ = nullptr;
+  core::Connectable* source_connectable_ = nullptr;
   // Destination Processor (ProcessNode/Port)
-  std::shared_ptr<core::Connectable> dest_connectable_ = nullptr;
+  core::Connectable* dest_connectable_ = nullptr;
   // Max queue size to apply back pressure
   std::atomic<uint64_t> max_queue_size_ = 0;
   // Max queue data size to apply back pressure
diff --git a/libminifi/include/CronDrivenSchedulingAgent.h b/libminifi/include/CronDrivenSchedulingAgent.h
index b0b9f1b..23a2c6c 100644
--- a/libminifi/include/CronDrivenSchedulingAgent.h
+++ b/libminifi/include/CronDrivenSchedulingAgent.h
@@ -50,9 +50,9 @@ class CronDrivenSchedulingAgent : public ThreadedSchedulingAgent {
       : ThreadedSchedulingAgent(controller_service_provider, repo, flow_repo, content_repo, configuration, thread_pool) {
   }
   // Destructor
-  virtual ~CronDrivenSchedulingAgent() = default;
+  ~CronDrivenSchedulingAgent() override = default;
   // Run function for the thread
-  utils::TaskRescheduleInfo run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+  utils::TaskRescheduleInfo run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
       const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) override;
 
   void stop() override {
diff --git a/libminifi/include/EventDrivenSchedulingAgent.h b/libminifi/include/EventDrivenSchedulingAgent.h
index d56e929..e9439a9 100644
--- a/libminifi/include/EventDrivenSchedulingAgent.h
+++ b/libminifi/include/EventDrivenSchedulingAgent.h
@@ -54,10 +54,10 @@ class EventDrivenSchedulingAgent : public ThreadedSchedulingAgent {
     time_slice_ = std::chrono::milliseconds(slice);
   }
 
-  void schedule(std::shared_ptr<core::Processor> processor) override;
+  void schedule(core::Processor* processor) override;
 
   // Run function for the thread
-  utils::TaskRescheduleInfo run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+  utils::TaskRescheduleInfo run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
       const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) override;
 
  private:
diff --git a/libminifi/include/FlowController.h b/libminifi/include/FlowController.h
index bbaa81f..2a3b10c 100644
--- a/libminifi/include/FlowController.h
+++ b/libminifi/include/FlowController.h
@@ -62,6 +62,10 @@ namespace apache {
 namespace nifi {
 namespace minifi {
 
+namespace state {
+class ProcessorController;
+}  // namespace state
+
 // Default NiFi Root Group Name
 #define DEFAULT_ROOT_GROUP_NAME ""
 
@@ -69,7 +73,7 @@ namespace minifi {
  * Flow Controller class. Generally used by FlowController factory
  * as a singleton.
  */
-class FlowController : public core::controller::ForwardingControllerServiceProvider,  public state::StateMonitor, public c2::C2Client, public std::enable_shared_from_this<FlowController> {
+class FlowController : public core::controller::ForwardingControllerServiceProvider,  public state::StateMonitor, public c2::C2Client {
  public:
   FlowController(std::shared_ptr<core::Repository> provenance_repo, std::shared_ptr<core::Repository> flow_file_repo,
                  std::shared_ptr<Configure> configure, std::unique_ptr<core::FlowConfiguration> flow_configuration,
@@ -87,13 +91,8 @@ class FlowController : public core::controller::ForwardingControllerServiceProvi
     return this->provenance_repo_;
   }
 
-  // Get the flowfile repository
-  virtual std::shared_ptr<core::Repository> getFlowFileRepository() {
-    return this->flow_file_repo_;
-  }
-
   // Load flow xml from disk, after that, create the root process group and its children, initialize the flows
-  virtual void load(const std::shared_ptr<core::ProcessGroup> &root = nullptr, bool reload = false);
+  virtual void load(std::unique_ptr<core::ProcessGroup> root = nullptr, bool reload = false);
 
   // Whether the Flow Controller is start running
   bool isRunning() override {
@@ -115,9 +114,9 @@ class FlowController : public core::controller::ForwardingControllerServiceProvi
     return -1;
   }
 
-  std::vector<std::shared_ptr<state::StateController>> getComponents(const std::string &name) override;
+  std::vector<state::StateController*> getComponents(const std::string &name) override;
 
-  std::vector<std::shared_ptr<state::StateController>> getAllComponents() override;
+  std::vector<state::StateController*> getAllComponents() override;
 
   int16_t clearConnection(const std::string &connection) override;
 
@@ -223,8 +222,6 @@ class FlowController : public core::controller::ForwardingControllerServiceProvi
 
   // Whether it has already been initialized (load the flow XML already)
   std::atomic<bool> initialized_;
-  // Thread pool for schedulers
-  utils::ThreadPool<utils::TaskRescheduleInfo> thread_pool_;
   // Flow Timer Scheduler
   std::shared_ptr<TimerDrivenSchedulingAgent> timer_scheduler_;
   // Flow Event Scheduler
@@ -237,9 +234,21 @@ class FlowController : public core::controller::ForwardingControllerServiceProvi
   std::chrono::steady_clock::time_point start_time_;
 
  private:
+  void getProcessorController(const std::string& name, std::vector<state::StateController*>& controllerVec,
+                              const std::function<std::unique_ptr<state::ProcessorController>(core::Processor&)>& controllerFactory);
+
+  void getAllProcessorControllers(std::vector<state::StateController*>& controllerVec,
+                                  const std::function<std::unique_ptr<state::ProcessorController>(core::Processor&)>& controllerFactory);
+
+  std::unique_ptr<state::ProcessorController> createController(core::Processor& processor);
+
   std::chrono::milliseconds shutdown_check_interval_{1000};
   std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<FlowController>::getLogger();
   std::string serial_number_;
+
+  // Thread pool for schedulers
+  utils::ThreadPool<utils::TaskRescheduleInfo> thread_pool_;
+  std::map<utils::Identifier, std::unique_ptr<state::ProcessorController>> processor_to_controller_;
 };
 
 }  // namespace minifi
diff --git a/libminifi/include/SchedulingAgent.h b/libminifi/include/SchedulingAgent.h
index e89a19a..d3f1d6f 100644
--- a/libminifi/include/SchedulingAgent.h
+++ b/libminifi/include/SchedulingAgent.h
@@ -88,11 +88,7 @@ class SchedulingAgent {
   }
 
   // onTrigger, return whether the yield is need
-  bool onTrigger(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext, const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory);
-  // Whether agent has work to do
-  bool hasWorkToDo(const std::shared_ptr<core::Processor>& processor);
-  // Whether the outgoing need to be backpressure
-  bool hasTooMuchOutGoing(const std::shared_ptr<core::Processor>& processor);
+  bool onTrigger(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext, const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory);
   // start
   void start() {
     running_ = true;
@@ -108,9 +104,9 @@ class SchedulingAgent {
   virtual std::future<utils::TaskRescheduleInfo> enableControllerService(std::shared_ptr<core::controller::ControllerServiceNode> &serviceNode);
   virtual std::future<utils::TaskRescheduleInfo> disableControllerService(std::shared_ptr<core::controller::ControllerServiceNode> &serviceNode);
   // schedule, overwritten by different DrivenSchedulingAgent
-  virtual void schedule(std::shared_ptr<core::Processor> processor) = 0;
+  virtual void schedule(core::Processor* processor) = 0;
   // unschedule, overwritten by different DrivenSchedulingAgent
-  virtual void unschedule(std::shared_ptr<core::Processor> processor) = 0;
+  virtual void unschedule(core::Processor* processor) = 0;
 
   SchedulingAgent(const SchedulingAgent &parent) = delete;
   SchedulingAgent &operator=(const SchedulingAgent &parent) = delete;
@@ -145,7 +141,7 @@ class SchedulingAgent {
     std::string name_;
     std::string uuid_;
 
-    explicit SchedulingInfo(const std::shared_ptr<core::Processor> &processor) :
+    explicit SchedulingInfo(const core::Processor* processor) :
       name_(processor->getName()),
       uuid_(processor->getUUIDStr()) {}
 
diff --git a/libminifi/include/ThreadedSchedulingAgent.h b/libminifi/include/ThreadedSchedulingAgent.h
index 3033afa..8d48804 100644
--- a/libminifi/include/ThreadedSchedulingAgent.h
+++ b/libminifi/include/ThreadedSchedulingAgent.h
@@ -55,14 +55,14 @@ class ThreadedSchedulingAgent : public SchedulingAgent {
   ~ThreadedSchedulingAgent() override = default;
 
   // Run function for the thread
-  virtual utils::TaskRescheduleInfo run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+  virtual utils::TaskRescheduleInfo run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
                        const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) = 0;
 
  public:
   // schedule, overwritten by different DrivenTimerDrivenSchedulingAgent
-  void schedule(std::shared_ptr<core::Processor> processor) override;
+  void schedule(core::Processor* processor) override;
   // unschedule, overwritten by different DrivenTimerDrivenSchedulingAgent
-  void unschedule(std::shared_ptr<core::Processor> processor) override;
+  void unschedule(core::Processor* processor) override;
 
   void stop() override;
 
diff --git a/libminifi/include/TimerDrivenSchedulingAgent.h b/libminifi/include/TimerDrivenSchedulingAgent.h
index c8f2a12..b4322a1 100644
--- a/libminifi/include/TimerDrivenSchedulingAgent.h
+++ b/libminifi/include/TimerDrivenSchedulingAgent.h
@@ -48,7 +48,7 @@ class TimerDrivenSchedulingAgent : public ThreadedSchedulingAgent {
   /**
    * Run function that accepts the processor, context and session factory.
    */
-  utils::TaskRescheduleInfo run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+  utils::TaskRescheduleInfo run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
       const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) override;
 
  private:
diff --git a/libminifi/include/agent/build_description.h b/libminifi/include/agent/build_description.h
index ba4f967..7eec050 100644
--- a/libminifi/include/agent/build_description.h
+++ b/libminifi/include/agent/build_description.h
@@ -23,6 +23,8 @@
 #include <string>
 #include <utility>
 #include <vector>
+#include "core/controller/ControllerService.h"
+#include "core/ClassLoader.h"
 #include "core/expect.h"
 #include "core/Property.h"
 #include "core/Relationship.h"
@@ -119,14 +121,14 @@ class ExternalBuildDescription {
 
 class BuildDescription {
  public:
-  static struct Components getClassDescriptions(const std::string group = "minifi-system") {
+  static struct Components getClassDescriptions(const std::string& group = "minifi-system") {
     static std::map<std::string, struct Components> class_mappings;
 #ifndef WIN32
     if (UNLIKELY(IsNullOrEmpty(class_mappings[group].processors_) && IsNullOrEmpty(class_mappings[group].processors_))) {
 #else
       if (class_mappings[group].processors_.empty()) {
 #endif
-      for (auto clazz : core::ClassLoader::getDefaultClassLoader().getClasses(group)) {
+      for (const auto& clazz : core::ClassLoader::getDefaultClassLoader().getClasses(group)) {
         std::string class_name = clazz;
         auto lastOfIdx = clazz.find_last_of("::");
         if (lastOfIdx != std::string::npos) {
@@ -136,15 +138,17 @@ class BuildDescription {
         }
         auto obj = core::ClassLoader::getDefaultClassLoader().instantiate(class_name, class_name);
 
-        std::shared_ptr<core::ConfigurableComponent> component = std::dynamic_pointer_cast<core::ConfigurableComponent>(obj);
+        std::unique_ptr<core::ConfigurableComponent> component{
+          utils::dynamic_unique_cast<core::ConfigurableComponent>(std::move(obj))
+        };
 
         std::string classDescriptionName = clazz;
         utils::StringUtils::replaceAll(classDescriptionName, "::", ".");
         ClassDescription description(classDescriptionName);
-        if (nullptr != component) {
-          auto processor = std::dynamic_pointer_cast<core::Processor>(obj);
-          bool is_processor = processor != nullptr;
-          bool is_controller_service = LIKELY(is_processor == true) ? false : std::dynamic_pointer_cast<core::controller::ControllerService>(obj) != nullptr;
+        if (component) {
+          auto processor = dynamic_cast<core::Processor*>(component.get());
+          const bool is_processor = processor != nullptr;
+          const bool is_controller_service = LIKELY(is_processor == true) ? false : dynamic_cast<core::controller::ControllerService*>(component.get()) != nullptr;
 
           component->initialize();
           description.class_properties_ = component->getProperties();
diff --git a/libminifi/include/c2/C2Agent.h b/libminifi/include/c2/C2Agent.h
index a25c280..0d4e28a 100644
--- a/libminifi/include/c2/C2Agent.h
+++ b/libminifi/include/c2/C2Agent.h
@@ -67,7 +67,7 @@ class C2Agent : public state::UpdateController {
 
   C2Agent(core::controller::ControllerServiceProvider *controller,
           state::Pausable *pause_handler,
-          const std::shared_ptr<state::StateMonitor> &updateSink,
+          state::StateMonitor* updateSink,
           const std::shared_ptr<Configure> &configure,
           const std::shared_ptr<utils::file::FileSystem> &filesystem = std::make_shared<utils::file::FileSystem>());
 
@@ -207,7 +207,7 @@ class C2Agent : public state::UpdateController {
   std::function<utils::TaskRescheduleInfo()> c2_producer_;
 
   // reference to the update sink, against which we will execute updates.
-  std::shared_ptr<state::StateMonitor> update_sink_;
+  state::StateMonitor* update_sink_;
 
   // functions that will be used for the udpate controller.
   std::vector<std::function<utils::TaskRescheduleInfo()>> functions_;
@@ -229,9 +229,9 @@ class C2Agent : public state::UpdateController {
 
   std::mutex heartbeat_mutex;
 
-  std::vector<std::shared_ptr<HeartbeatReporter>> heartbeat_protocols_;
+  std::vector<std::unique_ptr<HeartbeatReporter>> heartbeat_protocols_;
 
-  std::vector<std::shared_ptr<C2Trigger>> triggers_;
+  std::vector<std::unique_ptr<C2Trigger>> triggers_;
 
   std::atomic<C2Protocol*> protocol_;
 
diff --git a/libminifi/include/c2/C2Client.h b/libminifi/include/c2/C2Client.h
index 24e2338..068ec30 100644
--- a/libminifi/include/c2/C2Client.h
+++ b/libminifi/include/c2/C2Client.h
@@ -50,7 +50,7 @@ class C2Client : public core::Flow, public state::response::NodeReporter {
       std::unique_ptr<core::FlowConfiguration> flow_configuration, std::shared_ptr<utils::file::FileSystem> filesystem,
       std::shared_ptr<core::logging::Logger> logger = core::logging::LoggerFactory<C2Client>::getLogger());
 
-  void initialize(core::controller::ControllerServiceProvider *controller, state::Pausable *pause_handler, const std::shared_ptr<state::StateMonitor> &update_sink);
+  void initialize(core::controller::ControllerServiceProvider *controller, state::Pausable *pause_handler, state::StateMonitor* update_sink);
 
   std::shared_ptr<state::response::ResponseNode> getMetricsNode(const std::string& metrics_class) const override;
 
diff --git a/libminifi/include/c2/ControllerSocketProtocol.h b/libminifi/include/c2/ControllerSocketProtocol.h
index c56f66f..f12b058 100644
--- a/libminifi/include/c2/ControllerSocketProtocol.h
+++ b/libminifi/include/c2/ControllerSocketProtocol.h
@@ -49,14 +49,14 @@ class ControllerSocketProtocol : public HeartbeatReporter {
    * @param updateSink update mechanism that will be used to stop/clear elements
    * @param configuration configuration class.
    */
-  virtual void initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink,
-                          const std::shared_ptr<Configure> &configuration);
+  void initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink,
+                          const std::shared_ptr<Configure> &configuration) override;
 
   /**
    * Handles the heartbeat
    * @param payload incoming payload. From this function we only care about queue metrics.
    */
-  virtual int16_t heartbeat(const C2Payload &payload);
+  int16_t heartbeat(const C2Payload &payload) override;
 
  protected:
   /**
diff --git a/libminifi/include/c2/HeartbeatLogger.h b/libminifi/include/c2/HeartbeatLogger.h
index cd4093f..5c00c2c 100644
--- a/libminifi/include/c2/HeartbeatLogger.h
+++ b/libminifi/include/c2/HeartbeatLogger.h
@@ -34,7 +34,7 @@ class HeartbeatLogger : public RESTProtocol, public HeartbeatReporter {
  public:
   explicit HeartbeatLogger(const std::string& name, const utils::Identifier& id = {});
   int16_t heartbeat(const C2Payload &heartbeat) override;
-  void initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink, const std::shared_ptr<Configure> &configure) override;
+  void initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink, const std::shared_ptr<Configure> &configure) override;
 
  private:
   std::shared_ptr<core::logging::Logger> logger_ = core::logging::LoggerFactory<HeartbeatLogger>::getLogger();
diff --git a/libminifi/include/c2/HeartbeatReporter.h b/libminifi/include/c2/HeartbeatReporter.h
index 87c8767..88c2513 100644
--- a/libminifi/include/c2/HeartbeatReporter.h
+++ b/libminifi/include/c2/HeartbeatReporter.h
@@ -45,7 +45,7 @@ class HeartbeatReporter : public core::Connectable {
         configuration_(nullptr) {
   }
 
-  virtual void initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink,
+  virtual void initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink,
                           const std::shared_ptr<Configure> &configure) {
     controller_ = controller;
     update_sink_ = updateSink;
@@ -91,7 +91,7 @@ class HeartbeatReporter : public core::Connectable {
  protected:
   core::controller::ControllerServiceProvider* controller_;
 
-  std::shared_ptr<state::StateMonitor> update_sink_;
+  state::StateMonitor* update_sink_;
 
   std::shared_ptr<Configure> configuration_;
 };
diff --git a/libminifi/include/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.h b/libminifi/include/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.h
index 13c6ba4..5a725a2 100644
--- a/libminifi/include/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.h
+++ b/libminifi/include/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.h
@@ -31,17 +31,15 @@ namespace nifi {
 namespace minifi {
 namespace controllers {
 
-class AbstractCoreComponentStateManagerProvider : public std::enable_shared_from_this<AbstractCoreComponentStateManagerProvider>,
-                                                   public core::CoreComponentStateManagerProvider {
+class AbstractCoreComponentStateManagerProvider : public core::CoreComponentStateManagerProvider {
  public:
-  std::shared_ptr<core::CoreComponentStateManager> getCoreComponentStateManager(const utils::Identifier& uuid) override;
+  std::unique_ptr<core::CoreComponentStateManager> getCoreComponentStateManager(const utils::Identifier& uuid) override;
+
   std::map<utils::Identifier, std::unordered_map<std::string, std::string>> getAllCoreComponentStates() override;
 
-  class AbstractCoreComponentStateManager : public core::CoreComponentStateManager{
+  class AbstractCoreComponentStateManager : public core::CoreComponentStateManager {
    public:
-    AbstractCoreComponentStateManager(std::shared_ptr<AbstractCoreComponentStateManagerProvider> provider, const utils::Identifier& id);
-
-    ~AbstractCoreComponentStateManager() override;
+    AbstractCoreComponentStateManager(AbstractCoreComponentStateManagerProvider* provider, const utils::Identifier& id);
 
     bool set(const core::CoreComponentState& kvs) override;
     bool get(core::CoreComponentState& kvs) override;
@@ -60,7 +58,7 @@ class AbstractCoreComponentStateManagerProvider : public std::enable_shared_from
       CLEAR
     };
 
-    std::shared_ptr<AbstractCoreComponentStateManagerProvider> provider_;
+    AbstractCoreComponentStateManagerProvider* provider_;
     utils::Identifier id_;
     bool state_valid_;
     core::CoreComponentState state_;
@@ -77,10 +75,7 @@ class AbstractCoreComponentStateManagerProvider : public std::enable_shared_from
   virtual bool persistImpl() = 0;
 
  private:
-  void removeFromCache(utils::Identifier id);
-
   std::mutex mutex_;
-  std::map<utils::Identifier, std::weak_ptr<core::CoreComponentStateManager>> state_manager_cache_;
 };
 
 }  // namespace controllers
diff --git a/libminifi/include/core/ClassLoader.h b/libminifi/include/core/ClassLoader.h
index bf8abde..9b2bc09 100644
--- a/libminifi/include/core/ClassLoader.h
+++ b/libminifi/include/core/ClassLoader.h
@@ -116,7 +116,7 @@ class ClassLoader {
    * @return nullptr or object created from class_name definition.
    */
   template<class T = CoreComponent>
-  std::shared_ptr<T> instantiate(const std::string &class_name, const std::string &name);
+  std::unique_ptr<T> instantiate(const std::string &class_name, const std::string &name);
 
   /**
    * Instantiate object based on class_name
@@ -125,7 +125,7 @@ class ClassLoader {
    * @return nullptr or object created from class_name definition.
    */
   template<class T = CoreComponent>
-  std::shared_ptr<T> instantiate(const std::string &class_name, const utils::Identifier &uuid);
+  std::unique_ptr<T> instantiate(const std::string &class_name, const utils::Identifier &uuid);
 
   /**
    * Instantiate object based on class_name
@@ -149,7 +149,7 @@ class ClassLoader {
 };
 
 template<class T>
-std::shared_ptr<T> ClassLoader::instantiate(const std::string &class_name, const std::string &name) {
+std::unique_ptr<T> ClassLoader::instantiate(const std::string &class_name, const std::string &name) {
   std::lock_guard<std::mutex> lock(internal_mutex_);
   // allow subsequent classes to override functionality (like ProcessContextBuilder)
   for (auto& child_loader : class_loaders_) {
@@ -160,13 +160,13 @@ std::shared_ptr<T> ClassLoader::instantiate(const std::string &class_name, const
   auto factory_entry = loaded_factories_.find(class_name);
   if (factory_entry != loaded_factories_.end()) {
     auto obj = factory_entry->second->create(name);
-    return std::dynamic_pointer_cast<T>(obj);
+    return utils::dynamic_unique_cast<T>(std::move(obj));
   }
   return nullptr;
 }
 
 template<class T>
-std::shared_ptr<T> ClassLoader::instantiate(const std::string &class_name, const utils::Identifier &uuid) {
+std::unique_ptr<T> ClassLoader::instantiate(const std::string &class_name, const utils::Identifier &uuid) {
   std::lock_guard<std::mutex> lock(internal_mutex_);
   // allow subsequent classes to override functionality (like ProcessContextBuilder)
   for (auto& child_loader : class_loaders_) {
@@ -177,7 +177,7 @@ std::shared_ptr<T> ClassLoader::instantiate(const std::string &class_name, const
   auto factory_entry = loaded_factories_.find(class_name);
   if (factory_entry != loaded_factories_.end()) {
     auto obj = factory_entry->second->create(class_name, uuid);
-    return std::dynamic_pointer_cast<T>(obj);
+    return utils::dynamic_unique_cast<T>(std::move(obj));
   }
   return nullptr;
 }
diff --git a/libminifi/include/core/Connectable.h b/libminifi/include/core/Connectable.h
index f77c24b..68f9c65 100644
--- a/libminifi/include/core/Connectable.h
+++ b/libminifi/include/core/Connectable.h
@@ -82,7 +82,7 @@ class Connectable : public CoreComponent {
    * Get outgoing connection based on relationship
    * @return set of outgoing connections.
    */
-  virtual std::set<std::shared_ptr<Connectable>> getOutGoingConnections(const std::string &relationship) const;
+  virtual std::set<Connectable*> getOutGoingConnections(const std::string &relationship);
 
   virtual void put(const std::shared_ptr<FlowFile>& /*flow*/) {
   }
@@ -95,15 +95,15 @@ class Connectable : public CoreComponent {
    * Gets and sets next incoming connection
    * @return next incoming connection
    */
-  std::shared_ptr<Connectable> getNextIncomingConnection();
+  Connectable* getNextIncomingConnection();
 
-  virtual std::shared_ptr<Connectable> pickIncomingConnection();
+  virtual Connectable* pickIncomingConnection();
 
   /**
    * @return true if incoming connections > 0
    */
   bool hasIncomingConnections() const {
-    return !_incomingConnections.empty();
+    return !incoming_connections_.empty();
   }
 
   uint8_t getMaxConcurrentTasks() const {
@@ -159,7 +159,7 @@ class Connectable : public CoreComponent {
 
  protected:
   // must hold the relationship_mutex_ before calling this
-  std::shared_ptr<Connectable> getNextIncomingConnectionImpl(const std::lock_guard<std::mutex>& relationship_mutex_lock);
+  Connectable* getNextIncomingConnectionImpl(const std::lock_guard<std::mutex>& relationship_mutex_lock);
   // Penalization Period in MilliSecond
   std::atomic<std::chrono::milliseconds> penalization_period_;
 
@@ -170,12 +170,12 @@ class Connectable : public CoreComponent {
   // Autoterminated relationships
   std::map<std::string, core::Relationship> auto_terminated_relationships_;
 
-  // Incoming connection Iterator
-  std::set<std::shared_ptr<Connectable>>::iterator incoming_connections_Iter;
   // Incoming connections
-  std::set<std::shared_ptr<Connectable>> _incomingConnections;
+  std::set<Connectable*> incoming_connections_;
+  // Incoming connection Iterator
+  decltype(incoming_connections_)::iterator incoming_connections_Iter;
   // Outgoing connections map based on Relationship name
-  std::map<std::string, std::set<std::shared_ptr<Connectable>>> out_going_connections_;
+  std::map<std::string, std::set<Connectable*>> outgoing_connections_;
 
   // Mutex for protection
   mutable std::mutex relationship_mutex_;
diff --git a/libminifi/include/core/Core.h b/libminifi/include/core/Core.h
index aa7ed90..cc9a266 100644
--- a/libminifi/include/core/Core.h
+++ b/libminifi/include/core/Core.h
@@ -96,11 +96,11 @@ static inline std::string getClassName() {
 }
 
 template<typename T>
-std::shared_ptr<T> instantiate(const std::string name = {}) {
+std::unique_ptr<T> instantiate(const std::string name = {}) {
   if (name.empty()) {
-    return std::make_shared<T>();
+    return std::make_unique<T>();
   } else {
-    return std::make_shared<T>(name);
+    return std::make_unique<T>(name);
   }
 }
 
@@ -157,7 +157,7 @@ class CoreComponent {
   // A global unique identifier
   utils::Identifier uuid_;
 
-  // Connectable's name
+  // CoreComponent's name
   std::string name_;
 };
 
diff --git a/libminifi/include/core/CoreComponentState.h b/libminifi/include/core/CoreComponentState.h
index cabf56e..a0662a6 100644
--- a/libminifi/include/core/CoreComponentState.h
+++ b/libminifi/include/core/CoreComponentState.h
@@ -64,9 +64,9 @@ class CoreComponentStateManagerProvider {
  public:
   virtual ~CoreComponentStateManagerProvider() = default;
 
-  virtual std::shared_ptr<CoreComponentStateManager> getCoreComponentStateManager(const utils::Identifier& uuid) = 0;
+  virtual std::unique_ptr<CoreComponentStateManager> getCoreComponentStateManager(const utils::Identifier& uuid) = 0;
 
-  virtual std::shared_ptr<CoreComponentStateManager> getCoreComponentStateManager(const CoreComponent& component) {
+  virtual std::unique_ptr<CoreComponentStateManager> getCoreComponentStateManager(const CoreComponent& component) {
     return getCoreComponentStateManager(component.getUUID());
   }
 
diff --git a/libminifi/include/core/Flow.h b/libminifi/include/core/Flow.h
index 3013a83..fe8e5d5 100644
--- a/libminifi/include/core/Flow.h
+++ b/libminifi/include/core/Flow.h
@@ -45,7 +45,7 @@ class Flow {
 
   virtual utils::Identifier getControllerUUID() const = 0;
 
-  std::shared_ptr<core::ProcessGroup> root_;
+  std::unique_ptr<core::ProcessGroup> root_;
   std::shared_ptr<core::Repository> provenance_repo_;
   std::shared_ptr<core::Repository> flow_file_repo_;
   std::shared_ptr<core::ContentRepository> content_repo_;
diff --git a/libminifi/include/core/FlowConfiguration.h b/libminifi/include/core/FlowConfiguration.h
index 0c86b23..ec278c7 100644
--- a/libminifi/include/core/FlowConfiguration.h
+++ b/libminifi/include/core/FlowConfiguration.h
@@ -74,8 +74,8 @@ class FlowConfiguration : public CoreComponent {
   ~FlowConfiguration() override;
 
   // Create Processor (Node/Input/Output Port) based on the name
-  std::shared_ptr<core::Processor> createProcessor(const std::string &name, const utils::Identifier &uuid);
-  std::shared_ptr<core::Processor> createProcessor(const std::string &name, const std::string &fullname, const utils::Identifier &uuid);
+  std::unique_ptr<core::Processor> createProcessor(const std::string &name, const utils::Identifier &uuid);
+  std::unique_ptr<core::Processor> createProcessor(const std::string &name, const std::string &fullname, const utils::Identifier &uuid);
   // Create Root Processor Group
 
   std::unique_ptr<core::ProcessGroup> createRootProcessGroup(const std::string &name, const utils::Identifier &uuid, int version);
@@ -86,9 +86,9 @@ class FlowConfiguration : public CoreComponent {
       const utils::Identifier &uuid);
 
   // Create Connection
-  std::shared_ptr<minifi::Connection> createConnection(const std::string &name, const utils::Identifier &uuid) const;
+  std::unique_ptr<minifi::Connection> createConnection(const std::string &name, const utils::Identifier &uuid) const;
   // Create Provenance Report Task
-  std::shared_ptr<core::Processor> createProvenanceReportTask(void);
+  std::unique_ptr<core::reporting::SiteToSiteProvenanceReportingTask> createProvenanceReportTask();
 
   std::shared_ptr<state::response::FlowVersion> getFlowVersion() const {
     return flow_version_;
diff --git a/libminifi/include/core/FlowFile.h b/libminifi/include/core/FlowFile.h
index 2e1899b..cc55913 100644
--- a/libminifi/include/core/FlowFile.h
+++ b/libminifi/include/core/FlowFile.h
@@ -237,12 +237,12 @@ class FlowFile : public CoreComponent, public ReferenceContainer {
    * Sets the original connection with a shared pointer.
    * @param connection shared connection.
    */
-  void setConnection(const std::shared_ptr<core::Connectable>& connection);
+  void setConnection(core::Connectable* connection);
   /**
    * Returns the original connection referenced by this record.
    * @return shared original connection pointer.
    */
-  [[nodiscard]] std::shared_ptr<core::Connectable> getConnection() const;
+  [[nodiscard]] Connectable* getConnection() const;
 
   void setStoredToRepository(bool storedInRepository) {
     stored = storedInRepository;
@@ -285,7 +285,7 @@ class FlowFile : public CoreComponent, public ReferenceContainer {
   std::vector<utils::Identifier> lineage_Identifiers_;
 
   // Orginal connection queue that this flow file was dequeued from
-  std::shared_ptr<core::Connectable> connection_;
+  core::Connectable* connection_ = nullptr;
 
   static std::shared_ptr<logging::Logger> logger_;
   static std::shared_ptr<utils::IdGenerator> id_generator_;
diff --git a/libminifi/include/core/Funnel.h b/libminifi/include/core/Funnel.h
index ba38b22..0d7dba6 100644
--- a/libminifi/include/core/Funnel.h
+++ b/libminifi/include/core/Funnel.h
@@ -20,6 +20,7 @@
 #include <string>
 #include <memory>
 
+#include "logging/LoggerConfiguration.h"
 #include "Processor.h"
 
 namespace org {
diff --git a/libminifi/include/core/ObjectFactory.h b/libminifi/include/core/ObjectFactory.h
index 1f8010d..2a777e8 100644
--- a/libminifi/include/core/ObjectFactory.h
+++ b/libminifi/include/core/ObjectFactory.h
@@ -46,28 +46,28 @@ class ObjectFactory {
   virtual ~ObjectFactory() = default;
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a unique pointer to a new processor.
    */
-  virtual std::shared_ptr<CoreComponent> create(const std::string& /*name*/) {
+  virtual std::unique_ptr<CoreComponent> create(const std::string& /*name*/) {
     return nullptr;
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a raw pointer to a new processor.
    */
   virtual CoreComponent *createRaw(const std::string& /*name*/) {
     return nullptr;
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a unique pointer to a new processor.
    */
-  virtual std::shared_ptr<CoreComponent> create(const std::string& /*name*/, const utils::Identifier& /*uuid*/) {
+  virtual std::unique_ptr<CoreComponent> create(const std::string& /*name*/, const utils::Identifier& /*uuid*/) {
     return nullptr;
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a raw pointer to a new processor.
    */
   virtual CoreComponent* createRaw(const std::string& /*name*/, const utils::Identifier& /*uuid*/) {
     return nullptr;
@@ -99,23 +99,21 @@ class DefautObjectFactory : public ObjectFactory {
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a unique pointer to a new processor.
    */
-  std::shared_ptr<CoreComponent> create(const std::string &name) override {
-    std::shared_ptr<T> ptr = std::make_shared<T>(name);
-    return std::static_pointer_cast<CoreComponent>(ptr);
+  std::unique_ptr<CoreComponent> create(const std::string &name) override {
+    return std::make_unique<T>(name);
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a unique pointer to a new processor.
    */
-  std::shared_ptr<CoreComponent> create(const std::string &name, const utils::Identifier &uuid) override {
-    std::shared_ptr<T> ptr = std::make_shared<T>(name, uuid);
-    return std::static_pointer_cast<CoreComponent>(ptr);
+  std::unique_ptr<CoreComponent> create(const std::string &name, const utils::Identifier &uuid) override {
+    return std::make_unique<T>(name, uuid);
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a raw pointer to a new processor.
    */
   CoreComponent* createRaw(const std::string &name) override {
     T *ptr = new T(name);
@@ -123,7 +121,7 @@ class DefautObjectFactory : public ObjectFactory {
   }
 
   /**
-   * Create a shared pointer to a new processor.
+   * Create a raw pointer to a new processor.
    */
   CoreComponent* createRaw(const std::string &name, const utils::Identifier &uuid) override {
     T *ptr = new T(name, uuid);
diff --git a/libminifi/include/core/ProcessContext.h b/libminifi/include/core/ProcessContext.h
index c134305..317dca5 100644
--- a/libminifi/include/core/ProcessContext.h
+++ b/libminifi/include/core/ProcessContext.h
@@ -254,14 +254,14 @@ class ProcessContext : public controller::ControllerServiceLookup, public core::
 
   static constexpr char const* DefaultStateManagerProviderName = "defaultstatemanagerprovider";
 
-  std::shared_ptr<CoreComponentStateManager> getStateManager() {
+  CoreComponentStateManager* getStateManager() {
     if (state_manager_provider_ == nullptr) {
       return nullptr;
     }
     if (!state_manager_) {
       state_manager_ = state_manager_provider_->getCoreComponentStateManager(*processor_node_);
     }
-    return state_manager_;
+    return state_manager_.get();
   }
 
   bool hasStateManager() const {
@@ -388,7 +388,7 @@ class ProcessContext : public controller::ControllerServiceLookup, public core::
 
   controller::ControllerServiceProvider* controller_service_provider_;
   std::shared_ptr<core::CoreComponentStateManagerProvider> state_manager_provider_;
-  std::shared_ptr<CoreComponentStateManager> state_manager_;
+  std::unique_ptr<CoreComponentStateManager> state_manager_;
   std::shared_ptr<core::Repository> repo_;
   std::shared_ptr<core::Repository> flow_repo_;
   std::shared_ptr<core::ContentRepository> content_repo_;
diff --git a/libminifi/include/core/ProcessGroup.h b/libminifi/include/core/ProcessGroup.h
index 8b595a1..1ca0f7d 100644
--- a/libminifi/include/core/ProcessGroup.h
+++ b/libminifi/include/core/ProcessGroup.h
@@ -27,6 +27,7 @@
 #include <atomic>
 #include <algorithm>
 #include <set>
+#include <utility>
 
 #include "Processor.h"
 #include "Funnel.h"
@@ -47,6 +48,12 @@ namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
+
+namespace state {
+class StateController;
+class ProcessorController;
+}  // namespace state
+
 namespace core {
 
 // Process Group Type
@@ -54,7 +61,6 @@ enum ProcessGroupType {
   ROOT_PROCESS_GROUP = 0,
   SIMPLE_PROCESS_GROUP,
   REMOTE_PROCESS_GROUP,
-  MAX_PROCESS_GROUP_TYPE
 };
 
 #define ONSCHEDULE_RETRY_INTERVAL 30000  // millisecs
@@ -77,24 +83,19 @@ class ProcessGroup : public CoreComponent {
   ProcessGroup(ProcessGroupType type, const std::string& name, const utils::Identifier& uuid);
   ProcessGroup(ProcessGroupType type, const std::string& name, const utils::Identifier& uuid, int version);
   // Destructor
-  virtual ~ProcessGroup();
+  ~ProcessGroup() override;
   // Set URL
   void setURL(std::string url) {
-    url_ = url;
+    url_ = std::move(url);
   }
   // Get URL
-  std::string getURL(void) {
+  std::string getURL() {
     return (url_);
   }
   // SetTransmitting
   void setTransmitting(bool val) {
     transmitting_ = val;
   }
-  // Get Transmitting
-  bool getTransmitting() {
-    return transmitting_;
-  }
-  // setTimeout
   void setTimeout(uint64_t time) {
     timeout_ = time;
   }
@@ -117,27 +118,18 @@ class ProcessGroup : public CoreComponent {
   void setHttpProxyHost(std::string &host) {
     proxy_.host = host;
   }
-  std::string getHttpProxyHost() {
+  std::string getHttpProxyHost() const {
     return proxy_.host;
   }
   void setHttpProxyUserName(std::string &username) {
     proxy_.username = username;
   }
-  std::string getHttpProxyUserName() {
-    return proxy_.username;
-  }
   void setHttpProxyPassWord(std::string &password) {
     proxy_.password = password;
   }
-  std::string getHttpProxyPassWord() {
-    return proxy_.password;
-  }
   void setHttpProxyPort(int port) {
     proxy_.port = port;
   }
-  int getHttpProxyPort() {
-    return proxy_.port;
-  }
   utils::HTTPProxy getHTTPProxy() {
     return proxy_;
   }
@@ -146,7 +138,7 @@ class ProcessGroup : public CoreComponent {
     yield_period_msec_ = period;
   }
   // Get Processor yield period in MilliSecond
-  std::chrono::milliseconds getYieldPeriodMsec(void) {
+  std::chrono::milliseconds getYieldPeriodMsec() {
     return (yield_period_msec_);
   }
 
@@ -158,16 +150,18 @@ class ProcessGroup : public CoreComponent {
     return onschedule_retry_msec_;
   }
 
-  // getVersion
-  int getVersion() {
+  int getVersion() const {
     return config_version_;
   }
-  // Start Processing
-  void startProcessing(const std::shared_ptr<TimerDrivenSchedulingAgent>& timeScheduler, const std::shared_ptr<EventDrivenSchedulingAgent> &eventScheduler, const std::shared_ptr<CronDrivenSchedulingAgent> &cronScheduler); // NOLINT
-  // Stop Processing
-  void stopProcessing(const std::shared_ptr<TimerDrivenSchedulingAgent>& timeScheduler, const std::shared_ptr<EventDrivenSchedulingAgent> &eventScheduler, const std::shared_ptr<CronDrivenSchedulingAgent> &cronScheduler, const std::function<bool(const std::shared_ptr<Processor>&)>& filter = [] (const std::shared_ptr<Processor>&) {return true;}); // NOLINT
-  // Whether it is root process group
-  bool isRootProcessGroup();
+
+  void startProcessing(const std::shared_ptr<TimerDrivenSchedulingAgent>& timeScheduler,
+                       const std::shared_ptr<EventDrivenSchedulingAgent> &eventScheduler,
+                       const std::shared_ptr<CronDrivenSchedulingAgent> &cronScheduler);
+
+  void stopProcessing(const std::shared_ptr<TimerDrivenSchedulingAgent>& timeScheduler,
+                      const std::shared_ptr<EventDrivenSchedulingAgent>& eventScheduler,
+                      const std::shared_ptr<CronDrivenSchedulingAgent>& cronScheduler,
+                      const std::function<bool(const Processor*)>& filter = nullptr);
 
   bool isRemoteProcessGroup();
   // set parent process group
@@ -176,29 +170,27 @@ class ProcessGroup : public CoreComponent {
     parent_process_group_ = parent;
   }
   // get parent process group
-  ProcessGroup *getParent(void) {
+  ProcessGroup *getParent() {
     std::lock_guard<std::recursive_mutex> lock(mutex_);
     return parent_process_group_;
   }
   // Add processor
-  void addProcessor(const std::shared_ptr<Processor>& processor);
-  // Remove processor
-  void removeProcessor(const std::shared_ptr<Processor>& processor);
+  void addProcessor(std::unique_ptr<Processor> processor);
   // Add child processor group
   void addProcessGroup(std::unique_ptr<ProcessGroup> child);
   // ! Add connections
-  void addConnection(const std::shared_ptr<Connection>& connection);
+  void addConnection(std::unique_ptr<Connection> connection);
   // Generic find
   template <typename Fun>
-  std::shared_ptr<Processor> findProcessor(Fun condition, Traverse traverse) const {
+  Processor* findProcessor(Fun condition, Traverse traverse) const {
     std::lock_guard<std::recursive_mutex> lock(mutex_);
     const auto found = std::find_if(processors_.cbegin(), processors_.cend(), condition);
     if (found != processors_.cend()) {
-      return *found;
+      return found->get();
     }
     for (const auto& processGroup : child_process_groups_) {
       if (processGroup->isRemoteProcessGroup() || traverse == Traverse::IncludeChildren) {
-        std::shared_ptr<Processor> processor = processGroup->findProcessor(condition, traverse);
+        const auto processor = processGroup->findProcessor(condition, traverse);
         if (processor) {
           return processor;
         }
@@ -207,11 +199,12 @@ class ProcessGroup : public CoreComponent {
     return nullptr;
   }
   // findProcessor based on UUID
-  std::shared_ptr<Processor> findProcessorById(const utils::Identifier& uuid, Traverse traverse = Traverse::IncludeChildren) const;
+  Processor* findProcessorById(const utils::Identifier& uuid, Traverse traverse = Traverse::IncludeChildren) const;
   // findProcessor based on name
-  std::shared_ptr<Processor> findProcessorByName(const std::string &processorName, Traverse traverse = Traverse::IncludeChildren) const;
+  Processor* findProcessorByName(const std::string &processorName, Traverse traverse = Traverse::IncludeChildren) const;
+
+  void getAllProcessors(std::vector<Processor*>& processor_vec) const;
 
-  void getAllProcessors(std::vector<std::shared_ptr<Processor>> &processor_vec);
   /**
    * Add controller service
    * @param nodeId node identifier
@@ -226,16 +219,14 @@ class ProcessGroup : public CoreComponent {
    */
   std::shared_ptr<core::controller::ControllerServiceNode> findControllerService(const std::string &nodeId);
 
-  // removeConnection
-  void removeConnection(const std::shared_ptr<Connection>& connection);
   // update property value
-  void updatePropertyValue(std::string processorName, std::string propertyName, std::string propertyValue);
+  void updatePropertyValue(const std::string& processorName, const std::string& propertyName, const std::string& propertyValue);
 
-  void getConnections(std::map<std::string, std::shared_ptr<Connection>> &connectionMap);
+  void getConnections(std::map<std::string, Connection*>& connectionMap);
 
-  void getConnections(std::map<std::string, std::shared_ptr<Connectable>> &connectionMap);
+  void getConnections(std::map<std::string, Connectable*>& connectionMap);
 
-  void getFlowFileContainers(std::map<std::string, std::shared_ptr<Connectable>> &containers) const;
+  void getFlowFileContainers(std::map<std::string, Connectable*>& containers) const;
 
   void drainConnections();
 
@@ -251,11 +242,11 @@ class ProcessGroup : public CoreComponent {
   // Process Group Type
   const ProcessGroupType type_;
   // Processors (ProcessNode) inside this process group which include Input/Output Port, Remote Process Group input/Output port
-  std::set<std::shared_ptr<Processor>> processors_;
-  std::set<std::shared_ptr<Processor>> failed_processors_;
+  std::set<std::unique_ptr<Processor>> processors_;
+  std::set<Processor*> failed_processors_;
   std::set<std::unique_ptr<ProcessGroup>> child_process_groups_;
   // Connections between the processor inside the group;
-  std::set<std::shared_ptr<Connection>> connections_;
+  std::set<std::unique_ptr<Connection>> connections_;
   // Parent Process Group
   ProcessGroup* parent_process_group_;
   // Yield Period in Milliseconds
diff --git a/libminifi/include/core/ProcessSession.h b/libminifi/include/core/ProcessSession.h
index 63391f8..171c446 100644
--- a/libminifi/include/core/ProcessSession.h
+++ b/libminifi/include/core/ProcessSession.h
@@ -183,11 +183,11 @@ class ProcessSession : public ReferenceContainer {
   RouteResult routeFlowFile(const std::shared_ptr<FlowFile>& record);
 
   void persistFlowFilesBeforeTransfer(
-      std::map<std::shared_ptr<Connectable>, std::vector<std::shared_ptr<core::FlowFile>>>& transactionMap,
+      std::map<Connectable*, std::vector<std::shared_ptr<core::FlowFile>>>& transactionMap,
       const std::map<utils::Identifier, FlowFileUpdate>& modifiedFlowFiles);
 
   void ensureNonNullResourceClaim(
-      const std::map<std::shared_ptr<Connectable>, std::vector<std::shared_ptr<core::FlowFile>>>& transactionMap);
+      const std::map<Connectable*, std::vector<std::shared_ptr<core::FlowFile>>>& transactionMap);
 
   // Clone the flow file during transfer to multiple connections for a relationship
   std::shared_ptr<core::FlowFile> cloneDuringTransfer(const std::shared_ptr<core::FlowFile> &parent);
@@ -200,7 +200,7 @@ class ProcessSession : public ReferenceContainer {
 
   std::shared_ptr<ContentSession> content_session_;
 
-  std::shared_ptr<CoreComponentStateManager> stateManager_;
+  CoreComponentStateManager* stateManager_;
 
   static std::shared_ptr<utils::IdGenerator> id_generator_;
 };
diff --git a/libminifi/include/core/Processor.h b/libminifi/include/core/Processor.h
index d5569db..c08a49f 100644
--- a/libminifi/include/core/Processor.h
+++ b/libminifi/include/core/Processor.h
@@ -25,28 +25,17 @@
 #include <chrono>
 #include <condition_variable>
 #include <functional>
-#include <map>
 #include <memory>
 #include <mutex>
-#include <queue>
-#include <set>
-#include <stack>
 #include <string>
-#include <vector>
 #include <unordered_set>
 #include <unordered_map>
+#include <utility>
 
 #include "ConfigurableComponent.h"
 #include "Connectable.h"
-#include "Connection.h"
 #include "Core.h"
 #include "core/Annotation.h"
-#include "io/StreamFactory.h"
-#include "ProcessContext.h"
-#include "ProcessSession.h"
-#include "ProcessSessionFactory.h"
-#include "Property.h"
-#include "Relationship.h"
 #include "Scheduling.h"
 #include "utils/TimeUtil.h"
 
@@ -54,8 +43,19 @@ namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
+
+class Connection;
+
+namespace io {
+class StreamFactory;
+}
+
 namespace core {
 
+class ProcessContext;
+class ProcessSession;
+class ProcessSessionFactory;
+
 // Minimum scheduling period in Nano Second
 constexpr std::chrono::nanoseconds MINIMUM_SCHEDULING_NANOS{30000};
 
@@ -63,13 +63,10 @@ constexpr std::chrono::nanoseconds MINIMUM_SCHEDULING_NANOS{30000};
 
 #define BUILDING_DLL 1
 // Processor Class
-class Processor : public Connectable, public ConfigurableComponent, public std::enable_shared_from_this<Processor> {
+class Processor : public Connectable, public ConfigurableComponent {
  public:
   Processor(const std::string& name, const utils::Identifier& uuid);
   explicit Processor(const std::string& name);
-  virtual ~Processor() {
-    notifyStop();
-  }
 
   bool isRunning() override;
   // Set Processor Scheduled State
@@ -86,14 +83,6 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
   SchedulingStrategy getSchedulingStrategy() const {
     return strategy_;
   }
-  // Set Processor Loss Tolerant
-  void setlossTolerant(bool lossTolerant) {
-    loss_tolerant_ = lossTolerant;
-  }
-  // Get Processor Loss Tolerant
-  bool getlossTolerant() const {
-    return loss_tolerant_;
-  }
   // Set Processor Scheduling Period in Nano Second
   void setSchedulingPeriodNano(std::chrono::nanoseconds period) {
     scheduling_period_nano_ = std::max(MINIMUM_SCHEDULING_NANOS, period);
@@ -115,7 +104,7 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
    * Returns the cron period
    * @return cron period
    */
-  const std::string getCronPeriod() const {
+  std::string getCronPeriod() const {
     return cron_period_;
   }
 
@@ -185,8 +174,7 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
   // Whether flow file queue full in any of the outgoing connection
   bool flowFilesOutGoingFull() const;
 
-  bool addConnection(std::shared_ptr<Connectable> connection);
-  void removeConnection(std::shared_ptr<Connectable> connection);
+  bool addConnection(Connectable* connection);
 
   virtual void onTrigger(const std::shared_ptr<ProcessContext> &context, const std::shared_ptr<ProcessSessionFactory> &sessionFactory);
   void onTrigger(ProcessContext *context, ProcessSessionFactory *sessionFactory);
@@ -221,7 +209,7 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
   bool isWorkAvailable() override;
 
   void setStreamFactory(std::shared_ptr<minifi::io::StreamFactory> stream_factory) {
-    stream_factory_ = stream_factory;
+    stream_factory_ = std::move(stream_factory);
   }
 
   bool supportsDynamicProperties() override {
@@ -230,7 +218,7 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
 
   bool isThrottledByBackpressure() const;
 
-  std::shared_ptr<Connectable> pickIncomingConnection() override;
+  Connectable* pickIncomingConnection() override;
 
   void validateAnnotations() const;
 
@@ -245,8 +233,6 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
   // Processor state
   std::atomic<ScheduledState> state_;
 
-  // lossTolerant
-  std::atomic<bool> loss_tolerant_;
   // SchedulePeriod in Nano Seconds
   std::atomic<std::chrono::nanoseconds> scheduling_period_nano_;
   // Run Duration in Nano Seconds
@@ -281,7 +267,7 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
   // must hold the graphMutex
   void updateReachability(const std::lock_guard<std::mutex>& graph_lock, bool force = false);
 
-  static bool partOfCycle(const std::shared_ptr<Connection>& conn);
+  static bool partOfCycle(Connection* conn);
 
   virtual annotation::Input getInputRequirement() const {
       // default input requirement
@@ -289,13 +275,12 @@ class Processor : public Connectable, public ConfigurableComponent, public std::
   }
 
   // an outgoing connection allows us to reach these nodes
-  std::unordered_map<std::shared_ptr<Connection>, std::unordered_set<std::shared_ptr<const Processor>>> reachable_processors_;
+  std::unordered_map<Connection*, std::unordered_set<Processor*>> reachable_processors_;
 
   std::shared_ptr<logging::Logger> logger_;
 };
 
 }  // namespace core
-/* namespace core */
 }  // namespace minifi
 }  // namespace nifi
 }  // namespace apache
diff --git a/libminifi/include/core/ProcessorNode.h b/libminifi/include/core/ProcessorNode.h
index a0ee009..52578d0 100644
--- a/libminifi/include/core/ProcessorNode.h
+++ b/libminifi/include/core/ProcessorNode.h
@@ -38,11 +38,13 @@ namespace core {
  */
 class ProcessorNode : public ConfigurableComponent, public Connectable {
  public:
-  explicit ProcessorNode(const std::shared_ptr<Connectable> &processor);
+  explicit ProcessorNode(Connectable* processor);
 
   ProcessorNode(const ProcessorNode &other) = delete;
   ProcessorNode(ProcessorNode &&other) = delete;
 
+  ~ProcessorNode() override;
+
   ProcessorNode& operator=(const ProcessorNode &other) = delete;
   ProcessorNode& operator=(ProcessorNode &&other) = delete;
 
@@ -52,7 +54,7 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @param value value passed in by reference
    * @return result of getting property.
    */
-  std::shared_ptr<Connectable> getProcessor() const {
+  Connectable* getProcessor() const {
     return processor_;
   }
 
@@ -68,7 +70,7 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    */
   template<typename T>
   bool getProperty(const std::string &name, T &value) {
-    const std::shared_ptr<ConfigurableComponent> processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     if (nullptr != processor_cast) {
       return processor_cast->getProperty<T>(name, value);
     } else {
@@ -81,8 +83,8 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @param value property value.
    * @return result of setting property.
    */
-  bool setProperty(const std::string &name, std::string value) {
-    const std::shared_ptr<ConfigurableComponent> processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+  bool setProperty(const std::string &name, const std::string& value) {
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     bool ret = ConfigurableComponent::setProperty(name, value);
     if (nullptr != processor_cast)
       ret = processor_cast->setProperty(name, value);
@@ -97,7 +99,7 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @return result of getting property.
    */
   bool getDynamicProperty(const std::string name, std::string &value) const {
-    const auto &processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     if (processor_cast) {
       return processor_cast->getDynamicProperty(name, value);
     } else {
@@ -123,8 +125,8 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @param value property value.
    * @return result of setting property.
    */
-  bool setDynamicProperty(const std::string name, std::string value) {
-    const auto &processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+  bool setDynamicProperty(const std::string& name, const std::string& value) {
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     auto ret = ConfigurableComponent::setDynamicProperty(name, value);
 
     if (processor_cast) {
@@ -141,7 +143,7 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @return result of getting property.
    */
   std::vector<std::string> getDynamicPropertyKeys() const {
-    const auto &processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     if (processor_cast) {
       return processor_cast->getDynamicPropertyKeys();
     } else {
@@ -155,8 +157,8 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @param value property value.
    * @return whether property was set or not
    */
-  bool setProperty(const Property &prop, std::string value) {
-    const std::shared_ptr<ConfigurableComponent> processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+  bool setProperty(const Property &prop, const std::string& value) {
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     bool ret = ConfigurableComponent::setProperty(prop, value);
     if (nullptr != processor_cast)
       ret = processor_cast->setProperty(prop, value);
@@ -169,8 +171,8 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * @param supported properties
    * @return result of set operation.
    */
-  bool setSupportedProperties(std::set<Property> properties) {
-    const std::shared_ptr<ConfigurableComponent> processor_cast = std::dynamic_pointer_cast<ConfigurableComponent>(processor_);
+  bool setSupportedProperties(const std::set<Property>& properties) {
+    const auto processor_cast = dynamic_cast<ConfigurableComponent*>(processor_);
     bool ret = ConfigurableComponent::setSupportedProperties(properties);
     if (nullptr != processor_cast)
       ret = processor_cast->setSupportedProperties(properties);
@@ -225,7 +227,7 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * Get outgoing connection based on relationship
    * @return set of outgoing connections.
    */
-  std::set<std::shared_ptr<Connectable>> getOutGoingConnections(const std::string& relationship) const override {
+  std::set<Connectable*> getOutGoingConnections(const std::string& relationship) override {
     return processor_->getOutGoingConnections(relationship);
   }
 
@@ -233,11 +235,11 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
    * Get next incoming connection
    * @return next incoming connection
    */
-  std::shared_ptr<Connectable> getNextIncomingConnection() {
+  Connectable* getNextIncomingConnection() {
     return processor_->getNextIncomingConnection();
   }
 
-  std::shared_ptr<Connectable> pickIncomingConnection() override {
+  Connectable* pickIncomingConnection() override {
     return processor_->pickIncomingConnection();
   }
 
@@ -286,8 +288,6 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
 
   bool isWorkAvailable() override;
 
-  virtual ~ProcessorNode();
-
  protected:
   bool canEdit() override {
     return !processor_->isRunning();
@@ -296,7 +296,7 @@ class ProcessorNode : public ConfigurableComponent, public Connectable {
   /**
    * internal connectable.
    */
-  std::shared_ptr<Connectable> processor_;
+  Connectable* processor_;
 };
 
 }  // namespace core
diff --git a/libminifi/include/core/Repository.h b/libminifi/include/core/Repository.h
index 79bdeba..3380451 100644
--- a/libminifi/include/core/Repository.h
+++ b/libminifi/include/core/Repository.h
@@ -114,12 +114,12 @@ class Repository : public virtual core::SerializableComponent, public core::Trac
     return found;
   }
 
-  void setConnectionMap(std::map<std::string, std::shared_ptr<core::Connectable>> &connectionMap) {
-    this->connectionMap = connectionMap;
+  void setConnectionMap(std::map<std::string, core::Connectable*> connectionMap) {
+    connection_map_ = std::move(connectionMap);
   }
 
-  void setContainers(std::map<std::string, std::shared_ptr<core::Connectable>> &containers) {
-    this->containers = containers;
+  void setContainers(std::map<std::string, core::Connectable*> containers) {
+    containers_ = std::move(containers);
   }
 
   virtual bool Get(const std::string& /*key*/, std::string& /*value*/) {
@@ -141,7 +141,7 @@ class Repository : public virtual core::SerializableComponent, public core::Trac
   // Start the repository monitor thread
   virtual void start();
   // Stop the repository monitor thread
-  virtual void stop();
+  void stop();
   // whether the repo is full
   virtual bool isFull() {
     return repo_full_;
@@ -237,9 +237,9 @@ class Repository : public virtual core::SerializableComponent, public core::Trac
   Repository &operator=(const Repository &parent) = delete;
 
  protected:
-  std::map<std::string, std::shared_ptr<core::Connectable>> containers;
+  std::map<std::string, core::Connectable*> containers_;
 
-  std::map<std::string, std::shared_ptr<core::Connectable>> connectionMap;
+  std::map<std::string, core::Connectable*> connection_map_;
   // Mutex for protection
   std::mutex mutex_;
   // repository directory
diff --git a/libminifi/include/core/RepositoryFactory.h b/libminifi/include/core/RepositoryFactory.h
index 507873b..2a56728 100644
--- a/libminifi/include/core/RepositoryFactory.h
+++ b/libminifi/include/core/RepositoryFactory.h
@@ -39,7 +39,7 @@ namespace core {
  * @param fail_safe determines whether or not to make the default class if configuration_class_name is invalid
  * @param repo_name name of the repository
  */
-std::shared_ptr<core::Repository> createRepository(const std::string configuration_class_name, bool fail_safe = false, const std::string repo_name = "");
+std::unique_ptr<core::Repository> createRepository(const std::string& configuration_class_name, bool fail_safe = false, const std::string& repo_name = "");
 
 /**
  * Create a context repository
@@ -47,7 +47,7 @@ std::shared_ptr<core::Repository> createRepository(const std::string configurati
  * @param fail_safe determines whether or not to make the default class if configuration_class_name is invalid
  * @param repo_name name of the repository
  */
-std::shared_ptr<core::ContentRepository> createContentRepository(const std::string configuration_class_name, bool fail_safe = false, const std::string repo_name = "");
+std::unique_ptr<core::ContentRepository> createContentRepository(const std::string& configuration_class_name, bool fail_safe = false, const std::string& repo_name = "");
 
 }  // namespace core
 }  // namespace minifi
diff --git a/libminifi/include/core/controller/StandardControllerServiceNode.h b/libminifi/include/core/controller/StandardControllerServiceNode.h
index c335b5e..8a710d6 100644
--- a/libminifi/include/core/controller/StandardControllerServiceNode.h
+++ b/libminifi/include/core/controller/StandardControllerServiceNode.h
@@ -48,10 +48,6 @@ class StandardControllerServiceNode : public ControllerServiceNode {
         logger_(logging::LoggerFactory<StandardControllerServiceNode>::getLogger()) {
   }
 
-  std::shared_ptr<core::ProcessGroup> &getProcessGroup();
-
-  void setProcessGroup(std::shared_ptr<ProcessGroup> &processGroup);
-
   StandardControllerServiceNode(const StandardControllerServiceNode &other) = delete;
   StandardControllerServiceNode &operator=(const StandardControllerServiceNode &parent) = delete;
 
@@ -88,9 +84,6 @@ class StandardControllerServiceNode : public ControllerServiceNode {
   // controller service provider.
   std::shared_ptr<ControllerServiceProvider> provider;
 
-  // process group.
-  std::shared_ptr<core::ProcessGroup> process_group_;
-
   std::mutex mutex_;
 
  private:
diff --git a/libminifi/include/core/controller/StandardControllerServiceProvider.h b/libminifi/include/core/controller/StandardControllerServiceProvider.h
index faa2106..c940251 100644
--- a/libminifi/include/core/controller/StandardControllerServiceProvider.h
+++ b/libminifi/include/core/controller/StandardControllerServiceProvider.h
@@ -42,7 +42,7 @@ namespace controller {
 
 class StandardControllerServiceProvider : public ControllerServiceProvider, public std::enable_shared_from_this<StandardControllerServiceProvider> {
  public:
-  explicit StandardControllerServiceProvider(std::shared_ptr<ControllerServiceMap> services, std::shared_ptr<ProcessGroup> root_group, std::shared_ptr<Configure> configuration,
+  explicit StandardControllerServiceProvider(std::shared_ptr<ControllerServiceMap> services, ProcessGroup* root_group, std::shared_ptr<Configure> configuration,
                                              std::shared_ptr<minifi::SchedulingAgent> agent, ClassLoader &loader = ClassLoader::getDefaultClassLoader())
       : ControllerServiceProvider(services),
         agent_(agent),
@@ -52,7 +52,7 @@ class StandardControllerServiceProvider : public ControllerServiceProvider, publ
         logger_(logging::LoggerFactory<StandardControllerServiceProvider>::getLogger()) {
   }
 
-  explicit StandardControllerServiceProvider(std::shared_ptr<ControllerServiceMap> services, std::shared_ptr<ProcessGroup> root_group, std::shared_ptr<Configure> configuration, ClassLoader &loader =
+  explicit StandardControllerServiceProvider(std::shared_ptr<ControllerServiceMap> services, ProcessGroup* root_group, std::shared_ptr<Configure> configuration, ClassLoader &loader =
                                                  ClassLoader::getDefaultClassLoader())
       : ControllerServiceProvider(services),
         agent_(nullptr),
@@ -68,7 +68,7 @@ class StandardControllerServiceProvider : public ControllerServiceProvider, publ
   StandardControllerServiceProvider& operator=(const StandardControllerServiceProvider &other) = delete;
   StandardControllerServiceProvider& operator=(StandardControllerServiceProvider &&other) = delete;
 
-  void setRootGroup(std::shared_ptr<ProcessGroup> rg) {
+  void setRootGroup(ProcessGroup* rg) {
     root_group_ = rg;
   }
 
@@ -200,7 +200,7 @@ class StandardControllerServiceProvider : public ControllerServiceProvider, publ
 
   ClassLoader &extension_loader_;
 
-  std::shared_ptr<ProcessGroup> root_group_;
+  ProcessGroup* root_group_ = nullptr;
 
   std::shared_ptr<Configure> configuration_;
 
diff --git a/libminifi/include/core/repository/VolatileRepository.h b/libminifi/include/core/repository/VolatileRepository.h
index afc72e9..f5ef08c 100644
--- a/libminifi/include/core/repository/VolatileRepository.h
+++ b/libminifi/include/core/repository/VolatileRepository.h
@@ -74,18 +74,17 @@ class VolatileRepository : public core::Repository, public utils::EnableSharedFr
     purge_required_ = false;
   }
 
-  // Destructor
-  virtual ~VolatileRepository();
+  ~VolatileRepository() override;
 
   /**
    * Initialize thevolatile repsitory
    **/
 
-  virtual bool initialize(const std::shared_ptr<Configure> &configure);
+  bool initialize(const std::shared_ptr<Configure> &configure) override;
 
-  virtual void run() = 0;
+  void run() override = 0;
 
-  virtual bool isNoop() {
+  bool isNoop() override {
     return false;
   }
 
@@ -94,32 +93,32 @@ class VolatileRepository : public core::Repository, public utils::EnableSharedFr
    * @param key key to add to the repository
    * @param buf buffer
    **/
-  virtual bool Put(T key, const uint8_t *buf, size_t bufLen);
+  bool Put(T key, const uint8_t *buf, size_t bufLen) override;
 
   /**
    * Places new objects into the volatile memory area
    * @param data the key-value pairs to add to the repository
    **/
-  virtual bool MultiPut(const std::vector<std::pair<T, std::unique_ptr<io::BufferStream>>>& data);
+  bool MultiPut(const std::vector<std::pair<T, std::unique_ptr<io::BufferStream>>>& data) override;
 
   /**
    * Deletes the key
    * @return status of the delete operation
    */
-  virtual bool Delete(T key);
+  bool Delete(T key) override;
 
   /**
    * Sets the value from the provided key. Once the item is retrieved
    * it may not be retrieved again.
    * @return status of the get operation.
    */
-  virtual bool Get(const T &key, std::string &value);
+  bool Get(const T &key, std::string &value) override;
   /**
    * Deserializes objects into store
    * @param store vector in which we will store newly created objects.
    * @param max_size size of objects deserialized
    */
-  virtual bool DeSerialize(std::vector<std::shared_ptr<core::SerializableComponent>> &store, size_t &max_size, std::function<std::shared_ptr<core::SerializableComponent>()> lambda);
+  bool DeSerialize(std::vector<std::shared_ptr<core::SerializableComponent>> &store, size_t &max_size, std::function<std::shared_ptr<core::SerializableComponent>()> lambda) override;
 
   /**
    * Deserializes objects into a store that contains a fixed number of objects in which
@@ -127,22 +126,16 @@ class VolatileRepository : public core::Repository, public utils::EnableSharedFr
    * @param store precreated object vector
    * @param max_size size of objects deserialized
    */
-  virtual bool DeSerialize(std::vector<std::shared_ptr<core::SerializableComponent>> &store, size_t &max_size);
-
-  /**
-   * Set the connection map
-   * @param connectionMap map of all connections through this repo.
-   */
-  void setConnectionMap(std::map<std::string, std::shared_ptr<minifi::Connection>> &connectionMap);
+  bool DeSerialize(std::vector<std::shared_ptr<core::SerializableComponent>> &store, size_t &max_size) override;
 
   /**
    * Function to load this component.
    */
-  virtual void loadComponent(const std::shared_ptr<core::ContentRepository> &content_repo);
+  void loadComponent(const std::shared_ptr<core::ContentRepository> &content_repo) override;
 
-  virtual void start();
+  void start() override;
 
-  virtual uint64_t getRepoSize() {
+  uint64_t getRepoSize() override {
     return current_size_;
   }
 
@@ -164,7 +157,6 @@ class VolatileRepository : public core::Repository, public utils::EnableSharedFr
       return false;
   }
 
-  std::map<std::string, std::shared_ptr<minifi::Connection>> connectionMap;
   // current size of the volatile repo.
   std::atomic<size_t> current_size_;
   // current index.
@@ -203,6 +195,8 @@ VolatileRepository<T>::~VolatileRepository() {
   for (auto ent : value_vector_) {
     delete ent;
   }
+
+  stop();
 }
 
 /**
@@ -397,11 +391,6 @@ bool VolatileRepository<T>::DeSerialize(std::vector<std::shared_ptr<core::Serial
 }
 
 template<typename T>
-void VolatileRepository<T>::setConnectionMap(std::map<std::string, std::shared_ptr<minifi::Connection>> &connectionMap) {
-  this->connectionMap = connectionMap;
-}
-
-template<typename T>
 void VolatileRepository<T>::start() {
   if (this->purge_period_ <= std::chrono::milliseconds(0))
     return;
diff --git a/libminifi/include/core/state/ProcessorController.h b/libminifi/include/core/state/ProcessorController.h
index 5b76121..fe1de13 100644
--- a/libminifi/include/core/state/ProcessorController.h
+++ b/libminifi/include/core/state/ProcessorController.h
@@ -38,9 +38,9 @@ namespace state {
  */
 class ProcessorController : public StateController {
  public:
-  ProcessorController(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<SchedulingAgent> &scheduler);
+  ProcessorController(core::Processor* processor, const std::shared_ptr<SchedulingAgent> &scheduler);
 
-  virtual ~ProcessorController();
+  ~ProcessorController() override;
 
   std::string getComponentName() const override {
     return processor_->getName();
@@ -50,7 +50,7 @@ class ProcessorController : public StateController {
     return processor_->getUUID();
   }
 
-  std::shared_ptr<core::Processor> getProcessor() {
+  core::Processor* getProcessor() {
     return processor_;
   }
   /**
@@ -69,7 +69,7 @@ class ProcessorController : public StateController {
   int16_t resume() override;
 
  protected:
-  std::shared_ptr<core::Processor> processor_;
+  core::Processor* processor_;
   std::shared_ptr<SchedulingAgent> scheduler_;
 };
 
diff --git a/libminifi/include/core/state/UpdateController.h b/libminifi/include/core/state/UpdateController.h
index a493e60..4fee93b 100644
--- a/libminifi/include/core/state/UpdateController.h
+++ b/libminifi/include/core/state/UpdateController.h
@@ -187,9 +187,9 @@ class StateMonitor : public StateController {
     return controller_running_;
   }
 
-  virtual std::vector<std::shared_ptr<StateController>> getComponents(const std::string &name) = 0;
+  virtual std::vector<StateController*> getComponents(const std::string &name) = 0;
 
-  virtual std::vector<std::shared_ptr<StateController>> getAllComponents() = 0;
+  virtual std::vector<StateController*> getAllComponents() = 0;
   /**
    * Operational controllers
    */
diff --git a/libminifi/include/core/state/nodes/AgentInformation.h b/libminifi/include/core/state/nodes/AgentInformation.h
index fb4b242..8eb0fa4 100644
--- a/libminifi/include/core/state/nodes/AgentInformation.h
+++ b/libminifi/include/core/state/nodes/AgentInformation.h
@@ -586,13 +586,13 @@ class AgentMonitor {
     }
   }
 
-  void setStateMonitor(const std::shared_ptr<state::StateMonitor> &monitor) {
+  void setStateMonitor(state::StateMonitor* &monitor) {
     monitor_ = monitor;
   }
 
  protected:
   std::map<std::string, std::shared_ptr<core::Repository>> repositories_;
-  std::shared_ptr<state::StateMonitor> monitor_;
+  state::StateMonitor* monitor_;
 };
 
 /**
diff --git a/libminifi/include/core/state/nodes/FlowInformation.h b/libminifi/include/core/state/nodes/FlowInformation.h
index 2f40b2c..13bc5f8 100644
--- a/libminifi/include/core/state/nodes/FlowInformation.h
+++ b/libminifi/include/core/state/nodes/FlowInformation.h
@@ -141,7 +141,7 @@ class FlowMonitor : public StateMonitorNode {
       : StateMonitorNode(name) {
   }
 
-  void addConnection(const std::shared_ptr<minifi::Connection> &connection) {
+  void addConnection(minifi::Connection* connection) {
     if (nullptr != connection) {
       connections_.insert(std::make_pair(connection->getUUIDStr(), connection));
     }
@@ -152,7 +152,7 @@ class FlowMonitor : public StateMonitorNode {
   }
  protected:
   std::shared_ptr<state::response::FlowVersion> flow_version_;
-  std::map<std::string, std::shared_ptr<minifi::Connection>> connections_;
+  std::map<std::string, minifi::Connection*> connections_;
 };
 
 /**
diff --git a/libminifi/include/core/state/nodes/QueueMetrics.h b/libminifi/include/core/state/nodes/QueueMetrics.h
index cd0efd3..3cf516d 100644
--- a/libminifi/include/core/state/nodes/QueueMetrics.h
+++ b/libminifi/include/core/state/nodes/QueueMetrics.h
@@ -57,16 +57,15 @@ class QueueMetrics : public ResponseNode {
     return "QueueMetrics";
   }
 
-  void addConnection(const std::shared_ptr<minifi::Connection> &connection) {
+  void addConnection(std::unique_ptr<minifi::Connection> connection) {
     if (nullptr != connection) {
-      connections.insert(std::make_pair(connection->getName(), connection));
+      connections.insert(std::make_pair(connection->getName(), std::move(connection)));
     }
   }
 
   std::vector<SerializedResponseNode> serialize() {
     std::vector<SerializedResponseNode> serialized;
-    for (auto conn : connections) {
-      auto connection = conn.second;
+    for (const auto& [_, connection] : connections) {
       SerializedResponseNode parent;
       parent.name = connection->getName();
       SerializedResponseNode datasize;
@@ -96,7 +95,7 @@ class QueueMetrics : public ResponseNode {
   }
 
  protected:
-  std::map<std::string, std::shared_ptr<minifi::Connection>> connections;
+  std::map<std::string, std::unique_ptr<minifi::Connection>> connections;
 };
 
 }  // namespace response
diff --git a/libminifi/include/core/state/nodes/StateMonitor.h b/libminifi/include/core/state/nodes/StateMonitor.h
index 32bfb15..cbeffa8 100644
--- a/libminifi/include/core/state/nodes/StateMonitor.h
+++ b/libminifi/include/core/state/nodes/StateMonitor.h
@@ -53,11 +53,11 @@ class StateMonitorNode : public DeviceInformation {
         monitor_(nullptr) {
   }
 
-  void setStateMonitor(const std::shared_ptr<state::StateMonitor> &monitor) {
+  void setStateMonitor(state::StateMonitor* monitor) {
     monitor_ = monitor;
   }
  protected:
-  std::shared_ptr<state::StateMonitor> monitor_;
+  state::StateMonitor* monitor_;
 };
 
 }  // namespace response
diff --git a/libminifi/include/core/yaml/YamlConfiguration.h b/libminifi/include/core/yaml/YamlConfiguration.h
index 15dff7b..dd6e163 100644
--- a/libminifi/include/core/yaml/YamlConfiguration.h
+++ b/libminifi/include/core/yaml/YamlConfiguration.h
@@ -143,7 +143,7 @@ class YamlConfiguration : public FlowConfiguration {
    * @param component_name
    * @param yaml_section
    */
-  void validateComponentProperties(const std::shared_ptr<ConfigurableComponent> &component, const std::string &component_name, const std::string &yaml_section) const;
+  void validateComponentProperties(ConfigurableComponent& component, const std::string &component_name, const std::string &yaml_section) const;
 
  protected:
   /**
@@ -247,7 +247,7 @@ class YamlConfiguration : public FlowConfiguration {
    * @param propertiesNode the YAML::Node containing the properties
    * @param processor      the Processor to which to add the resulting properties
    */
-  void parsePropertiesNodeYaml(const YAML::Node& propertiesNode, std::shared_ptr<core::ConfigurableComponent> processor, const std::string& component_name, const std::string& yaml_section);
+  void parsePropertiesNodeYaml(const YAML::Node& propertiesNode, core::ConfigurableComponent& processor, const std::string& component_name, const std::string& yaml_section);
 
   /**
    * Parses the Funnels section of a configuration YAML.
@@ -299,9 +299,9 @@ class YamlConfiguration : public FlowConfiguration {
 
  private:
   PropertyValue getValidatedProcessorPropertyForDefaultTypeInfo(const core::Property& propertyFromProcessor, const YAML::Node& propertyValueNode);
-  void parsePropertyValueSequence(const std::string& propertyName, const YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor);
-  void parseSingleProperty(const std::string& propertyName, const YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor);
-  void parsePropertyNodeElement(const std::string& propertyName, const YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor);
+  void parsePropertyValueSequence(const std::string& propertyName, const YAML::Node& propertyValueNode, core::ConfigurableComponent& processor);
+  void parseSingleProperty(const std::string& propertyName, const YAML::Node& propertyValueNode, core::ConfigurableComponent& processor);
+  void parsePropertyNodeElement(const std::string& propertyName, const YAML::Node& propertyValueNode, core::ConfigurableComponent& processor);
 
   std::shared_ptr<logging::Logger> logger_;
   static std::shared_ptr<utils::IdGenerator> id_generator_;
diff --git a/libminifi/include/core/yaml/YamlConnectionParser.h b/libminifi/include/core/yaml/YamlConnectionParser.h
index 831bca2..f15224f 100644
--- a/libminifi/include/core/yaml/YamlConnectionParser.h
+++ b/libminifi/include/core/yaml/YamlConnectionParser.h
@@ -44,7 +44,7 @@ class YamlConnectionParser {
       parent_(parent),
       logger_(logger) {}
 
-  void configureConnectionSourceRelationshipsFromYaml(const std::shared_ptr<minifi::Connection>& connection) const;
+  void configureConnectionSourceRelationshipsFromYaml(minifi::Connection& connection) const;
   [[nodiscard]] uint64_t getWorkQueueSizeFromYaml() const;
   [[nodiscard]] uint64_t getWorkQueueDataSizeFromYaml() const;
   [[nodiscard]] utils::Identifier getSourceUUIDFromYaml() const;
@@ -53,8 +53,8 @@ class YamlConnectionParser {
   [[nodiscard]] bool getDropEmptyFromYaml() const;
 
  private:
-  void addNewRelationshipToConnection(const std::string& relationship_name, const std::shared_ptr<minifi::Connection>& connection) const;
-  void addFunnelRelationshipToConnection(const std::shared_ptr<minifi::Connection>& connection) const;
+  void addNewRelationshipToConnection(const std::string& relationship_name, minifi::Connection& connection) const;
+  void addFunnelRelationshipToConnection(minifi::Connection& connection) const;
 
   const YAML::Node& connectionNode_;
   const std::string& name_;
diff --git a/libminifi/include/processors/ProcessorUtils.h b/libminifi/include/processors/ProcessorUtils.h
index fe9ebc6..b7d5534 100644
--- a/libminifi/include/processors/ProcessorUtils.h
+++ b/libminifi/include/processors/ProcessorUtils.h
@@ -21,16 +21,15 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace processors {
+namespace org::apache::nifi::minifi::processors {
 
 class ProcessorUtils {
  public:
+  ProcessorUtils() = delete;
+
   /**
    * Instantiates and configures a processor
    * @param class_short_name short name of the class
@@ -38,7 +37,7 @@ class ProcessorUtils {
    * @param uuid uuid object for the processor
    * @param stream_factory stream factory to be set onto the processor
    */
-  static inline std::shared_ptr<core::Processor> createProcessor(const std::string &class_short_name, const std::string &canonicalName, const utils::Identifier &uuid,
+  static inline std::unique_ptr<core::Processor> createProcessor(const std::string &class_short_name, const std::string &canonicalName, const utils::Identifier &uuid,
                                                                  const std::shared_ptr<minifi::io::StreamFactory> &stream_factory) {
     auto ptr = core::ClassLoader::getDefaultClassLoader().instantiate(class_short_name, uuid);
     // fallback to the canonical name if the short name does not work, then attempt JNI bindings if they exist
@@ -47,7 +46,7 @@ class ProcessorUtils {
       if (ptr == nullptr) {
         ptr = core::ClassLoader::getDefaultClassLoader().instantiate("ExecuteJavaClass", uuid);
         if (ptr != nullptr) {
-          std::shared_ptr<core::Processor> processor = std::dynamic_pointer_cast<core::Processor>(ptr);
+          auto processor = utils::dynamic_unique_cast<core::Processor>(std::move(ptr));
           if (processor == nullptr) {
             throw std::runtime_error("Invalid return from the classloader");
           }
@@ -61,25 +60,16 @@ class ProcessorUtils {
     if (ptr == nullptr) {
       return nullptr;
     }
-    auto returnPtr = std::dynamic_pointer_cast<core::Processor>(ptr);
 
-    if (returnPtr == nullptr) {
+    auto returnPtr = utils::dynamic_unique_cast<core::Processor>(std::move(ptr));
+    if (!returnPtr) {
       throw std::runtime_error("Invalid return from the classloader");
     }
 
     returnPtr->initialize();
-
     returnPtr->setStreamFactory(stream_factory);
-
     return returnPtr;
   }
-
- private:
-  ProcessorUtils();
 };
 
-}  // namespace processors
-}  // namespace minifi
-}  // namespace nifi
-}  // namespace apache
-}  // namespace org
+}  // namespace org::apache::nifi::minifi::processors
diff --git a/libminifi/include/utils/GeneralUtils.h b/libminifi/include/utils/GeneralUtils.h
index 002a7c9..bc641f1 100644
--- a/libminifi/include/utils/GeneralUtils.h
+++ b/libminifi/include/utils/GeneralUtils.h
@@ -34,6 +34,16 @@ constexpr T intdiv_ceil(T numerator, T denominator) {
       : numerator / denominator + (numerator % denominator != 0));
 }
 
+/**
+ * safely converts unique_ptr from one type to another
+ * if conversion succeeds, an desired valid unique_ptr is returned, the "from" object released and invalidated
+ * if conversion fails, an empty unique_ptr is returned
+ */
+template <typename T_To, typename T_From>
+std::unique_ptr<T_To> dynamic_unique_cast(std::unique_ptr<T_From> obj) {
+  return std::unique_ptr<T_To>{dynamic_cast<T_To*>(obj.get()) ? dynamic_cast<T_To*>(obj.release()) : nullptr};
+}
+
 #if __cpp_lib_concepts >= 202002L
 using std::identity;
 #else
diff --git a/libminifi/include/utils/ListingStateManager.h b/libminifi/include/utils/ListingStateManager.h
index 280155a..0ca25e1 100644
--- a/libminifi/include/utils/ListingStateManager.h
+++ b/libminifi/include/utils/ListingStateManager.h
@@ -49,8 +49,8 @@ struct ListingState {
 
 class ListingStateManager {
  public:
-  explicit ListingStateManager(std::shared_ptr<core::CoreComponentStateManager> state_manager)
-    : state_manager_(std::move(state_manager)) {
+  explicit ListingStateManager(core::CoreComponentStateManager* state_manager)
+    : state_manager_(state_manager) {
   }
 
   [[nodiscard]] ListingState getCurrentState() const;
@@ -63,9 +63,7 @@ class ListingStateManager {
   [[nodiscard]] static uint64_t getLatestListedKeyTimestampInMilliseconds(const std::unordered_map<std::string, std::string> &state);
   [[nodiscard]] static std::unordered_set<std::string> getLatestListedKeys(const std::unordered_map<std::string, std::string> &state);
 
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
-  const std::string timestamp_key_;
-  const std::string listed_object_prefix_;
+  core::CoreComponentStateManager* state_manager_;
   std::shared_ptr<core::logging::Logger> logger_{core::logging::LoggerFactory<ListingStateManager>::getLogger()};
 };
 
diff --git a/libminifi/include/utils/ThreadPool.h b/libminifi/include/utils/ThreadPool.h
index 744a39b..161d330 100644
--- a/libminifi/include/utils/ThreadPool.h
+++ b/libminifi/include/utils/ThreadPool.h
@@ -167,15 +167,15 @@ class WorkerThread {
 template<typename T>
 class ThreadPool {
  public:
-  ThreadPool(int max_worker_threads = 2, bool daemon_threads = false, const std::shared_ptr<core::controller::ControllerServiceProvider> &controller_service_provider = nullptr,
-             const std::string &name = "NamelessPool")
+  ThreadPool(int max_worker_threads = 2, bool daemon_threads = false, core::controller::ControllerServiceProvider* controller_service_provider = nullptr,
+             std::string name = "NamelessPool")
       : daemon_threads_(daemon_threads),
         thread_reduction_count_(0),
         max_worker_threads_(max_worker_threads),
         adjust_threads_(false),
         running_(false),
         controller_service_provider_(controller_service_provider),
-        name_(name) {
+        name_(std::move(name)) {
     current_workers_ = 0;
     task_count_ = 0;
     thread_manager_ = nullptr;
@@ -273,7 +273,7 @@ class ThreadPool {
       start();
   }
 
-  void setControllerServiceProvider(std::shared_ptr<core::controller::ControllerServiceProvider> controller_service_provider) {
+  void setControllerServiceProvider(core::controller::ControllerServiceProvider* controller_service_provider) {
     std::lock_guard<std::recursive_mutex> lock(manager_mutex_);
     bool was_running = running_;
     if (was_running) {
@@ -322,7 +322,7 @@ class ThreadPool {
 // atomic running boolean
   std::atomic<bool> running_;
 // controller service provider
-  std::shared_ptr<core::controller::ControllerServiceProvider> controller_service_provider_;
+  core::controller::ControllerServiceProvider* controller_service_provider_;
 // integrated power manager
   std::shared_ptr<controllers::ThreadManagementService> thread_manager_;
   // thread queue for the recently deceased threads.
diff --git a/libminifi/src/Connection.cpp b/libminifi/src/Connection.cpp
index 5dd1d0b..9432eb1 100644
--- a/libminifi/src/Connection.cpp
+++ b/libminifi/src/Connection.cpp
@@ -80,7 +80,7 @@ bool Connection::isEmpty() const {
   return queue_.empty();
 }
 
-bool Connection::isFull() {
+bool Connection::isFull() const {
   std::lock_guard<std::mutex> lock(mutex_);
 
   if (max_queue_size_ <= 0 && max_data_queue_size_ <= 0)
@@ -155,20 +155,18 @@ std::shared_ptr<core::FlowFile> Connection::poll(std::set<std::shared_ptr<core::
         expiredFlowRecords.insert(item);
         logger_->log_debug("Delete flow file UUID %s from connection %s, because it expired", item->getUUIDStr(), name_);
       } else {
-        std::shared_ptr<Connectable> connectable = std::static_pointer_cast<Connectable>(shared_from_this());
-        item->setConnection(connectable);
+        item->setConnection(this);
         logger_->log_debug("Dequeue flow file UUID %s from connection %s", item->getUUIDStr(), name_);
         return item;
       }
     } else {
-      std::shared_ptr<Connectable> connectable = std::static_pointer_cast<Connectable>(shared_from_this());
-      item->setConnection(connectable);
+      item->setConnection(this);
       logger_->log_debug("Dequeue flow file UUID %s from connection %s", item->getUUIDStr(), name_);
       return item;
     }
   }
 
-  return NULL;
+  return nullptr;
 }
 
 void Connection::drain(bool delete_permanently) {
diff --git a/libminifi/src/CronDrivenSchedulingAgent.cpp b/libminifi/src/CronDrivenSchedulingAgent.cpp
index 101db10..27fddc5 100644
--- a/libminifi/src/CronDrivenSchedulingAgent.cpp
+++ b/libminifi/src/CronDrivenSchedulingAgent.cpp
@@ -34,7 +34,7 @@ namespace apache {
 namespace nifi {
 namespace minifi {
 
-utils::TaskRescheduleInfo CronDrivenSchedulingAgent::run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+utils::TaskRescheduleInfo CronDrivenSchedulingAgent::run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
                                         const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) {
   if (this->running_ && processor->isRunning()) {
     auto uuid = processor->getUUID();
diff --git a/libminifi/src/EventDrivenSchedulingAgent.cpp b/libminifi/src/EventDrivenSchedulingAgent.cpp
index e9823e9..10edd64 100644
--- a/libminifi/src/EventDrivenSchedulingAgent.cpp
+++ b/libminifi/src/EventDrivenSchedulingAgent.cpp
@@ -31,14 +31,14 @@ namespace apache {
 namespace nifi {
 namespace minifi {
 
-void EventDrivenSchedulingAgent::schedule(std::shared_ptr<core::Processor> processor) {
+void EventDrivenSchedulingAgent::schedule(core::Processor* processor) {
   if (!processor->hasIncomingConnections()) {
     throw Exception(PROCESS_SCHEDULE_EXCEPTION, "EventDrivenSchedulingAgent cannot schedule processor without incoming connection!");
   }
   ThreadedSchedulingAgent::schedule(processor);
 }
 
-utils::TaskRescheduleInfo EventDrivenSchedulingAgent::run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+utils::TaskRescheduleInfo EventDrivenSchedulingAgent::run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
                                          const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) {
   if (this->running_) {
     auto start_time = std::chrono::steady_clock::now();
diff --git a/libminifi/src/FlowController.cpp b/libminifi/src/FlowController.cpp
index b87f819..77a61aa 100644
--- a/libminifi/src/FlowController.cpp
+++ b/libminifi/src/FlowController.cpp
@@ -137,7 +137,7 @@ bool FlowController::applyConfiguration(const std::string &source, const std::st
   initialized_ = false;
   bool started = false;
   try {
-    load(this->root_, true);
+    load(std::move(root_), true);
     flow_update_ = true;
     started = start() == 0;
 
@@ -155,7 +155,7 @@ bool FlowController::applyConfiguration(const std::string &source, const std::st
     }
   } catch (...) {
     this->root_ = std::move(prevRoot);
-    load(this->root_, true);
+    load(std::move(this->root_), true);
     flow_update_ = true;
     updating_ = false;
   }
@@ -170,7 +170,7 @@ int16_t FlowController::stop() {
     logger_->log_info("Stop Flow Controller");
     if (this->root_) {
       // stop source processors first
-      this->root_->stopProcessing(timer_scheduler_, event_scheduler_, cron_scheduler_, [] (const std::shared_ptr<core::Processor>& proc) -> bool {
+      this->root_->stopProcessing(timer_scheduler_, event_scheduler_, cron_scheduler_, [] (const core::Processor* proc) -> bool {
         return !proc->hasIncomingConnections();
       });
       // we enable C2 to progressively increase the timeout
@@ -255,7 +255,7 @@ std::unique_ptr<core::ProcessGroup> FlowController::loadInitialFlow() {
   // since we don't have access to the flow definition, the C2 communication
   // won't be able to use the services defined there, e.g. SSLContextService
   controller_service_provider_impl_ = flow_configuration_->getControllerServiceProvider();
-  C2Client::initialize(this, this, shared_from_this());
+  C2Client::initialize(this, this, this);
   auto opt_source = fetchFlow(*opt_flow_url);
   if (!opt_source) {
     logger_->log_error("Couldn't fetch flow configuration from C2 server");
@@ -271,7 +271,7 @@ std::unique_ptr<core::ProcessGroup> FlowController::loadInitialFlow() {
   return root;
 }
 
-void FlowController::load(const std::shared_ptr<core::ProcessGroup> &root, bool reload) {
+void FlowController::load(std::unique_ptr<core::ProcessGroup> root, bool reload) {
   std::lock_guard<std::recursive_mutex> flow_lock(mutex_);
   if (running_) {
     stop();
@@ -283,10 +283,10 @@ void FlowController::load(const std::shared_ptr<core::ProcessGroup> &root, bool
 
     if (root) {
       logger_->log_info("Load Flow Controller from provided root");
-      this->root_ = root;
+      this->root_ = std::move(root);
     } else {
       logger_->log_info("Instantiating new flow");
-      this->root_ = std::shared_ptr<core::ProcessGroup>(loadInitialFlow());
+      this->root_ = loadInitialFlow();
     }
 
     if (root_) {
@@ -296,12 +296,11 @@ void FlowController::load(const std::shared_ptr<core::ProcessGroup> &root, bool
     logger_->log_info("Loaded root processor Group");
     logger_->log_info("Initializing timers");
     controller_service_provider_impl_ = flow_configuration_->getControllerServiceProvider();
-    auto base_shared_ptr = std::dynamic_pointer_cast<core::controller::ControllerServiceProvider>(shared_from_this());
 
     if (!thread_pool_.isRunning() || reload) {
       thread_pool_.shutdown();
       thread_pool_.setMaxConcurrentTasks(configuration_->getInt(Configure::nifi_flow_engine_threads, 2));
-      thread_pool_.setControllerServiceProvider(base_shared_ptr);
+      thread_pool_.setControllerServiceProvider(this);
       thread_pool_.start();
     }
 
@@ -309,7 +308,7 @@ void FlowController::load(const std::shared_ptr<core::ProcessGroup> &root, bool
     conditionalReloadScheduler<EventDrivenSchedulingAgent>(event_scheduler_, !event_scheduler_ || reload);
     conditionalReloadScheduler<CronDrivenSchedulingAgent>(cron_scheduler_, !cron_scheduler_ || reload);
 
-    std::static_pointer_cast<core::controller::StandardControllerServiceProvider>(controller_service_provider_impl_)->setRootGroup(root_);
+    std::static_pointer_cast<core::controller::StandardControllerServiceProvider>(controller_service_provider_impl_)->setRootGroup(root_.get());
     std::static_pointer_cast<core::controller::StandardControllerServiceProvider>(controller_service_provider_impl_)->setSchedulingAgent(
         std::static_pointer_cast<minifi::SchedulingAgent>(event_scheduler_));
 
@@ -337,8 +336,8 @@ void FlowController::load(const std::shared_ptr<core::ProcessGroup> &root, bool
 void FlowController::loadFlowRepo() {
   if (this->flow_file_repo_ != nullptr) {
     logger_->log_debug("Getting connection map");
-    std::map<std::string, std::shared_ptr<core::Connectable>> connectionMap;
-    std::map<std::string, std::shared_ptr<core::Connectable>> containers;
+    std::map<std::string, core::Connectable*> connectionMap;
+    std::map<std::string, core::Connectable*> containers;
     if (this->root_ != nullptr) {
       this->root_->getConnections(connectionMap);
       this->root_->getFlowFileContainers(containers);
@@ -370,7 +369,7 @@ int16_t FlowController::start() {
         // as the thread_pool_ is started in load()
         this->root_->startProcessing(timer_scheduler_, event_scheduler_, cron_scheduler_);
       }
-      C2Client::initialize(this, this, shared_from_this());
+      C2Client::initialize(this, this, this);
       running_ = true;
       this->protocol_->start();
       this->provenance_repo_->start();
@@ -420,7 +419,7 @@ int16_t FlowController::applyUpdate(const std::string &source, const std::string
 int16_t FlowController::clearConnection(const std::string &connection) {
   if (root_ != nullptr) {
     logger_->log_info("Attempting to clear connection %s", connection);
-    std::map<std::string, std::shared_ptr<Connection>> connections;
+    std::map<std::string, Connection*> connections;
     root_->getConnections(connections);
     auto conn = connections.find(connection);
     if (conn != connections.end()) {
@@ -438,58 +437,44 @@ std::shared_ptr<state::response::ResponseNode> FlowController::getAgentManifest(
   return agentInfo;
 }
 
-std::vector<std::shared_ptr<state::StateController>> FlowController::getAllComponents() {
-  std::vector<std::shared_ptr<state::StateController>> vec;
-  vec.push_back(shared_from_this());
-  std::vector<std::shared_ptr<core::Processor>> processors;
-  if (root_ != nullptr) {
-    root_->getAllProcessors(processors);
-    for (auto &processor : processors) {
-      switch (processor->getSchedulingStrategy()) {
-        case core::SchedulingStrategy::TIMER_DRIVEN:
-          vec.push_back(std::make_shared<state::ProcessorController>(processor, timer_scheduler_));
-          break;
-        case core::SchedulingStrategy::EVENT_DRIVEN:
-          vec.push_back(std::make_shared<state::ProcessorController>(processor, event_scheduler_));
-          break;
-        case core::SchedulingStrategy::CRON_DRIVEN:
-          vec.push_back(std::make_shared<state::ProcessorController>(processor, cron_scheduler_));
-          break;
-        default:
-          break;
-      }
-    }
+std::vector<state::StateController*> FlowController::getAllComponents() {
+  std::vector<state::StateController*> vec{this};
+  if (root_) {
+    auto controllerFactory = [this] (core::Processor& p) {
+      return createController(p);
+    };
+    getAllProcessorControllers(vec, controllerFactory);
   }
   return vec;
 }
-std::vector<std::shared_ptr<state::StateController>> FlowController::getComponents(const std::string &name) {
-  std::vector<std::shared_ptr<state::StateController>> vec;
+
+std::vector<state::StateController*> FlowController::getComponents(const std::string& name) {
+  std::vector<state::StateController*> vec;
 
   if (name == "FlowController") {
-    vec.push_back(shared_from_this());
+    vec.push_back(this);
   } else if (root_) {
-    // check processors
-    std::shared_ptr<core::Processor> processor = root_->findProcessorByName(name);
-    if (processor != nullptr) {
-      switch (processor->getSchedulingStrategy()) {
-        case core::SchedulingStrategy::TIMER_DRIVEN:
-          vec.push_back(std::make_shared<state::ProcessorController>(processor, timer_scheduler_));
-          break;
-        case core::SchedulingStrategy::EVENT_DRIVEN:
-          vec.push_back(std::make_shared<state::ProcessorController>(processor, event_scheduler_));
-          break;
-        case core::SchedulingStrategy::CRON_DRIVEN:
-          vec.push_back(std::make_shared<state::ProcessorController>(processor, cron_scheduler_));
-          break;
-        default:
-          break;
-      }
-    }
+    auto controllerFactory = [this] (core::Processor& p) {
+      return createController(p);
+    };
+    getProcessorController(name, vec, controllerFactory);
   }
 
   return vec;
 }
 
+std::unique_ptr<state::ProcessorController> FlowController::createController(core::Processor& processor) {
+  switch (processor.getSchedulingStrategy()) {
+    case core::SchedulingStrategy::TIMER_DRIVEN:
+      return std::make_unique<state::ProcessorController>(&processor, timer_scheduler_);
+    case core::SchedulingStrategy::EVENT_DRIVEN:
+      return std::make_unique<state::ProcessorController>(&processor, event_scheduler_);
+    case core::SchedulingStrategy::CRON_DRIVEN:
+      return std::make_unique<state::ProcessorController>(&processor, cron_scheduler_);
+  }
+  return {};
+}
+
 uint64_t FlowController::getUptime() {
   auto now = std::chrono::steady_clock::now();
   auto time_since = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time_).count();
@@ -520,6 +505,33 @@ std::map<std::string, std::unique_ptr<io::InputStream>> FlowController::getDebug
   return debug_info;
 }
 
+void FlowController::getAllProcessorControllers(std::vector<state::StateController*>& controllerVec,
+                                              const std::function<std::unique_ptr<state::ProcessorController>(core::Processor&)>& controllerFactory) {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+
+  std::vector<core::Processor*> processorVec;
+  root_->getAllProcessors(processorVec);
+
+  for (const auto& processor : processorVec) {
+    // find controller for processor, if it doesn't exist, create one
+    auto& controller = processor_to_controller_[processor->getUUID()];
+    if (!controller) {
+      controller = controllerFactory(*processor);
+    }
+    controllerVec.push_back(controller.get());
+  }
+}
+
+void FlowController::getProcessorController(const std::string& name, std::vector<state::StateController*>& controllerVec,
+                                          const std::function<std::unique_ptr<state::ProcessorController>(core::Processor&)>& controllerFactory) {
+  auto* processor = root_->findProcessorByName(name);
+  auto& controller = processor_to_controller_[processor->getUUID()];
+  if (!controller) {
+    controller = controllerFactory(*processor);
+  }
+  controllerVec.push_back(controller.get());
+}
+
 }  // namespace minifi
 }  // namespace nifi
 }  // namespace apache
diff --git a/libminifi/src/SchedulingAgent.cpp b/libminifi/src/SchedulingAgent.cpp
index 0f5db51..130c4cb 100644
--- a/libminifi/src/SchedulingAgent.cpp
+++ b/libminifi/src/SchedulingAgent.cpp
@@ -25,19 +25,18 @@
 #include "core/Processor.h"
 #include "utils/gsl.h"
 
+namespace {
+bool hasWorkToDo(org::apache::nifi::minifi::core::Processor* processor) {
+  // Whether it has work to do
+  return processor->getTriggerWhenEmpty() || !processor->hasIncomingConnections() || processor->isWorkAvailable();
+}
+}  // namespace
+
 namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
 
-bool SchedulingAgent::hasWorkToDo(const std::shared_ptr<core::Processor>& processor) {
-  // Whether it has work to do
-  if (processor->getTriggerWhenEmpty() || !processor->hasIncomingConnections() || processor->isWorkAvailable())
-    return true;
-  else
-    return false;
-}
-
 std::future<utils::TaskRescheduleInfo> SchedulingAgent::enableControllerService(std::shared_ptr<core::controller::ControllerServiceNode> &serviceNode) {
   logger_->log_info("Enabling CSN in SchedulingAgent %s", serviceNode->getName());
   // reference the enable function from serviceNode
@@ -79,11 +78,7 @@ std::future<utils::TaskRescheduleInfo> SchedulingAgent::disableControllerService
   return future;
 }
 
-bool SchedulingAgent::hasTooMuchOutGoing(const std::shared_ptr<core::Processor>& processor) {
-  return processor->flowFilesOutGoingFull();
-}
-
-bool SchedulingAgent::onTrigger(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+bool SchedulingAgent::onTrigger(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
                                 const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) {
   if (processor->isYield()) {
     logger_->log_debug("Not running %s since it must yield", processor->getName());
diff --git a/libminifi/src/ThreadedSchedulingAgent.cpp b/libminifi/src/ThreadedSchedulingAgent.cpp
index b045a08..fe6cf46 100644
--- a/libminifi/src/ThreadedSchedulingAgent.cpp
+++ b/libminifi/src/ThreadedSchedulingAgent.cpp
@@ -46,7 +46,7 @@ namespace apache {
 namespace nifi {
 namespace minifi {
 
-void ThreadedSchedulingAgent::schedule(std::shared_ptr<core::Processor> processor) {
+void ThreadedSchedulingAgent::schedule(core::Processor* processor) {
   std::lock_guard<std::mutex> lock(mutex_);
 
   admin_yield_duration_ = 100ms;  // We should prevent burning CPU in case of rollbacks
@@ -81,7 +81,7 @@ void ThreadedSchedulingAgent::schedule(std::shared_ptr<core::Processor> processo
 
   std::shared_ptr<core::ProcessorNode> processor_node = std::make_shared<core::ProcessorNode>(processor);
 
-  auto contextBuilder = core::ClassLoader::getDefaultClassLoader().instantiate<core::ProcessContextBuilder>("ProcessContextBuilder", "ProcessContextBuilder");
+  std::shared_ptr<core::ProcessContextBuilder> contextBuilder = core::ClassLoader::getDefaultClassLoader().instantiate<core::ProcessContextBuilder>("ProcessContextBuilder", "ProcessContextBuilder");
 
   contextBuilder = contextBuilder->withContentRepository(content_repo_)->withFlowFileRepository(flow_repo_)->withProvider(controller_service_provider_)->withProvenanceRepository(repo_)
       ->withConfiguration(configure_);
@@ -123,7 +123,7 @@ void ThreadedSchedulingAgent::stop() {
   }
 }
 
-void ThreadedSchedulingAgent::unschedule(std::shared_ptr<core::Processor> processor) {
+void ThreadedSchedulingAgent::unschedule(core::Processor* processor) {
   std::lock_guard<std::mutex> lock(mutex_);
   logger_->log_debug("Shutting down threads for processor %s/%s", processor->getName(), processor->getUUIDStr());
 
diff --git a/libminifi/src/TimerDrivenSchedulingAgent.cpp b/libminifi/src/TimerDrivenSchedulingAgent.cpp
index f82482e..7864a79 100644
--- a/libminifi/src/TimerDrivenSchedulingAgent.cpp
+++ b/libminifi/src/TimerDrivenSchedulingAgent.cpp
@@ -31,7 +31,7 @@ namespace apache {
 namespace nifi {
 namespace minifi {
 
-utils::TaskRescheduleInfo TimerDrivenSchedulingAgent::run(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<core::ProcessContext> &processContext,
+utils::TaskRescheduleInfo TimerDrivenSchedulingAgent::run(core::Processor* processor, const std::shared_ptr<core::ProcessContext> &processContext,
                                          const std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) {
   if (this->running_ && processor->isRunning()) {
     bool shouldYield = this->onTrigger(processor, processContext, sessionFactory);
diff --git a/libminifi/src/c2/C2Agent.cpp b/libminifi/src/c2/C2Agent.cpp
index e7d7d3c..e79449a 100644
--- a/libminifi/src/c2/C2Agent.cpp
+++ b/libminifi/src/c2/C2Agent.cpp
@@ -55,7 +55,7 @@ namespace c2 {
 
 C2Agent::C2Agent(core::controller::ControllerServiceProvider *controller,
                  state::Pausable *pause_handler,
-                 const std::shared_ptr<state::StateMonitor> &updateSink,
+                 state::StateMonitor* updateSink,
                  const std::shared_ptr<Configure> &configuration,
                  const std::shared_ptr<utils::file::FileSystem> &filesystem)
     : heart_beat_period_(3s),
@@ -190,7 +190,7 @@ void C2Agent::configure(const std::shared_ptr<Configure> &configure, bool reconf
         logger_->log_error("Could not instantiate %s", reporter);
       } else {
         heartbeat_reporter_obj->initialize(controller_, update_sink_, configuration_);
-        heartbeat_protocols_.push_back(heartbeat_reporter_obj);
+        heartbeat_protocols_.push_back(std::move(heartbeat_reporter_obj));
       }
     }
   }
@@ -205,7 +205,7 @@ void C2Agent::configure(const std::shared_ptr<Configure> &configure, bool reconf
         logger_->log_error("Could not instantiate %s", trigger);
       } else {
         trigger_obj->initialize(configuration_);
-        triggers_.push_back(trigger_obj);
+        triggers_.push_back(std::move(trigger_obj));
       }
     }
   }
@@ -216,14 +216,14 @@ void C2Agent::configure(const std::shared_ptr<Configure> &configure, bool reconf
     logger_->log_error("Could not instantiate %s", base_reporter);
   } else {
     heartbeat_reporter_obj->initialize(controller_, update_sink_, configuration_);
-    heartbeat_protocols_.push_back(heartbeat_reporter_obj);
+    heartbeat_protocols_.push_back(std::move(heartbeat_reporter_obj));
   }
 }
 
 void C2Agent::performHeartBeat() {
   C2Payload payload(Operation::HEARTBEAT);
   logger_->log_trace("Performing heartbeat");
-  std::shared_ptr<state::response::NodeReporter> reporter = std::dynamic_pointer_cast<state::response::NodeReporter>(update_sink_);
+  auto reporter = dynamic_cast<state::response::NodeReporter*>(update_sink_);
   std::vector<std::shared_ptr<state::response::ResponseNode>> metrics;
   if (reporter) {
     if (!manifest_sent_) {
@@ -249,7 +249,7 @@ void C2Agent::performHeartBeat() {
 
   std::lock_guard<std::mutex> lock(heartbeat_mutex);
 
-  for (auto reporter : heartbeat_protocols_) {
+  for (auto& reporter : heartbeat_protocols_) {
     reporter->heartbeat(payload);
   }
 }
@@ -355,7 +355,7 @@ void C2Agent::handle_c2_server_response(const C2ContentResponse &resp) {
         raise(SIGTERM);
       }
 
-      std::vector<std::shared_ptr<state::StateController>> components = update_sink_->getComponents(resp.name);
+      const auto components = update_sink_->getComponents(resp.name);
       // stop all referenced components.
       for (auto &component : components) {
         logger_->log_debug("Stopping component %s", component->getComponentName());
@@ -431,7 +431,7 @@ C2Payload C2Agent::prepareConfigurationOptions(const C2ContentResponse &resp) co
  * to be put into the acknowledgement
  */
 void C2Agent::handle_describe(const C2ContentResponse &resp) {
-  auto reporter = std::dynamic_pointer_cast<state::response::NodeReporter>(update_sink_);
+  auto reporter = dynamic_cast<state::response::NodeReporter*>(update_sink_);
   if (resp.name == "metrics") {
     C2Payload response(Operation::ACKNOWLEDGE, resp.ident, true);
     if (reporter != nullptr) {
@@ -529,10 +529,10 @@ void C2Agent::handle_clear(const C2ContentResponse &resp) {
     update_sink_->drainRepositories();
   } else if (resp.name == "corecomponentstate") {
     for (const auto& corecomponent : resp.operation_arguments) {
-      std::vector<std::shared_ptr<state::StateController>> components = update_sink_->getComponents(corecomponent.second.to_string());
+      std::vector<state::StateController*> components = update_sink_->getComponents(corecomponent.second.to_string());
       auto state_manager_provider = core::ProcessContext::getStateManagerProvider(logger_, controller_, configuration_);
       if (state_manager_provider != nullptr) {
-        for (auto &component : components) {
+        for (auto* component : components) {
           logger_->log_debug("Clearing state for component %s", component->getComponentName());
           auto state_manager = state_manager_provider->getCoreComponentStateManager(component->getComponentUUID());
           if (state_manager != nullptr) {
diff --git a/libminifi/src/c2/C2Client.cpp b/libminifi/src/c2/C2Client.cpp
index d738a92..c9782e4 100644
--- a/libminifi/src/c2/C2Client.cpp
+++ b/libminifi/src/c2/C2Client.cpp
@@ -59,7 +59,7 @@ bool C2Client::isC2Enabled() const {
   return utils::StringUtils::toBool(c2_enable_str).value_or(false);
 }
 
-void C2Client::initialize(core::controller::ControllerServiceProvider *controller, state::Pausable *pause_handler, const std::shared_ptr<state::StateMonitor> &update_sink) {
+void C2Client::initialize(core::controller::ControllerServiceProvider *controller, state::Pausable *pause_handler, state::StateMonitor* update_sink) {
   if (!isC2Enabled()) {
     return;
   }
@@ -79,7 +79,7 @@ void C2Client::initialize(core::controller::ControllerServiceProvider *controlle
 
   // root_response_nodes_ was not cleared before, it is unclear if that was intentional
 
-  std::map<std::string, std::shared_ptr<Connection>> connections;
+  std::map<std::string, Connection*> connections;
   if (root_ != nullptr) {
     root_->getConnections(connections);
   }
@@ -89,27 +89,28 @@ void C2Client::initialize(core::controller::ControllerServiceProvider *controlle
     std::vector<std::string> classes = utils::StringUtils::split(class_csv, ",");
 
     for (const std::string& clazz : classes) {
-      auto response_node = std::dynamic_pointer_cast<state::response::ResponseNode>(core::ClassLoader::getDefaultClassLoader().instantiate(clazz, clazz));
+      auto instance = core::ClassLoader::getDefaultClassLoader().instantiate(clazz, clazz);
+      auto response_node = utils::dynamic_unique_cast<state::response::ResponseNode>(std::move(instance));
       if (nullptr == response_node) {
         logger_->log_error("No metric defined for %s", clazz);
         continue;
       }
-      auto identifier = std::dynamic_pointer_cast<state::response::AgentIdentifier>(response_node);
+      auto identifier = dynamic_cast<state::response::AgentIdentifier*>(response_node.get());
       if (identifier != nullptr) {
         identifier->setAgentIdentificationProvider(configuration_);
       }
-      auto monitor = std::dynamic_pointer_cast<state::response::AgentMonitor>(response_node);
+      auto monitor = dynamic_cast<state::response::AgentMonitor*>(response_node.get());
       if (monitor != nullptr) {
         monitor->addRepository(provenance_repo_);
         monitor->addRepository(flow_file_repo_);
         monitor->setStateMonitor(update_sink);
       }
-      auto configuration_checksums = std::dynamic_pointer_cast<state::response::ConfigurationChecksums>(response_node);
+      auto configuration_checksums = dynamic_cast<state::response::ConfigurationChecksums*>(response_node.get());
       if (configuration_checksums) {
         configuration_checksums->addChecksumCalculator(configuration_->getChecksumCalculator());
         configuration_checksums->addChecksumCalculator(flow_configuration_->getChecksumCalculator());
       }
-      auto flowMonitor = std::dynamic_pointer_cast<state::response::FlowMonitor>(response_node);
+      auto flowMonitor = dynamic_cast<state::response::FlowMonitor*>(response_node.get());
       if (flowMonitor != nullptr) {
         for (auto &con : connections) {
           flowMonitor->addConnection(con.second);
@@ -117,8 +118,9 @@ void C2Client::initialize(core::controller::ControllerServiceProvider *controlle
         flowMonitor->setStateMonitor(update_sink);
         flowMonitor->setFlowVersion(flow_configuration_->getFlowVersion());
       }
+      const auto responseNodeName = response_node->getName();
       std::lock_guard<std::mutex> guard(metrics_mutex_);
-      root_response_nodes_[response_node->getName()] = response_node;
+      root_response_nodes_[responseNodeName] = std::move(response_node);
     }
   }
 
@@ -130,7 +132,7 @@ void C2Client::initialize(core::controller::ControllerServiceProvider *controlle
   if (!initialized_) {
     // C2Agent is initialized once, meaning that a C2-triggered flow/configuration update
     // might not be equal to a fresh restart
-    c2_agent_ = std::unique_ptr<c2::C2Agent>(new c2::C2Agent(controller, pause_handler, update_sink, configuration_, filesystem_));
+    c2_agent_ = std::make_unique<c2::C2Agent>(controller, pause_handler, update_sink, configuration_, filesystem_);
     c2_agent_->start();
     initialized_ = true;
   }
@@ -152,10 +154,10 @@ void C2Client::initializeComponentMetrics() {
   if (root_ == nullptr) {
     return;
   }
-  std::vector<std::shared_ptr<core::Processor>> processors;
+  std::vector<core::Processor*> processors;
   root_->getAllProcessors(processors);
-  for (const auto &processor : processors) {
-    auto rep = std::dynamic_pointer_cast<state::response::ResponseNodeSource>(processor);
+  for (const auto processor : processors) {
+    auto rep = dynamic_cast<state::response::ResponseNodeSource*>(processor);
     if (rep == nullptr) {
       continue;
     }
@@ -192,7 +194,7 @@ void C2Client::loadC2ResponseConfiguration(const std::string &prefix) {
         std::vector<std::string> classes = utils::StringUtils::split(class_definitions, ",");
         for (const std::string& clazz : classes) {
           // instantiate the object
-          auto ptr = core::ClassLoader::getDefaultClassLoader().instantiate(clazz, clazz);
+          std::shared_ptr<core::CoreComponent> ptr = core::ClassLoader::getDefaultClassLoader().instantiate(clazz, clazz);
           if (nullptr == ptr) {
             const bool found_metric = [&] {
               std::lock_guard<std::mutex> guard{metrics_mutex_};
@@ -255,7 +257,7 @@ std::shared_ptr<state::response::ResponseNode> C2Client::loadC2ResponseConfigura
           std::vector<std::string> classes = utils::StringUtils::split(class_definitions, ",");
           for (const std::string& clazz : classes) {
             // instantiate the object
-            auto ptr = core::ClassLoader::getDefaultClassLoader().instantiate(clazz, clazz);
+            std::shared_ptr<core::CoreComponent> ptr = core::ClassLoader::getDefaultClassLoader().instantiate(clazz, clazz);
             if (nullptr == ptr) {
               const bool found_metric = [&] {
                 std::lock_guard<std::mutex> guard{metrics_mutex_};
diff --git a/libminifi/src/c2/ControllerSocketProtocol.cpp b/libminifi/src/c2/ControllerSocketProtocol.cpp
index 0bafce5..0afa8e0 100644
--- a/libminifi/src/c2/ControllerSocketProtocol.cpp
+++ b/libminifi/src/c2/ControllerSocketProtocol.cpp
@@ -34,7 +34,7 @@ namespace nifi {
 namespace minifi {
 namespace c2 {
 
-void ControllerSocketProtocol::initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink,
+void ControllerSocketProtocol::initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink,
                                           const std::shared_ptr<Configure> &configuration) {
   HeartbeatReporter::initialize(controller, updateSink, configuration);
   stream_factory_ = minifi::io::StreamFactory::getInstance(configuration);
diff --git a/libminifi/src/c2/HeartbeatLogger.cpp b/libminifi/src/c2/HeartbeatLogger.cpp
index 5f9ba3b..90e5bc9 100644
--- a/libminifi/src/c2/HeartbeatLogger.cpp
+++ b/libminifi/src/c2/HeartbeatLogger.cpp
@@ -35,7 +35,7 @@ int16_t HeartbeatLogger::heartbeat(const C2Payload &heartbeat) {
   return 0;
 }
 
-void HeartbeatLogger::initialize(core::controller::ControllerServiceProvider* controller, const std::shared_ptr<state::StateMonitor> &updateSink, const std::shared_ptr<Configure> &configure) {
+void HeartbeatLogger::initialize(core::controller::ControllerServiceProvider* controller, state::StateMonitor* updateSink, const std::shared_ptr<Configure> &configure) {
   HeartbeatReporter::initialize(controller, updateSink, configure);
   RESTProtocol::initialize(controller, configure);
 }
diff --git a/libminifi/src/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.cpp b/libminifi/src/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.cpp
index 3c7467b..4160db9 100644
--- a/libminifi/src/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.cpp
+++ b/libminifi/src/controllers/keyvalue/AbstractCoreComponentStateManagerProvider.cpp
@@ -71,9 +71,9 @@ namespace minifi {
 namespace controllers {
 
 AbstractCoreComponentStateManagerProvider::AbstractCoreComponentStateManager::AbstractCoreComponentStateManager(
-    std::shared_ptr<AbstractCoreComponentStateManagerProvider> provider,
+    AbstractCoreComponentStateManagerProvider* provider,
     const utils::Identifier& id)
-    : provider_(std::move(provider))
+    : provider_(provider)
     , id_(id)
     , state_valid_(false)
     , transaction_in_progress_(false)
@@ -85,10 +85,6 @@ AbstractCoreComponentStateManagerProvider::AbstractCoreComponentStateManager::Ab
   }
 }
 
-AbstractCoreComponentStateManagerProvider::AbstractCoreComponentStateManager::~AbstractCoreComponentStateManager() {
-  provider_->removeFromCache(id_);
-}
-
 bool AbstractCoreComponentStateManagerProvider::AbstractCoreComponentStateManager::set(const core::CoreComponentState& kvs) {
   bool autoCommit = false;
   if (!transaction_in_progress_) {
@@ -200,28 +196,9 @@ bool AbstractCoreComponentStateManagerProvider::AbstractCoreComponentStateManage
   return true;
 }
 
-std::shared_ptr<core::CoreComponentStateManager> AbstractCoreComponentStateManagerProvider::getCoreComponentStateManager(const utils::Identifier& uuid) {
-  std::lock_guard<std::mutex> guard(mutex_);
-
-  const auto iter = state_manager_cache_.find(uuid);
-  if (iter == state_manager_cache_.end()) {
-    auto stateManager = std::make_shared<AbstractCoreComponentStateManager>(shared_from_this(), uuid);
-    state_manager_cache_.emplace(uuid, stateManager);
-    return stateManager;
-  }
-
-  auto cachedStateManager = iter->second.lock();
-  if (!cachedStateManager) {
-    auto stateManager = std::make_shared<AbstractCoreComponentStateManager>(shared_from_this(), uuid);
-    iter->second = stateManager;
-    return stateManager;
-  }
-  return cachedStateManager;
-}
-
-void AbstractCoreComponentStateManagerProvider::removeFromCache(const utils::Identifier id) {
+std::unique_ptr<core::CoreComponentStateManager> AbstractCoreComponentStateManagerProvider::getCoreComponentStateManager(const utils::Identifier& uuid) {
   std::lock_guard<std::mutex> guard(mutex_);
-  state_manager_cache_.erase(id);
+  return std::make_unique<AbstractCoreComponentStateManager>(this, uuid);
 }
 
 std::map<utils::Identifier, core::CoreComponentState> AbstractCoreComponentStateManagerProvider::getAllCoreComponentStates() {
diff --git a/libminifi/src/core/Connectable.cpp b/libminifi/src/core/Connectable.cpp
index 310d2de..a35117f 100644
--- a/libminifi/src/core/Connectable.cpp
+++ b/libminifi/src/core/Connectable.cpp
@@ -141,39 +141,37 @@ void Connectable::notifyWork() {
   }
 }
 
-std::set<std::shared_ptr<Connectable>> Connectable::getOutGoingConnections(const std::string &relationship) const {
-  std::set<std::shared_ptr<Connectable>> empty;
-
-  const auto &&it = out_going_connections_.find(relationship);
-  if (it != out_going_connections_.end()) {
+std::set<Connectable*> Connectable::getOutGoingConnections(const std::string &relationship) {
+  const auto it = outgoing_connections_.find(relationship);
+  if (it != outgoing_connections_.end()) {
     return it->second;
   } else {
-    return empty;
+    return {};
   }
 }
 
-std::shared_ptr<Connectable> Connectable::getNextIncomingConnection() {
+Connectable* Connectable::getNextIncomingConnection() {
   std::lock_guard<std::mutex> lock(relationship_mutex_);
   return getNextIncomingConnectionImpl(lock);
 }
 
-std::shared_ptr<Connectable> Connectable::getNextIncomingConnectionImpl(const std::lock_guard<std::mutex>& /*relatioship_mutex_lock*/) {
-  if (_incomingConnections.size() == 0)
+Connectable* Connectable::getNextIncomingConnectionImpl(const std::lock_guard<std::mutex>& /*relatioship_mutex_lock*/) {
+  if (incoming_connections_.empty())
     return nullptr;
 
-  if (incoming_connections_Iter == _incomingConnections.end())
-    incoming_connections_Iter = _incomingConnections.begin();
+  if (incoming_connections_Iter == incoming_connections_.end())
+    incoming_connections_Iter = incoming_connections_.begin();
 
-  std::shared_ptr<Connectable> ret = *incoming_connections_Iter;
+  auto ret = *incoming_connections_Iter;
   incoming_connections_Iter++;
 
-  if (incoming_connections_Iter == _incomingConnections.end())
-    incoming_connections_Iter = _incomingConnections.begin();
+  if (incoming_connections_Iter == incoming_connections_.end())
+    incoming_connections_Iter = incoming_connections_.begin();
 
   return ret;
 }
 
-std::shared_ptr<Connectable> Connectable::pickIncomingConnection() {
+Connectable* Connectable::pickIncomingConnection() {
   return getNextIncomingConnection();
 }
 
diff --git a/libminifi/src/core/FlowConfiguration.cpp b/libminifi/src/core/FlowConfiguration.cpp
index d6ebd1b..f7108d4 100644
--- a/libminifi/src/core/FlowConfiguration.cpp
+++ b/libminifi/src/core/FlowConfiguration.cpp
@@ -75,7 +75,7 @@ FlowConfiguration::~FlowConfiguration() {
   }
 }
 
-std::shared_ptr<core::Processor> FlowConfiguration::createProcessor(const std::string &name, const utils::Identifier &uuid) {
+std::unique_ptr<core::Processor> FlowConfiguration::createProcessor(const std::string &name, const utils::Identifier &uuid) {
   auto processor = minifi::processors::ProcessorUtils::createProcessor(name, name, uuid, stream_factory_);
   if (nullptr == processor) {
     logger_->log_error("No Processor defined for %s", name);
@@ -84,7 +84,7 @@ std::shared_ptr<core::Processor> FlowConfiguration::createProcessor(const std::s
   return processor;
 }
 
-std::shared_ptr<core::Processor> FlowConfiguration::createProcessor(const std::string &name, const std::string &fullname, const utils::Identifier &uuid) {
+std::unique_ptr<core::Processor> FlowConfiguration::createProcessor(const std::string &name, const std::string &fullname, const utils::Identifier &uuid) {
   auto processor = minifi::processors::ProcessorUtils::createProcessor(name, fullname, uuid, stream_factory_);
   if (nullptr == processor) {
     logger_->log_error("No Processor defined for %s", fullname);
@@ -93,9 +93,8 @@ std::shared_ptr<core::Processor> FlowConfiguration::createProcessor(const std::s
   return processor;
 }
 
-std::shared_ptr<core::Processor> FlowConfiguration::createProvenanceReportTask() {
-  std::shared_ptr<core::Processor> processor = std::make_shared<org::apache::nifi::minifi::core::reporting::SiteToSiteProvenanceReportingTask>(stream_factory_, this->configuration_);
-  // initialize the processor
+std::unique_ptr<core::reporting::SiteToSiteProvenanceReportingTask> FlowConfiguration::createProvenanceReportTask() {
+  auto processor = std::make_unique<org::apache::nifi::minifi::core::reporting::SiteToSiteProvenanceReportingTask>(stream_factory_, this->configuration_);
   processor->initialize();
   return processor;
 }
@@ -159,8 +158,8 @@ std::unique_ptr<core::ProcessGroup> FlowConfiguration::createRemoteProcessGroup(
   return std::make_unique<core::ProcessGroup>(core::REMOTE_PROCESS_GROUP, name, uuid);
 }
 
-std::shared_ptr<minifi::Connection> FlowConfiguration::createConnection(const std::string& name, const utils::Identifier& uuid) const {
-  return std::make_shared<minifi::Connection>(flow_file_repo_, content_repo_, name, uuid);
+std::unique_ptr<minifi::Connection> FlowConfiguration::createConnection(const std::string& name, const utils::Identifier& uuid) const {
+  return std::make_unique<minifi::Connection>(flow_file_repo_, content_repo_, name, uuid);
 }
 
 std::shared_ptr<core::controller::ControllerServiceNode> FlowConfiguration::createControllerService(const std::string &class_name, const std::string &full_class_name, const std::string &name,
diff --git a/libminifi/src/core/FlowFile.cpp b/libminifi/src/core/FlowFile.cpp
index 22a75f2..ec70326 100644
--- a/libminifi/src/core/FlowFile.cpp
+++ b/libminifi/src/core/FlowFile.cpp
@@ -207,7 +207,7 @@ void FlowFile::setLineageStartDate(const std::chrono::system_clock::time_point d
  * Sets the original connection with a shared pointer.
  * @param connection shared connection.
  */
-void FlowFile::setConnection(const std::shared_ptr<core::Connectable>& connection) {
+void FlowFile::setConnection(core::Connectable* connection) {
   connection_ = connection;
 }
 
@@ -215,7 +215,7 @@ void FlowFile::setConnection(const std::shared_ptr<core::Connectable>& connectio
  * Returns the original connection referenced by this record.
  * @return shared original connection pointer.
  */
-std::shared_ptr<core::Connectable> FlowFile::getConnection() const {
+core::Connectable* FlowFile::getConnection() const {
   return connection_;
 }
 
diff --git a/libminifi/src/core/Funnel.cpp b/libminifi/src/core/Funnel.cpp
index 2dc6691..e6b89b5 100644
--- a/libminifi/src/core/Funnel.cpp
+++ b/libminifi/src/core/Funnel.cpp
@@ -15,7 +15,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #include "core/Funnel.h"
+#include "core/ProcessSession.h"
 
 namespace org {
 namespace apache {
diff --git a/libminifi/src/core/ProcessGroup.cpp b/libminifi/src/core/ProcessGroup.cpp
index bfe4d4d..3c8a96c 100644
--- a/libminifi/src/core/ProcessGroup.cpp
+++ b/libminifi/src/core/ProcessGroup.cpp
@@ -18,17 +18,17 @@
  * limitations under the License.
  */
 #include "core/ProcessGroup.h"
-#include <time.h>
 #include <vector>
 #include <memory>
 #include <string>
-#include <queue>
 #include <map>
 #include <set>
 #include <chrono>
 #include <thread>
-#include "core/Processor.h"
 #include "core/logging/LoggerConfiguration.h"
+#include "core/Processor.h"
+#include "core/state/ProcessorController.h"
+#include "core/state/UpdateController.h"
 
 using namespace std::literals::chrono_literals;
 
@@ -71,7 +71,7 @@ ProcessGroup::ProcessGroup(ProcessGroupType type, const std::string& name)
     : CoreComponent(name, {}, id_generator_),
       config_version_(0),
       type_(type),
-      parent_process_group_(0),
+      parent_process_group_(nullptr),
       logger_(logging::LoggerFactory<ProcessGroup>::getLogger()) {
   yield_period_msec_ = 0ms;
   onschedule_retry_msec_ = ONSCHEDULE_RETRY_INTERVAL;
@@ -91,32 +91,20 @@ ProcessGroup::~ProcessGroup() {
   }
 }
 
-bool ProcessGroup::isRootProcessGroup() {
-  return (type_ == ROOT_PROCESS_GROUP);
-}
-
 bool ProcessGroup::isRemoteProcessGroup() {
   return (type_ == REMOTE_PROCESS_GROUP);
 }
 
 
-void ProcessGroup::addProcessor(const std::shared_ptr<Processor>& processor) {
-  std::lock_guard<std::recursive_mutex> lock(mutex_);
-
-  if (processors_.find(processor) == processors_.end()) {
-    // We do not have the same processor in this process group yet
-    processors_.insert(processor);
-    logger_->log_debug("Add processor %s into process group %s", processor->getName(), name_);
-  }
-}
-
-void ProcessGroup::removeProcessor(const std::shared_ptr<Processor>& processor) {
+void ProcessGroup::addProcessor(std::unique_ptr<Processor> processor) {
+  gsl_Expects(processor);
+  const auto name = processor->getName();
   std::lock_guard<std::recursive_mutex> lock(mutex_);
-
-  if (processors_.find(processor) != processors_.end()) {
-    // We do have the same processor in this process group yet
-    processors_.erase(processor);
-    logger_->log_debug("Remove processor %s from process group %s", processor->getName(), name_);
+  const auto [iter, inserted] = processors_.insert(std::move(processor));
+  if (inserted) {
+    logger_->log_debug("Add processor %s into process group %s", name, name_);
+  } else {
+    logger_->log_debug("Not adding processor %s into process group %s, as it is already there", name, name_);
   }
 }
 
@@ -134,9 +122,9 @@ void ProcessGroup::startProcessingProcessors(const std::shared_ptr<TimerDrivenSc
     const std::shared_ptr<EventDrivenSchedulingAgent> &eventScheduler, const std::shared_ptr<CronDrivenSchedulingAgent> &cronScheduler) {
   std::unique_lock<std::recursive_mutex> lock(mutex_);
 
-  std::set<std::shared_ptr<Processor> > failed_processors;
+  std::set<Processor*> failed_processors;
 
-  for (const auto &processor : failed_processors_) {
+  for (const auto processor : failed_processors_) {
     try {
       logger_->log_debug("Starting %s", processor->getName());
       switch (processor->getSchedulingStrategy()) {
@@ -162,7 +150,7 @@ void ProcessGroup::startProcessingProcessors(const std::shared_ptr<TimerDrivenSc
   }
   failed_processors_ = std::move(failed_processors);
 
-  for (auto& processor : failed_processors_) {
+  for (const auto processor : failed_processors_) {
     try {
       processor->onUnSchedule();
     } catch (...) {
@@ -175,7 +163,7 @@ void ProcessGroup::startProcessingProcessors(const std::shared_ptr<TimerDrivenSc
     auto func = [this, eventScheduler, cronScheduler, timeScheduler]() {
       this->startProcessingProcessors(timeScheduler, eventScheduler, cronScheduler);
     };
-    onScheduleTimer_.reset(new utils::CallBackTimer(std::chrono::milliseconds(onschedule_retry_msec_), func));
+    onScheduleTimer_ = std::make_unique<utils::CallBackTimer>(std::chrono::milliseconds(onschedule_retry_msec_), func);
     onScheduleTimer_->start();
   } else if (failed_processors_.empty() && onScheduleTimer_) {
     onScheduleTimer_->stop();
@@ -187,7 +175,10 @@ void ProcessGroup::startProcessing(const std::shared_ptr<TimerDrivenSchedulingAg
   std::lock_guard<std::recursive_mutex> lock(mutex_);
 
   try {
-    failed_processors_ = processors_;  // All processors are marked as failed.
+    // All processors are marked as failed.
+    for (auto& processor : processors_) {
+      failed_processors_.insert(processor.get());
+    }
 
     // Start all the processor node, input and output ports
     startProcessingProcessors(timeScheduler, eventScheduler, cronScheduler);
@@ -206,7 +197,7 @@ void ProcessGroup::startProcessing(const std::shared_ptr<TimerDrivenSchedulingAg
 }
 
 void ProcessGroup::stopProcessing(const std::shared_ptr<TimerDrivenSchedulingAgent>& timeScheduler, const std::shared_ptr<EventDrivenSchedulingAgent> &eventScheduler,
-                                  const std::shared_ptr<CronDrivenSchedulingAgent> &cronScheduler, const std::function<bool(const std::shared_ptr<Processor>&)>& filter) {
+                                  const std::shared_ptr<CronDrivenSchedulingAgent> &cronScheduler, const std::function<bool(const Processor*)>& filter) {
   std::lock_guard<std::recursive_mutex> lock(mutex_);
 
   if (onScheduleTimer_) {
@@ -218,19 +209,19 @@ void ProcessGroup::stopProcessing(const std::shared_ptr<TimerDrivenSchedulingAge
   try {
     // Stop all the processor node, input and output ports
     for (const auto &processor : processors_) {
-      if (!filter(processor)) {
+      if (filter && !filter(processor.get())) {
         continue;
       }
       logger_->log_debug("Stopping %s", processor->getName());
       switch (processor->getSchedulingStrategy()) {
         case TIMER_DRIVEN:
-          timeScheduler->unschedule(processor);
+          timeScheduler->unschedule(processor.get());
           break;
         case EVENT_DRIVEN:
-          eventScheduler->unschedule(processor);
+          eventScheduler->unschedule(processor.get());
           break;
         case CRON_DRIVEN:
-          cronScheduler->unschedule(processor);
+          cronScheduler->unschedule(processor.get());
           break;
       }
     }
@@ -247,8 +238,8 @@ void ProcessGroup::stopProcessing(const std::shared_ptr<TimerDrivenSchedulingAge
   }
 }
 
-std::shared_ptr<Processor> ProcessGroup::findProcessorById(const utils::Identifier& uuid, Traverse traverse) const {
-  const auto id_matches = [&] (const std::shared_ptr<Processor>& processor) {
+Processor* ProcessGroup::findProcessorById(const utils::Identifier& uuid, Traverse traverse) const {
+  const auto id_matches = [&] (const std::unique_ptr<Processor>& processor) {
     logger_->log_trace("Searching for processor by id, checking processor %s", processor->getName());
     utils::Identifier processorUUID = processor->getUUID();
     return processorUUID && uuid == processorUUID;
@@ -256,8 +247,8 @@ std::shared_ptr<Processor> ProcessGroup::findProcessorById(const utils::Identifi
   return findProcessor(id_matches, traverse);
 }
 
-std::shared_ptr<Processor> ProcessGroup::findProcessorByName(const std::string &processorName, Traverse traverse) const {
-  const auto name_matches = [&] (const std::shared_ptr<Processor>& processor) {
+Processor* ProcessGroup::findProcessorByName(const std::string &processorName, Traverse traverse) const {
+  const auto name_matches = [&] (const std::unique_ptr<Processor>& processor) {
     logger_->log_trace("Searching for processor by name, checking processor %s", processor->getName());
     return processor->getName() == processorName;
   };
@@ -277,19 +268,19 @@ std::shared_ptr<core::controller::ControllerServiceNode> ProcessGroup::findContr
   return controller_service_map_.getControllerServiceNode(nodeId);
 }
 
-void ProcessGroup::getAllProcessors(std::vector<std::shared_ptr<Processor>> &processor_vec) {
+void ProcessGroup::getAllProcessors(std::vector<Processor*>& processor_vec) const {
   std::lock_guard<std::recursive_mutex> lock(mutex_);
 
-  for (auto& processor : processors_) {
+  for (const auto& processor : processors_) {
     logger_->log_trace("Collecting all processors, current processor is %s", processor->getName());
-    processor_vec.push_back(processor);
+    processor_vec.push_back(processor.get());
   }
-  for (auto& processGroup : child_process_groups_) {
+  for (const auto& processGroup : child_process_groups_) {
     processGroup->getAllProcessors(processor_vec);
   }
 }
 
-void ProcessGroup::updatePropertyValue(std::string processorName, std::string propertyName, std::string propertyValue) {
+void ProcessGroup::updatePropertyValue(const std::string& processorName, const std::string& propertyName, const std::string& propertyValue) {
   std::lock_guard<std::recursive_mutex> lock(mutex_);
   for (auto& processor : processors_) {
     if (processor->getName() == processorName) {
@@ -301,79 +292,66 @@ void ProcessGroup::updatePropertyValue(std::string processorName, std::string pr
   }
 }
 
-void ProcessGroup::getConnections(std::map<std::string, std::shared_ptr<Connection>> &connectionMap) {
+void ProcessGroup::getConnections(std::map<std::string, Connection*>& connectionMap) {
   for (auto& connection : connections_) {
-    connectionMap[connection->getUUIDStr()] = connection;
-    connectionMap[connection->getName()] = connection;
+    connectionMap[connection->getUUIDStr()] = connection.get();
+    connectionMap[connection->getName()] = connection.get();
   }
   for (auto& processGroup : child_process_groups_) {
     processGroup->getConnections(connectionMap);
   }
 }
 
-void ProcessGroup::getConnections(std::map<std::string, std::shared_ptr<Connectable>> &connectionMap) {
+void ProcessGroup::getConnections(std::map<std::string, Connectable*>& connectionMap) {
   for (auto& connection : connections_) {
-    connectionMap[connection->getUUIDStr()] = connection;
-    connectionMap[connection->getName()] = connection;
+    connectionMap[connection->getUUIDStr()] = connection.get();
+    connectionMap[connection->getName()] = connection.get();
   }
   for (auto& processGroup : child_process_groups_) {
     processGroup->getConnections(connectionMap);
   }
 }
 
-void ProcessGroup::getFlowFileContainers(std::map<std::string, std::shared_ptr<Connectable>> &containers) const {
+void ProcessGroup::getFlowFileContainers(std::map<std::string, Connectable*>& containers) const {
   for (auto& connection : connections_) {
-    containers[connection->getUUIDStr()] = connection;
-    containers[connection->getName()] = connection;
+    containers[connection->getUUIDStr()] = connection.get();
+    containers[connection->getName()] = connection.get();
   }
   for (auto& processor : processors_) {
     // processors can also own FlowFiles
-    containers[processor->getUUIDStr()] = processor;
+    containers[processor->getUUIDStr()] = processor.get();
   }
   for (auto& processGroup : child_process_groups_) {
     processGroup->getFlowFileContainers(containers);
   }
 }
 
-void ProcessGroup::addConnection(const std::shared_ptr<Connection>& connection) {
+void ProcessGroup::addConnection(std::unique_ptr<Connection> connection) {
   std::lock_guard<std::recursive_mutex> lock(mutex_);
 
-  if (connections_.find(connection) == connections_.end()) {
-    // We do not have the same connection in this process group yet
-    connections_.insert(connection);
-    logger_->log_debug("Add connection %s into process group %s", connection->getName(), name_);
-    // only allow connections between processors of the same process group
-    std::shared_ptr<Processor> source = this->findProcessorById(connection->getSourceUUID(), Traverse::ExcludeChildren);
-    if (source) {
-      source->addConnection(connection);
-    } else {
-      logger_->log_error("Cannot find the source processor with id '%s' for the connection [name = '%s', id = '%s']",
-                         connection->getSourceUUID().to_string(), connection->getName(), connection->getUUIDStr());
-    }
-    std::shared_ptr<Processor> destination = this->findProcessorById(connection->getDestinationUUID(), Traverse::ExcludeChildren);
-    if (!destination) {
-      logger_->log_error("Cannot find the destination processor with id '%s' for the connection [name = '%s', id = '%s']",
-                         connection->getDestinationUUID().to_string(), connection->getName(), connection->getUUIDStr());
-    }
-    if (destination && destination != source) {
-      destination->addConnection(connection);
-    }
+  auto [insertPos, inserted] = connections_.insert(std::move(connection));
+  if (!inserted) {
+    return;
   }
-}
 
-void ProcessGroup::removeConnection(const std::shared_ptr<Connection>& connection) {
-  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  auto& insertedConnection = *insertPos;
 
-  if (connections_.find(connection) != connections_.end()) {
-    // We do not have the same connection in this process group yet
-    connections_.erase(connection);
-    logger_->log_debug("Remove connection %s into process group %s", connection->getName(), name_);
-    std::shared_ptr<Processor> source = this->findProcessorById(connection->getSourceUUID());
-    if (source)
-      source->removeConnection(connection);
-    std::shared_ptr<Processor> destination = this->findProcessorById(connection->getDestinationUUID());
-    if (destination && destination != source)
-      destination->removeConnection(connection);
+  logger_->log_debug("Add connection %s into process group %s", insertedConnection->getName(), name_);
+  // only allow connections between processors of the same process group
+  auto source = this->findProcessorById(insertedConnection->getSourceUUID(), Traverse::ExcludeChildren);
+  if (source) {
+    source->addConnection(insertedConnection.get());
+  } else {
+    logger_->log_error("Cannot find the source processor with id '%s' for the connection [name = '%s', id = '%s']",
+                       insertedConnection->getSourceUUID().to_string(), insertedConnection->getName(), insertedConnection->getUUIDStr());
+  }
+  auto destination = this->findProcessorById(insertedConnection->getDestinationUUID(), Traverse::ExcludeChildren);
+  if (!destination) {
+    logger_->log_error("Cannot find the destination processor with id '%s' for the connection [name = '%s', id = '%s']",
+                       insertedConnection->getDestinationUUID().to_string(), insertedConnection->getName(), insertedConnection->getUUIDStr());
+  }
+  if (destination && destination != source) {
+    destination->addConnection(insertedConnection.get());
   }
 }
 
diff --git a/libminifi/src/core/ProcessSession.cpp b/libminifi/src/core/ProcessSession.cpp
index ccc64ae..1c3f0c8 100644
--- a/libminifi/src/core/ProcessSession.cpp
+++ b/libminifi/src/core/ProcessSession.cpp
@@ -759,7 +759,7 @@ ProcessSession::RouteResult ProcessSession::routeFlowFile(const std::shared_ptr<
   }
   Relationship relationship = itRelationship->second;
   // Find the relationship, we need to find the connections for that relationship
-  std::set<std::shared_ptr<Connectable>> connections = process_context_->getProcessorNode()->getOutGoingConnections(relationship.getName());
+  const auto connections = process_context_->getProcessorNode()->getOutGoingConnections(relationship.getName());
   if (connections.empty()) {
     // No connection
     if (!process_context_->getProcessorNode()->isAutoTerminated(relationship)) {
@@ -773,7 +773,7 @@ ProcessSession::RouteResult ProcessSession::routeFlowFile(const std::shared_ptr<
   } else {
     // We connections, clone the flow and assign the connection accordingly
     for (auto itConnection = connections.begin(); itConnection != connections.end(); ++itConnection) {
-      std::shared_ptr<Connectable> connection = *itConnection;
+      auto connection = *itConnection;
       if (itConnection == connections.begin()) {
         // First connection which the flow need be routed to
         record->setConnection(connection);
@@ -810,9 +810,9 @@ void ProcessSession::commit() {
       }
     }
 
-    std::map<std::shared_ptr<Connectable>, std::vector<std::shared_ptr<FlowFile>>> connectionQueues;
+    std::map<Connectable*, std::vector<std::shared_ptr<FlowFile>>> connectionQueues;
 
-    std::shared_ptr<Connectable> connection = nullptr;
+    Connectable* connection = nullptr;
     // Complete process the added and update flow files for the session, send the flow file to its queue
     for (const auto &it : _updatedFlowFiles) {
       auto record = it.second.modified;
@@ -870,7 +870,7 @@ void ProcessSession::commit() {
     persistFlowFilesBeforeTransfer(connectionQueues, _updatedFlowFiles);
 
     for (auto& cq : connectionQueues) {
-      auto connection = std::dynamic_pointer_cast<Connection>(cq.first);
+      auto connection = dynamic_cast<Connection*>(cq.first);
       if (connection) {
         connection->multiPut(cq.second);
       } else {
@@ -902,7 +902,7 @@ void ProcessSession::commit() {
 void ProcessSession::rollback() {
   // new FlowFiles are only persisted during commit
   // no need to delete them here
-  std::map<std::shared_ptr<Connectable>, std::vector<std::shared_ptr<FlowFile>>> connectionQueues;
+  std::map<Connectable*, std::vector<std::shared_ptr<FlowFile>>> connectionQueues;
 
   try {
     // Requeue the snapshot of the flowfile back
@@ -924,7 +924,7 @@ void ProcessSession::rollback() {
 
     // put everything back where it came from
     for (auto& cq : connectionQueues) {
-      auto connection = std::dynamic_pointer_cast<Connection>(cq.first);
+      auto connection = dynamic_cast<Connection*>(cq.first);
       if (connection) {
         connection->multiPut(cq.second);
       } else {
@@ -955,7 +955,7 @@ void ProcessSession::rollback() {
 }
 
 void ProcessSession::persistFlowFilesBeforeTransfer(
-    std::map<std::shared_ptr<Connectable>, std::vector<std::shared_ptr<core::FlowFile> > >& transactionMap,
+    std::map<Connectable*, std::vector<std::shared_ptr<core::FlowFile> > >& transactionMap,
     const std::map<utils::Identifier, FlowFileUpdate>& modifiedFlowFiles) {
 
   std::vector<std::pair<std::string, std::unique_ptr<io::BufferStream>>> flowData;
@@ -963,11 +963,9 @@ void ProcessSession::persistFlowFilesBeforeTransfer(
   auto flowFileRepo = process_context_->getFlowFileRepository();
   auto contentRepo = process_context_->getContentRepository();
 
-  for (auto& transaction : transactionMap) {
-    const std::shared_ptr<Connectable>& target = transaction.first;
-    std::shared_ptr<Connection> connection = std::dynamic_pointer_cast<Connection>(target);
-    const bool shouldDropEmptyFiles = connection ? connection->getDropEmptyFlowFiles() : false;
-    auto& flows = transaction.second;
+  for (auto& [target, flows] : transactionMap) {
+    const auto connection = dynamic_cast<Connection*>(target);
+    const bool shouldDropEmptyFiles = connection && connection->getDropEmptyFlowFiles();
     for (auto &ff : flows) {
       if (shouldDropEmptyFiles && ff->getSize() == 0) {
         // the receiver will drop this FF
@@ -986,11 +984,9 @@ void ProcessSession::persistFlowFilesBeforeTransfer(
     throw Exception(PROCESS_SESSION_EXCEPTION, "Failed to put flowfiles to repository");
   }
 
-  for (auto& transaction : transactionMap) {
-    const std::shared_ptr<Connectable>& target = transaction.first;
-    std::shared_ptr<Connection> connection = std::dynamic_pointer_cast<Connection>(target);
-    const bool shouldDropEmptyFiles = connection ? connection->getDropEmptyFlowFiles() : false;
-    auto& flows = transaction.second;
+  for (auto& [target, flows] : transactionMap) {
+    const auto connection = dynamic_cast<Connection*>(target);
+    const bool shouldDropEmptyFiles = connection && connection->getDropEmptyFlowFiles();
     for (auto &ff : flows) {
       utils::Identifier uuid = ff->getUUID();
       auto snapshotIt = modifiedFlowFiles.find(uuid);
@@ -1018,7 +1014,7 @@ void ProcessSession::persistFlowFilesBeforeTransfer(
 }
 
 void ProcessSession::ensureNonNullResourceClaim(
-    const std::map<std::shared_ptr<Connectable>, std::vector<std::shared_ptr<core::FlowFile>>> &transactionMap) {
+    const std::map<Connectable*, std::vector<std::shared_ptr<core::FlowFile>>> &transactionMap) {
   for (auto& transaction : transactionMap) {
     for (auto& flowFile : transaction.second) {
       auto claim = flowFile->getResourceClaim();
@@ -1034,14 +1030,19 @@ void ProcessSession::ensureNonNullResourceClaim(
 }
 
 std::shared_ptr<core::FlowFile> ProcessSession::get() {
-  std::shared_ptr<Connectable> first = process_context_->getProcessorNode()->pickIncomingConnection();
+  const auto first = process_context_->getProcessorNode()->pickIncomingConnection();
 
   if (first == nullptr) {
     logger_->log_trace("Get is null for %s", process_context_->getProcessorNode()->getName());
     return nullptr;
   }
 
-  std::shared_ptr<Connection> current = std::static_pointer_cast<Connection>(first);
+  auto current = dynamic_cast<Connection*>(first);
+  if (!current) {
+    logger_->log_error("The incoming connection [%s] of the processor [%s] \"%s\" is not actually a Connection.",
+                       first->getUUIDStr(), process_context_->getProcessorNode()->getUUIDStr(), process_context_->getProcessorNode()->getName());
+    return {};
+  }
 
   do {
     std::set<std::shared_ptr<core::FlowFile> > expired;
@@ -1072,7 +1073,7 @@ std::shared_ptr<core::FlowFile> ProcessSession::get() {
       }
       return ret;
     }
-    current = std::static_pointer_cast<Connection>(process_context_->getProcessorNode()->pickIncomingConnection());
+    current = dynamic_cast<Connection*>(process_context_->getProcessorNode()->pickIncomingConnection());
   } while (current != nullptr && current != first);
 
   return nullptr;
@@ -1083,10 +1084,10 @@ void ProcessSession::flushContent() {
 }
 
 bool ProcessSession::outgoingConnectionsFull(const std::string& relationship) {
-  std::set<std::shared_ptr<Connectable>> connections = process_context_->getProcessorNode()->getOutGoingConnections(relationship);
+  std::set<Connectable*> connections = process_context_->getProcessorNode()->getOutGoingConnections(relationship);
   Connection * connection = nullptr;
-  for (const auto& conn : connections) {
-    connection = dynamic_cast<Connection*>(conn.get());
+  for (const auto conn : connections) {
+    connection = dynamic_cast<Connection*>(conn);
     if (connection && connection->isFull()) {
       return true;
     }
diff --git a/libminifi/src/core/Processor.cpp b/libminifi/src/core/Processor.cpp
index f31f7c0..30c8381 100644
--- a/libminifi/src/core/Processor.cpp
+++ b/libminifi/src/core/Processor.cpp
@@ -51,7 +51,6 @@ Processor::Processor(const std::string& name)
   // Setup the default values
   state_ = DISABLED;
   strategy_ = TIMER_DRIVEN;
-  loss_tolerant_ = false;
   _triggerWhenEmpty = false;
   scheduling_period_nano_ = MINIMUM_SCHEDULING_NANOS;
   run_duration_nano_ = DEFAULT_RUN_DURATION;
@@ -59,7 +58,7 @@ Processor::Processor(const std::string& name)
   penalization_period_ = DEFAULT_PENALIZATION_PERIOD;
   max_concurrent_tasks_ = DEFAULT_MAX_CONCURRENT_TASKS;
   active_tasks_ = 0;
-  incoming_connections_Iter = this->_incomingConnections.begin();
+  incoming_connections_Iter = this->incoming_connections_.begin();
   logger_->log_debug("Processor %s created UUID %s", name_, getUUIDStr());
 }
 
@@ -71,7 +70,6 @@ Processor::Processor(const std::string& name, const utils::Identifier& uuid)
   // Setup the default values
   state_ = DISABLED;
   strategy_ = TIMER_DRIVEN;
-  loss_tolerant_ = false;
   _triggerWhenEmpty = false;
   scheduling_period_nano_ = MINIMUM_SCHEDULING_NANOS;
   run_duration_nano_ = DEFAULT_RUN_DURATION;
@@ -79,7 +77,7 @@ Processor::Processor(const std::string& name, const utils::Identifier& uuid)
   penalization_period_ = DEFAULT_PENALIZATION_PERIOD;
   max_concurrent_tasks_ = DEFAULT_MAX_CONCURRENT_TASKS;
   active_tasks_ = 0;
-  incoming_connections_Iter = this->_incomingConnections.begin();
+  incoming_connections_Iter = this->incoming_connections_.begin();
   logger_->log_debug("Processor %s created with uuid %s", name_, getUUIDStr());
 }
 
@@ -94,7 +92,7 @@ void Processor::setScheduledState(ScheduledState state) {
   }
 }
 
-bool Processor::addConnection(std::shared_ptr<Connectable> conn) {
+bool Processor::addConnection(Connectable* conn) {
   enum class SetAs{
     NONE,
     OUTPUT,
@@ -106,7 +104,11 @@ bool Processor::addConnection(std::shared_ptr<Connectable> conn) {
     logger_->log_warn("Can not add connection while the process %s is running", name_);
     return false;
   }
-  std::shared_ptr<Connection> connection = std::static_pointer_cast<Connection>(conn);
+  const auto connection = dynamic_cast<Connection*>(conn);
+  if (!connection) {
+    return false;
+  }
+
   std::lock_guard<std::mutex> lock(getGraphMutex());
 
   auto updateGraph = gsl::finally([&] {
@@ -122,37 +124,36 @@ bool Processor::addConnection(std::shared_ptr<Connectable> conn) {
 
   if (uuid_ == destUUID) {
     // Connection is destination to the current processor
-    if (_incomingConnections.find(connection) == _incomingConnections.end()) {
-      _incomingConnections.insert(connection);
-      connection->setDestination(shared_from_this());
+    if (incoming_connections_.find(connection) == incoming_connections_.end()) {
+      incoming_connections_.insert(connection);
+      connection->setDestination(this);
       logger_->log_debug("Add connection %s into Processor %s incoming connection", connection->getName(), name_);
-      incoming_connections_Iter = this->_incomingConnections.begin();
+      incoming_connections_Iter = this->incoming_connections_.begin();
       result = SetAs::OUTPUT;
     }
   }
   if (uuid_ == srcUUID) {
-    const auto &rels = connection->getRelationships();
-    for (auto i = rels.begin(); i != rels.end(); i++) {
-      const auto relationship = (*i).getName();
+    for (const auto& rel : connection->getRelationships()) {
+      const auto relationship = rel.getName();
       // Connection is source from the current processor
-      auto &&it = out_going_connections_.find(relationship);
-      if (it != out_going_connections_.end()) {
+      auto &&it = outgoing_connections_.find(relationship);
+      if (it != outgoing_connections_.end()) {
         // We already has connection for this relationship
-        std::set<std::shared_ptr<Connectable>> existedConnection = it->second;
+        std::set<Connectable*> existedConnection = it->second;
         if (existedConnection.find(connection) == existedConnection.end()) {
           // We do not have the same connection for this relationship yet
           existedConnection.insert(connection);
-          connection->setSource(shared_from_this());
-          out_going_connections_[relationship] = existedConnection;
+          connection->setSource(this);
+          outgoing_connections_[relationship] = existedConnection;
           logger_->log_debug("Add connection %s into Processor %s outgoing connection for relationship %s", connection->getName(), name_, relationship);
           result = SetAs::INPUT;
         }
       } else {
         // We do not have any outgoing connection for this relationship yet
-        std::set<std::shared_ptr<Connectable>> newConnection;
+        std::set<Connectable*> newConnection;
         newConnection.insert(connection);
-        connection->setSource(shared_from_this());
-        out_going_connections_[relationship] = newConnection;
+        connection->setSource(this);
+        outgoing_connections_[relationship] = newConnection;
         logger_->log_debug("Add connection %s into Processor %s outgoing connection for relationship %s", connection->getName(), name_, relationship);
         result = SetAs::INPUT;
       }
@@ -161,54 +162,14 @@ bool Processor::addConnection(std::shared_ptr<Connectable> conn) {
   return result != SetAs::NONE;
 }
 
-void Processor::removeConnection(std::shared_ptr<Connectable> conn) {
-  if (isRunning()) {
-    logger_->log_warn("Can not remove connection while the process %s is running", name_);
-    return;
-  }
-
-  std::lock_guard<std::mutex> lock(getGraphMutex());
-
-  std::shared_ptr<Connection> connection = std::static_pointer_cast<Connection>(conn);
-
-  utils::Identifier srcUUID = connection->getSourceUUID();
-  utils::Identifier destUUID = connection->getDestinationUUID();
-
-  if (uuid_ == destUUID) {
-    // Connection is destination to the current processor
-    if (_incomingConnections.find(connection) != _incomingConnections.end()) {
-      _incomingConnections.erase(connection);
-      connection->setDestination(NULL);
-      logger_->log_debug("Remove connection %s into Processor %s incoming connection", connection->getName(), name_);
-      incoming_connections_Iter = this->_incomingConnections.begin();
-    }
-  }
-
-  if (uuid_ == srcUUID) {
-    const auto &rels = connection->getRelationships();
-    for (auto i = rels.begin(); i != rels.end(); i++) {
-      const auto relationship = (*i).getName();
-      // Connection is source from the current processor
-      auto &&it = out_going_connections_.find(relationship);
-      if (it != out_going_connections_.end()) {
-        if (out_going_connections_[relationship].find(connection) != out_going_connections_[relationship].end()) {
-          out_going_connections_[relationship].erase(connection);
-          connection->setSource(NULL);
-          logger_->log_debug("Remove connection %s into Processor %s outgoing connection for relationship %s", connection->getName(), name_, relationship);
-        }
-      }
-    }
-  }
-}
-
 bool Processor::flowFilesOutGoingFull() const {
   std::lock_guard<std::mutex> lock(mutex_);
 
-  for (const auto& connection_pair : out_going_connections_) {
+  for (const auto& connection_pair : outgoing_connections_) {
     // We already has connection for this relationship
-    std::set<std::shared_ptr<Connectable>> existedConnection = connection_pair.second;
-    const bool has_full_connection = std::any_of(begin(existedConnection), end(existedConnection), [](const std::shared_ptr<Connectable>& conn) {
-      auto connection = std::dynamic_pointer_cast<Connection>(conn);
+    std::set<Connectable*> existedConnection = connection_pair.second;
+    const bool has_full_connection = std::any_of(begin(existedConnection), end(existedConnection), [](const Connectable* conn) {
+      auto connection = dynamic_cast<const Connection*>(conn);
       return connection && connection->isFull();
     });
     if (has_full_connection) { return true; }
@@ -261,8 +222,11 @@ bool Processor::isWorkAvailable() {
   bool hasWork = false;
 
   try {
-    for (const auto &conn : _incomingConnections) {
-      std::shared_ptr<Connection> connection = std::static_pointer_cast<Connection>(conn);
+    for (const auto &conn : incoming_connections_) {
+      auto connection = dynamic_cast<Connection*>(conn);
+      if (!connection) {
+        continue;
+      }
       if (connection->isWorkAvailable()) {
         hasWork = true;
         break;
@@ -279,13 +243,13 @@ bool Processor::isWorkAvailable() {
 // must hold the graphMutex
 void Processor::updateReachability(const std::lock_guard<std::mutex>& graph_lock, bool force) {
   bool didChange = force;
-  for (auto& outIt : out_going_connections_) {
+  for (auto& outIt : outgoing_connections_) {
     for (auto& outConn : outIt.second) {
-      auto connection = std::dynamic_pointer_cast<Connection>(outConn);
+      auto connection = dynamic_cast<Connection*>(outConn);
       if (!connection) {
         continue;
       }
-      auto dest = std::dynamic_pointer_cast<const Processor>(connection->getDestination());
+      auto dest = dynamic_cast<Processor*>(connection->getDestination());
       if (!dest) {
         continue;
       }
@@ -303,12 +267,12 @@ void Processor::updateReachability(const std::lock_guard<std::mutex>& graph_lock
   }
   if (didChange) {
     // propagate the change to sources
-    for (auto& inConn : _incomingConnections) {
-      auto connection = std::dynamic_pointer_cast<Connection>(inConn);
+    for (auto& inConn : incoming_connections_) {
+      auto connection = dynamic_cast<Connection*>(inConn);
       if (!connection) {
         continue;
       }
-      auto source = std::dynamic_pointer_cast<Processor>(connection->getSource());
+      auto source = dynamic_cast<Processor*>(connection->getSource());
       if (!source) {
         continue;
       }
@@ -317,8 +281,8 @@ void Processor::updateReachability(const std::lock_guard<std::mutex>& graph_lock
   }
 }
 
-bool Processor::partOfCycle(const std::shared_ptr<Connection>& conn) {
-  auto source = std::dynamic_pointer_cast<Processor>(conn->getSource());
+bool Processor::partOfCycle(Connection* conn) {
+  auto source = dynamic_cast<Processor*>(conn->getSource());
   if (!source) {
     return false;
   }
@@ -331,9 +295,9 @@ bool Processor::partOfCycle(const std::shared_ptr<Connection>& conn) {
 
 bool Processor::isThrottledByBackpressure() const {
   bool isThrottledByOutgoing = ([&] {
-    for (auto &outIt : out_going_connections_) {
+    for (auto &outIt : outgoing_connections_) {
       for (auto &out : outIt.second) {
-        auto connection = std::dynamic_pointer_cast<Connection>(out);
+        auto connection = dynamic_cast<Connection*>(out);
         if (!connection) {
           continue;
         }
@@ -345,8 +309,8 @@ bool Processor::isThrottledByBackpressure() const {
     return false;
   })();
   bool isForcedByIncomingCycle = ([&] {
-    for (auto &inConn : _incomingConnections) {
-      auto connection = std::dynamic_pointer_cast<Connection>(inConn);
+    for (auto &inConn : incoming_connections_) {
+      auto connection = dynamic_cast<Connection*>(inConn);
       if (!connection) {
         continue;
       }
@@ -359,14 +323,14 @@ bool Processor::isThrottledByBackpressure() const {
   return isThrottledByOutgoing && !isForcedByIncomingCycle;
 }
 
-std::shared_ptr<Connectable> Processor::pickIncomingConnection() {
+Connectable* Processor::pickIncomingConnection() {
   std::lock_guard<std::mutex> rel_guard(relationship_mutex_);
 
   auto beginIt = incoming_connections_Iter;
-  std::shared_ptr<Connectable> inConn;
+  Connectable* inConn;
   do {
     inConn = getNextIncomingConnectionImpl(rel_guard);
-    auto connection = std::dynamic_pointer_cast<Connection>(inConn);
+    auto connection = dynamic_cast<Connection*>(inConn);
     if (!connection) {
       continue;
     }
diff --git a/libminifi/src/core/ProcessorNode.cpp b/libminifi/src/core/ProcessorNode.cpp
index cd0e719..64ece98 100644
--- a/libminifi/src/core/ProcessorNode.cpp
+++ b/libminifi/src/core/ProcessorNode.cpp
@@ -24,7 +24,7 @@ namespace nifi {
 namespace minifi {
 namespace core {
 
-ProcessorNode::ProcessorNode(const std::shared_ptr<Connectable> &processor)
+ProcessorNode::ProcessorNode(Connectable* processor)
     : ConfigurableComponent(),
       Connectable(processor->getName()),
       processor_(processor) {
diff --git a/libminifi/src/core/RepositoryFactory.cpp b/libminifi/src/core/RepositoryFactory.cpp
index 1ce4c66..47ff0bb 100644
--- a/libminifi/src/core/RepositoryFactory.cpp
+++ b/libminifi/src/core/RepositoryFactory.cpp
@@ -35,19 +35,13 @@ namespace nifi {
 namespace minifi {
 namespace core {
 
-std::shared_ptr<core::Repository> createRepository(const std::string configuration_class_name, bool fail_safe, const std::string repo_name) {
+std::unique_ptr<core::Repository> createRepository(const std::string& configuration_class_name, bool fail_safe, const std::string& repo_name) {
   std::string class_name_lc = configuration_class_name;
   std::transform(class_name_lc.begin(), class_name_lc.end(), class_name_lc.begin(), ::tolower);
   try {
-    std::shared_ptr<core::Repository> return_obj = nullptr;
-
-    auto ptr = core::ClassLoader::getDefaultClassLoader().instantiate<core::Repository>(class_name_lc, class_name_lc);
-    if (nullptr != ptr) {
-      ptr->setName(repo_name);
-      return_obj = ptr;
-    }
-
+    auto return_obj = core::ClassLoader::getDefaultClassLoader().instantiate<core::Repository>(class_name_lc, class_name_lc);
     if (return_obj) {
+      return_obj->setName(repo_name);
       return return_obj;
     }
     // if the desired repos don't exist, we can try doing string matches and reoly on volatile repositories
@@ -62,45 +56,40 @@ std::shared_ptr<core::Repository> createRepository(const std::string configurati
       return return_obj;
     }
     if (fail_safe) {
-      return std::make_shared<core::Repository>("fail_safe", "fail_safe", 1ms, 1, 1ms);
+      return std::make_unique<core::Repository>("fail_safe", "fail_safe", 1ms, 1, 1ms);
     } else {
       throw std::runtime_error("Support for the provided configuration class could not be found");
     }
   } catch (const std::runtime_error &) {
     if (fail_safe) {
-      return std::make_shared<core::Repository>("fail_safe", "fail_safe", 1ms, 1, 1ms);
+      return std::make_unique<core::Repository>("fail_safe", "fail_safe", 1ms, 1, 1ms);
     }
   }
 
   throw std::runtime_error("Support for the provided configuration class could not be found");
 }
 
-std::shared_ptr<core::ContentRepository> createContentRepository(const std::string configuration_class_name, bool fail_safe, const std::string repo_name) {
+std::unique_ptr<core::ContentRepository> createContentRepository(const std::string& configuration_class_name, bool fail_safe, const std::string& repo_name) {
   std::string class_name_lc = configuration_class_name;
   std::transform(class_name_lc.begin(), class_name_lc.end(), class_name_lc.begin(), ::tolower);
   try {
-    std::shared_ptr<core::ContentRepository> return_obj = nullptr;
-
-    auto ptr = core::ClassLoader::getDefaultClassLoader().instantiate<core::ContentRepository>(class_name_lc, class_name_lc);
-    if (nullptr != ptr) {
-      return_obj = ptr;
-    }
+    auto return_obj = core::ClassLoader::getDefaultClassLoader().instantiate<core::ContentRepository>(class_name_lc, class_name_lc);
     if (return_obj) {
       return return_obj;
     }
     if (class_name_lc == "volatilecontentrepository") {
-      return std::make_shared<core::repository::VolatileContentRepository>(repo_name);
+      return std::make_unique<core::repository::VolatileContentRepository>(repo_name);
     } else if (class_name_lc == "filesystemrepository") {
-      return std::make_shared<core::repository::FileSystemRepository>(repo_name);
+      return std::make_unique<core::repository::FileSystemRepository>(repo_name);
     }
     if (fail_safe) {
-      return std::make_shared<core::repository::VolatileContentRepository>("fail_safe");
+      return std::make_unique<core::repository::VolatileContentRepository>("fail_safe");
     } else {
       throw std::runtime_error("Support for the provided configuration class could not be found");
     }
   } catch (const std::runtime_error &) {
     if (fail_safe) {
-      return std::make_shared<core::repository::VolatileContentRepository>("fail_safe");
+      return std::make_unique<core::repository::VolatileContentRepository>("fail_safe");
     }
   }
 
diff --git a/libminifi/src/core/controller/StandardControllerServiceNode.cpp b/libminifi/src/core/controller/StandardControllerServiceNode.cpp
index 7ada440..9555245 100644
--- a/libminifi/src/core/controller/StandardControllerServiceNode.cpp
+++ b/libminifi/src/core/controller/StandardControllerServiceNode.cpp
@@ -26,15 +26,6 @@ namespace nifi {
 namespace minifi {
 namespace core {
 namespace controller {
-std::shared_ptr<core::ProcessGroup> &StandardControllerServiceNode::getProcessGroup() {
-  std::lock_guard<std::mutex> lock(mutex_);
-  return process_group_;
-}
-
-void StandardControllerServiceNode::setProcessGroup(std::shared_ptr<ProcessGroup> &processGroup) {
-  std::lock_guard<std::mutex> lock(mutex_);
-  process_group_ = processGroup;
-}
 
 bool StandardControllerServiceNode::enable() {
   Property property("Linked Services", "Referenced Controller Services");
diff --git a/libminifi/src/core/state/ProcessorController.cpp b/libminifi/src/core/state/ProcessorController.cpp
index dcf235a..47a1512 100644
--- a/libminifi/src/core/state/ProcessorController.cpp
+++ b/libminifi/src/core/state/ProcessorController.cpp
@@ -25,7 +25,7 @@ namespace nifi {
 namespace minifi {
 namespace state {
 
-ProcessorController::ProcessorController(const std::shared_ptr<core::Processor> &processor, const std::shared_ptr<SchedulingAgent> &scheduler)
+ProcessorController::ProcessorController(core::Processor* processor, const std::shared_ptr<SchedulingAgent> &scheduler)
     : processor_(processor),
       scheduler_(scheduler) {
 }
diff --git a/libminifi/src/core/yaml/YamlConfiguration.cpp b/libminifi/src/core/yaml/YamlConfiguration.cpp
index 79f6ab2..e08954c 100644
--- a/libminifi/src/core/yaml/YamlConfiguration.cpp
+++ b/libminifi/src/core/yaml/YamlConfiguration.cpp
@@ -144,7 +144,7 @@ std::unique_ptr<core::ProcessGroup> YamlConfiguration::getYamlRoot(const YAML::N
 void YamlConfiguration::parseProcessorNodeYaml(const YAML::Node& processorsNode, core::ProcessGroup* parentGroup) {
   int64_t runDurationNanos = -1;
   utils::Identifier uuid;
-  std::shared_ptr<core::Processor> processor = nullptr;
+  std::unique_ptr<core::Processor> processor;
 
   if (!parentGroup) {
     logger_->log_error("parseProcessNodeYaml: no parent group exists");
@@ -161,7 +161,7 @@ void YamlConfiguration::parseProcessorNodeYaml(const YAML::Node& processorsNode,
   // Evaluate sequence of processors
   for (YAML::const_iterator iter = processorsNode.begin(); iter != processorsNode.end(); ++iter) {
     core::ProcessorConfig procCfg;
-    YAML::Node procNode = iter->as<YAML::Node>();
+    const auto procNode = iter->as<YAML::Node>();
 
     yaml::checkRequiredField(procNode, "name", CONFIG_YAML_PROCESSORS_KEY);
     procCfg.name = procNode["name"].as<std::string>();
@@ -174,7 +174,7 @@ void YamlConfiguration::parseProcessorNodeYaml(const YAML::Node& processorsNode,
     logger_->log_debug("parseProcessorNode: class => [%s]", procCfg.javaClass);
 
     // Determine the processor name only from the Java class
-    auto lastOfIdx = procCfg.javaClass.find_last_of(".");
+    auto lastOfIdx = procCfg.javaClass.find_last_of('.');
     if (lastOfIdx != std::string::npos) {
       lastOfIdx++;  // if a value is found, increment to move beyond the .
       std::string processorName = procCfg.javaClass.substr(lastOfIdx);
@@ -240,7 +240,7 @@ void YamlConfiguration::parseProcessorNodeYaml(const YAML::Node& processorsNode,
     // handle processor properties
     if (procNode["Properties"]) {
       YAML::Node propertiesNode = procNode["Properties"];
-      parsePropertiesNodeYaml(propertiesNode, processor, procCfg.name, CONFIG_YAML_PROCESSORS_KEY);
+      parsePropertiesNodeYaml(propertiesNode, *processor, procCfg.name, CONFIG_YAML_PROCESSORS_KEY);
     }
 
     // Take care of scheduling
@@ -298,7 +298,7 @@ void YamlConfiguration::parseProcessorNodeYaml(const YAML::Node& processorsNode,
 
     processor->setAutoTerminatedRelationships(autoTerminatedRelationships);
 
-    parentGroup->addProcessor(processor);
+    parentGroup->addProcessor(std::move(processor));
   }
 }
 
@@ -437,11 +437,9 @@ void YamlConfiguration::parseProvenanceReportingYaml(const YAML::Node& reportNod
     return;
   }
 
-  std::shared_ptr<core::Processor> processor = nullptr;
-  processor = createProvenanceReportTask();
-  std::shared_ptr<core::reporting::SiteToSiteProvenanceReportingTask> reportTask = std::static_pointer_cast<core::reporting::SiteToSiteProvenanceReportingTask>(processor);
+  auto reportTask = createProvenanceReportTask();
 
-  YAML::Node node = reportNode.as<YAML::Node>();
+  const auto node = reportNode.as<YAML::Node>();
 
   yaml::checkRequiredField(node, "scheduling strategy", CONFIG_YAML_PROVENANCE_REPORT_KEY);
   auto schedulingStrategyStr = node["scheduling strategy"].as<std::string>();
@@ -450,11 +448,11 @@ void YamlConfiguration::parseProvenanceReportingYaml(const YAML::Node& reportNod
 
   if (auto scheduling_period = utils::timeutils::StringToDuration<std::chrono::nanoseconds>(schedulingPeriodStr)) {
     logger_->log_debug("ProvenanceReportingTask schedulingPeriod %" PRId64 " ns", scheduling_period->count());
-    processor->setSchedulingPeriodNano(*scheduling_period);
+    reportTask->setSchedulingPeriodNano(*scheduling_period);
   }
 
   if (schedulingStrategyStr == "TIMER_DRIVEN") {
-    processor->setSchedulingStrategy(core::TIMER_DRIVEN);
+    reportTask->setSchedulingStrategy(core::TIMER_DRIVEN);
     logger_->log_debug("ProvenanceReportingTask scheduling strategy %s", schedulingStrategyStr);
   } else {
     throw std::invalid_argument("Invalid scheduling strategy " + schedulingStrategyStr);
@@ -495,8 +493,8 @@ void YamlConfiguration::parseProvenanceReportingYaml(const YAML::Node& reportNod
   reportTask->initialize();
 
   // add processor to parent
-  parentGroup->addProcessor(processor);
-  processor->setScheduledState(core::RUNNING);
+  reportTask->setScheduledState(core::RUNNING);
+  parentGroup->addProcessor(std::move(reportTask));
 }
 
 void YamlConfiguration::parseControllerServices(const YAML::Node& controllerServicesNode) {
@@ -504,7 +502,7 @@ void YamlConfiguration::parseControllerServices(const YAML::Node& controllerServ
     return;
   }
   for (const auto& iter : controllerServicesNode) {
-    YAML::Node controllerServiceNode = iter.as<YAML::Node>();
+    const auto controllerServiceNode = iter.as<YAML::Node>();
     try {
       yaml::checkRequiredField(controllerServiceNode, "name", CONFIG_YAML_CONTROLLER_SERVICES_KEY);
       yaml::checkRequiredField(controllerServiceNode, "id", CONFIG_YAML_CONTROLLER_SERVICES_KEY);
@@ -513,7 +511,7 @@ void YamlConfiguration::parseControllerServices(const YAML::Node& controllerServ
       logger_->log_debug("Using type %s for controller service node", type);
 
       std::string fullType = type;
-      auto lastOfIdx = type.find_last_of(".");
+      auto lastOfIdx = type.find_last_of('.');
       if (lastOfIdx != std::string::npos) {
         lastOfIdx++;  // if a value is found, increment to move beyond the .
         type = type.substr(lastOfIdx);
@@ -524,17 +522,15 @@ void YamlConfiguration::parseControllerServices(const YAML::Node& controllerServ
 
       utils::Identifier uuid;
       uuid = id;
-      auto controller_service_node = createControllerService(type, fullType, name, uuid);
+      std::shared_ptr<core::controller::ControllerServiceNode> controller_service_node = createControllerService(type, fullType, name, uuid);
       if (nullptr != controller_service_node) {
         logger_->log_debug("Created Controller Service with UUID %s and name %s", id, name);
         controller_service_node->initialize();
         YAML::Node propertiesNode = controllerServiceNode["Properties"];
         // we should propagate properties to the node and to the implementation
-        parsePropertiesNodeYaml(propertiesNode, std::static_pointer_cast<core::ConfigurableComponent>(controller_service_node), name,
-        CONFIG_YAML_CONTROLLER_SERVICES_KEY);
-        if (controller_service_node->getControllerServiceImplementation() != nullptr) {
-          parsePropertiesNodeYaml(propertiesNode, std::static_pointer_cast<core::ConfigurableComponent>(controller_service_node->getControllerServiceImplementation()), name,
-          CONFIG_YAML_CONTROLLER_SERVICES_KEY);
+        parsePropertiesNodeYaml(propertiesNode, *controller_service_node, name, CONFIG_YAML_CONTROLLER_SERVICES_KEY);
+        if (auto controllerServiceImpl = controller_service_node->getControllerServiceImplementation(); controllerServiceImpl) {
+          parsePropertiesNodeYaml(propertiesNode, *controllerServiceImpl, name, CONFIG_YAML_CONTROLLER_SERVICES_KEY);
         }
       } else {
         logger_->log_debug("Could not locate %s", type);
@@ -557,25 +553,24 @@ void YamlConfiguration::parseConnectionYaml(const YAML::Node& connectionsNode, c
   }
 
   for (YAML::const_iterator iter = connectionsNode.begin(); iter != connectionsNode.end(); ++iter) {
-    YAML::Node connectionNode = iter->as<YAML::Node>();
-    std::shared_ptr<minifi::Connection> connection = nullptr;
+    const auto connectionNode = iter->as<YAML::Node>();
 
     // Configure basic connection
-    std::string id = getOrGenerateId(connectionNode);
+    const std::string id = getOrGenerateId(connectionNode);
 
     // Default name to be same as ID
     // If name is specified in configuration, use the value
-    std::string name = connectionNode["name"].as<std::string>(id);
+    const auto name = connectionNode["name"].as<std::string>(id);
 
     const auto uuid = utils::Identifier::parse(id) | utils::orElse([this] {
       logger_->log_debug("Incorrect connection UUID format.");
       throw Exception(ExceptionType::GENERAL_EXCEPTION, "Incorrect connection UUID format.");
     });
 
-    connection = createConnection(name, uuid.value());
+    auto connection = createConnection(name, uuid.value());
     logger_->log_debug("Created connection with UUID %s and name %s", id, name);
     const yaml::YamlConnectionParser connectionParser(connectionNode, name, gsl::not_null<core::ProcessGroup*>{ parent }, logger_);
-    connectionParser.configureConnectionSourceRelationshipsFromYaml(connection);
+    connectionParser.configureConnectionSourceRelationshipsFromYaml(*connection);
     connection->setMaxQueueSize(connectionParser.getWorkQueueSizeFromYaml());
     connection->setMaxQueueDataSize(connectionParser.getWorkQueueDataSizeFromYaml());
     connection->setSourceUUID(connectionParser.getSourceUUIDFromYaml());
@@ -583,21 +578,19 @@ void YamlConfiguration::parseConnectionYaml(const YAML::Node& connectionsNode, c
     connection->setFlowExpirationDuration(connectionParser.getFlowFileExpirationFromYaml());
     connection->setDropEmptyFlowFiles(connectionParser.getDropEmptyFromYaml());
 
-    parent->addConnection(connection);
+    parent->addConnection(std::move(connection));
   }
 }
 
 void YamlConfiguration::parsePortYaml(const YAML::Node& portNode, core::ProcessGroup* parent, sitetosite::TransferDirection direction) {
   utils::Identifier uuid;
-  std::shared_ptr<core::Processor> processor = NULL;
-  std::shared_ptr<minifi::RemoteProcessorGroupPort> port = NULL;
 
   if (!parent) {
     logger_->log_error("parseProcessNode: no parent group existed");
     return;
   }
 
-  YAML::Node inputPortsObj = portNode.as<YAML::Node>();
+  const auto inputPortsObj = portNode.as<YAML::Node>();
 
   // Check for required fields
   yaml::checkRequiredField(inputPortsObj, "name", CONFIG_YAML_REMOTE_PROCESS_GROUP_KEY);
@@ -611,14 +604,13 @@ void YamlConfiguration::parsePortYaml(const YAML::Node& portNode, core::ProcessG
   auto portId = inputPortsObj["id"].as<std::string>();
   uuid = portId;
 
-  port = std::make_shared<minifi::RemoteProcessorGroupPort>(stream_factory_, nameStr, parent->getURL(), this->configuration_, uuid);
-
-  processor = std::static_pointer_cast<core::Processor>(port);
+  auto port = std::make_unique<minifi::RemoteProcessorGroupPort>(
+          stream_factory_, nameStr, parent->getURL(), this->configuration_, uuid);
   port->setDirection(direction);
   port->setTimeout(parent->getTimeout());
   port->setTransmitting(true);
-  processor->setYieldPeriodMsec(parent->getYieldPeriodMsec());
-  processor->initialize();
+  port->setYieldPeriodMsec(parent->getYieldPeriodMsec());
+  port->initialize();
   if (!parent->getInterface().empty())
     port->setInterface(parent->getInterface());
   if (parent->getTransportProtocol() == "HTTP") {
@@ -629,39 +621,39 @@ void YamlConfiguration::parsePortYaml(const YAML::Node& portNode, core::ProcessG
   // else defaults to RAW
 
   // handle port properties
-  YAML::Node nodeVal = portNode.as<YAML::Node>();
+  const auto nodeVal = portNode.as<YAML::Node>();
   YAML::Node propertiesNode = nodeVal["Properties"];
-  parsePropertiesNodeYaml(propertiesNode, std::static_pointer_cast<core::ConfigurableComponent>(processor), nameStr,
-  CONFIG_YAML_REMOTE_PROCESS_GROUP_KEY);
+  parsePropertiesNodeYaml(propertiesNode, *port, nameStr, CONFIG_YAML_REMOTE_PROCESS_GROUP_KEY);
 
   // add processor to parent
-  parent->addProcessor(processor);
-  processor->setScheduledState(core::RUNNING);
+  auto& processor = *port;
+  parent->addProcessor(std::move(port));
+  processor.setScheduledState(core::RUNNING);
 
   if (inputPortsObj["max concurrent tasks"]) {
     auto rawMaxConcurrentTasks = inputPortsObj["max concurrent tasks"].as<std::string>();
     int32_t maxConcurrentTasks;
     if (core::Property::StringToInt(rawMaxConcurrentTasks, maxConcurrentTasks)) {
-      processor->setMaxConcurrentTasks(maxConcurrentTasks);
+      processor.setMaxConcurrentTasks(maxConcurrentTasks);
     }
     logger_->log_debug("parseProcessorNode: maxConcurrentTasks => [%d]", maxConcurrentTasks);
-    processor->setMaxConcurrentTasks(maxConcurrentTasks);
+    processor.setMaxConcurrentTasks(maxConcurrentTasks);
   }
 }
 
-void YamlConfiguration::parsePropertyValueSequence(const std::string& propertyName, const YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor) {
+void YamlConfiguration::parsePropertyValueSequence(const std::string& propertyName, const YAML::Node& propertyValueNode, core::ConfigurableComponent& component) {
   for (const auto& iter : propertyValueNode) {
     if (iter.IsDefined()) {
-      YAML::Node nodeVal = iter.as<YAML::Node>();
+      const auto nodeVal = iter.as<YAML::Node>();
       YAML::Node propertiesNode = nodeVal["value"];
       // must insert the sequence in differently.
-      std::string rawValueString = propertiesNode.as<std::string>();
+      const auto rawValueString = propertiesNode.as<std::string>();
       logger_->log_debug("Found %s=%s", propertyName, rawValueString);
-      if (!processor->updateProperty(propertyName, rawValueString)) {
-        std::shared_ptr<core::Connectable> proc = std::dynamic_pointer_cast<core::Connectable>(processor);
+      if (!component.updateProperty(propertyName, rawValueString)) {
+        auto proc = dynamic_cast<core::Connectable*>(&component);
         if (proc) {
           logger_->log_warn("Received property %s with value %s but is not one of the properties for %s. Attempting to add as dynamic property.", propertyName, rawValueString, proc->getName());
-          if (!processor->setDynamicProperty(propertyName, rawValueString)) {
+          if (!component.setDynamicProperty(propertyName, rawValueString)) {
             logger_->log_warn("Unable to set the dynamic property %s with value %s", propertyName, rawValueString);
           } else {
             logger_->log_warn("Dynamic property %s with value %s set", propertyName, rawValueString);
@@ -697,9 +689,10 @@ PropertyValue YamlConfiguration::getValidatedProcessorPropertyForDefaultTypeInfo
     if (defaultType == typeid(int64_t)) {
       coercedValue = propertyValueNode.as<int64_t>();
     } else if (defaultType == typeid(uint64_t)) {
-      try {
-        coercedValue = propertyValueNode.as<uint64_t>();
-      } catch (...) {
+      uint64_t integer_value;
+      if (YAML::convert<uint64_t>::decode(propertyValueNode, integer_value)) {
+        coercedValue = integer_value;
+      } else {
         coercedValue = propertyValueNode.as<std::string>();
       }
     } else if (defaultType == typeid(int)) {
@@ -719,24 +712,28 @@ PropertyValue YamlConfiguration::getValidatedProcessorPropertyForDefaultTypeInfo
   return defaultValue;
 }
 
-void YamlConfiguration::parseSingleProperty(const std::string& propertyName, const YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor) {
+void YamlConfiguration::parseSingleProperty(const std::string& propertyName, const YAML::Node& propertyValueNode, core::ConfigurableComponent& processor) {
   core::Property myProp(propertyName, "", "");
-  processor->getProperty(propertyName, myProp);
+  processor.getProperty(propertyName, myProp);
   const PropertyValue coercedValue = getValidatedProcessorPropertyForDefaultTypeInfo(myProp, propertyValueNode);
   bool property_set = false;
   try {
-    property_set = processor->setProperty(myProp, coercedValue);
+    property_set = processor.setProperty(myProp, coercedValue);
   } catch(const utils::internal::InvalidValueException&) {
-    auto component = std::dynamic_pointer_cast<core::CoreComponent>(processor);
-    logger_->log_error("Invalid value was set for property '%s' creating component '%s'", propertyName, component->getName());
+    auto component = dynamic_cast<core::CoreComponent*>(&processor);
+    if (component == nullptr) {
+      logger_->log_error("processor was not a CoreComponent for property '%s'", propertyName);
+    } else {
+      logger_->log_error("Invalid value was set for property '%s' creating component '%s'", propertyName, component->getName());
+    }
     throw;
   }
-  const std::string rawValueString = propertyValueNode.as<std::string>();
+  const auto rawValueString = propertyValueNode.as<std::string>();
   if (!property_set) {
-    std::shared_ptr<core::Connectable> proc = std::dynamic_pointer_cast<core::Connectable>(processor);
+    auto proc = dynamic_cast<core::Connectable*>(&processor);
     if (proc) {
       logger_->log_warn("Received property %s with value %s but is not one of the properties for %s. Attempting to add as dynamic property.", propertyName, rawValueString, proc->getName());
-      if (!processor->setDynamicProperty(propertyName, rawValueString)) {
+      if (!processor.setDynamicProperty(propertyName, rawValueString)) {
         logger_->log_warn("Unable to set the dynamic property %s with value %s", propertyName, rawValueString);
       } else {
         logger_->log_warn("Dynamic property %s with value %s set", propertyName, rawValueString);
@@ -747,7 +744,7 @@ void YamlConfiguration::parseSingleProperty(const std::string& propertyName, con
   }
 }
 
-void YamlConfiguration::parsePropertyNodeElement(const std::string& propertyName, const YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor) {
+void YamlConfiguration::parsePropertyNodeElement(const std::string& propertyName, const YAML::Node& propertyValueNode, core::ConfigurableComponent& processor) {
   logger_->log_trace("Encountered %s", propertyName);
   if (propertyValueNode.IsNull() || !propertyValueNode.IsDefined()) {
     return;
@@ -759,17 +756,17 @@ void YamlConfiguration::parsePropertyNodeElement(const std::string& propertyName
   }
 }
 
-void YamlConfiguration::parsePropertiesNodeYaml(const YAML::Node& propertiesNode, std::shared_ptr<core::ConfigurableComponent> processor, const std::string& component_name,
+void YamlConfiguration::parsePropertiesNodeYaml(const YAML::Node& propertiesNode, core::ConfigurableComponent& component, const std::string& component_name,
     const std::string& yaml_section) {
   // Treat generically as a YAML node so we can perform inspection on entries to ensure they are populated
   logger_->log_trace("Entered %s", component_name);
   for (const auto& propertyElem : propertiesNode) {
-    const std::string propertyName = propertyElem.first.as<std::string>();
+    const auto propertyName = propertyElem.first.as<std::string>();
     const YAML::Node propertyValueNode = propertyElem.second;
-    parsePropertyNodeElement(propertyName, propertyValueNode, processor);
+    parsePropertyNodeElement(propertyName, propertyValueNode, component);
   }
 
-  validateComponentProperties(processor, component_name, yaml_section);
+  validateComponentProperties(component, component_name, yaml_section);
 }
 
 void YamlConfiguration::parseFunnelsYaml(const YAML::Node& node, core::ProcessGroup* parent) {
@@ -782,28 +779,28 @@ void YamlConfiguration::parseFunnelsYaml(const YAML::Node& node, core::ProcessGr
   }
 
   for (const auto& element : node) {
-    YAML::Node funnel_node = element.as<YAML::Node>();
+    const auto funnel_node = element.as<YAML::Node>();
 
     std::string id = getOrGenerateId(funnel_node);
 
     // Default name to be same as ID
-    std::string name = funnel_node["name"].as<std::string>(id);
+    const auto name = funnel_node["name"].as<std::string>(id);
 
     const auto uuid = utils::Identifier::parse(id) | utils::orElse([this] {
       logger_->log_debug("Incorrect funnel UUID format.");
       throw Exception(ExceptionType::GENERAL_EXCEPTION, "Incorrect funnel UUID format.");
     });
 
-    std::shared_ptr<core::Processor> funnel = std::make_shared<core::Funnel>(name, uuid.value());
+    auto funnel = std::make_unique<core::Funnel>(name, uuid.value());
     logger_->log_debug("Created funnel with UUID %s and name %s", id, name);
     funnel->setScheduledState(core::RUNNING);
     funnel->setSchedulingStrategy(core::EVENT_DRIVEN);
-    parent->addProcessor(funnel);
+    parent->addProcessor(std::move(funnel));
   }
 }
 
-void YamlConfiguration::validateComponentProperties(const std::shared_ptr<ConfigurableComponent> &component, const std::string &component_name, const std::string &yaml_section) const {
-  const auto &component_properties = component->getProperties();
+void YamlConfiguration::validateComponentProperties(ConfigurableComponent& component, const std::string &component_name, const std::string &yaml_section) const {
+  const auto &component_properties = component.getProperties();
 
   // Validate required properties
   for (const auto &prop_pair : component_properties) {
diff --git a/libminifi/src/core/yaml/YamlConnectionParser.cpp b/libminifi/src/core/yaml/YamlConnectionParser.cpp
index bfb1041..3ffbaf7 100644
--- a/libminifi/src/core/yaml/YamlConnectionParser.cpp
+++ b/libminifi/src/core/yaml/YamlConnectionParser.cpp
@@ -29,13 +29,13 @@ namespace yaml {
 // This is no longer needed in c++17
 constexpr const char* YamlConnectionParser::CONFIG_YAML_CONNECTIONS_KEY;
 
-void YamlConnectionParser::addNewRelationshipToConnection(const std::string& relationship_name, const std::shared_ptr<minifi::Connection>& connection) const {
+void YamlConnectionParser::addNewRelationshipToConnection(const std::string& relationship_name, minifi::Connection& connection) const {
   core::Relationship relationship(relationship_name, "");
   logger_->log_debug("parseConnection: relationship => [%s]", relationship_name);
-  connection->addRelationship(std::move(relationship));
+  connection.addRelationship(std::move(relationship));
 }
 
-void YamlConnectionParser::addFunnelRelationshipToConnection(const std::shared_ptr<minifi::Connection>& connection) const {
+void YamlConnectionParser::addFunnelRelationshipToConnection(minifi::Connection& connection) const {
   utils::Identifier srcUUID;
   try {
     srcUUID = getSourceUUIDFromYaml();
@@ -48,13 +48,13 @@ void YamlConnectionParser::addFunnelRelationshipToConnection(const std::shared_p
     return;
   }
 
-  auto& processor_ref = *processor.get();
+  auto& processor_ref = *processor;
   if (typeid(minifi::core::Funnel) == typeid(processor_ref)) {
     addNewRelationshipToConnection(minifi::core::Funnel::Success.getName(), connection);
   }
 }
 
-void YamlConnectionParser::configureConnectionSourceRelationshipsFromYaml(const std::shared_ptr<minifi::Connection>& connection) const {
+void YamlConnectionParser::configureConnectionSourceRelationshipsFromYaml(minifi::Connection& connection) const {
   // Configure connection source
   if (connectionNode_.as<YAML::Node>()["source relationship name"] && !connectionNode_["source relationship name"].as<std::string>().empty()) {
     addNewRelationshipToConnection(connectionNode_["source relationship name"].as<std::string>(), connection);
diff --git a/libminifi/test/SingleInputTestController.h b/libminifi/test/SingleInputTestController.h
index 773ad9d..98380c1 100644
--- a/libminifi/test/SingleInputTestController.h
+++ b/libminifi/test/SingleInputTestController.h
@@ -24,6 +24,7 @@
 #include <utility>
 #include <vector>
 #include "TestBase.h"
+#include "FlowFileRecord.h"
 #include "core/Processor.h"
 
 namespace org::apache::nifi::minifi::test {
@@ -86,14 +87,14 @@ class SingleInputTestController : public TestController {
 
  private:
   std::shared_ptr<core::Processor> processor_;
-  std::unordered_map<core::Relationship, std::shared_ptr<Connection>> outgoing_connections_{[this] {
-    std::unordered_map<core::Relationship, std::shared_ptr<Connection>> result;
+  std::unordered_map<core::Relationship, Connection*> outgoing_connections_{[this] {
+    std::unordered_map<core::Relationship, Connection*> result;
     for (const auto& relationship: processor_->getSupportedRelationships()) {
       result.insert_or_assign(relationship, plan->addConnection(processor_, relationship, nullptr));
     }
     return result;
   }()};
-  std::shared_ptr<Connection> input_ = plan->addConnection(nullptr, core::Relationship{"success", "success"}, processor_);
+  Connection* input_ = plan->addConnection(nullptr, core::Relationship{"success", "success"}, processor_);
 };
 
 }  // namespace org::apache::nifi::minifi::test
diff --git a/libminifi/test/StatefulProcessor.cpp b/libminifi/test/StatefulProcessor.cpp
index 70dd0ea..4253718 100644
--- a/libminifi/test/StatefulProcessor.cpp
+++ b/libminifi/test/StatefulProcessor.cpp
@@ -21,6 +21,7 @@
 #include "StatefulProcessor.h"
 #include "Exception.h"
 #include "core/Resource.h"
+#include "core/ProcessContext.h"
 
 namespace org {
 namespace apache {
diff --git a/libminifi/test/StatefulProcessor.h b/libminifi/test/StatefulProcessor.h
index 63513f9..b5639bd 100644
--- a/libminifi/test/StatefulProcessor.h
+++ b/libminifi/test/StatefulProcessor.h
@@ -22,6 +22,7 @@
 #include <utility>
 #include <vector>
 #include "core/Processor.h"
+#include "core/CoreComponentState.h"
 
 namespace org {
 namespace apache {
@@ -45,7 +46,7 @@ class StatefulProcessor : public core::Processor {
 
  private:
   mutable std::mutex mutex_;
-  std::shared_ptr<core::CoreComponentStateManager> state_manager_;
+  core::CoreComponentStateManager* state_manager_;
   HookType on_schedule_hook_;
   std::vector<HookType> on_trigger_hooks_;
   size_t on_trigger_hook_index_ = 0;
diff --git a/libminifi/test/TestBase.cpp b/libminifi/test/TestBase.cpp
index dc6daf7..620a694 100644
--- a/libminifi/test/TestBase.cpp
+++ b/libminifi/test/TestBase.cpp
@@ -240,28 +240,27 @@ std::shared_ptr<minifi::core::Processor> TestPlan::addProcessor(const std::share
     }
     std::stringstream connection_name;
     connection_name << last->getUUIDStr() << "-to-" << processor->getUUIDStr();
-    std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
+    auto connection = std::make_unique<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
     logger_->log_info("Creating %s connection for proc %d", connection_name.str(), processor_queue_.size() + 1);
 
     for (const auto& relationship : relationships) {
       connection->addRelationship(relationship);
     }
     // link the connections so that we can test results at the end for this
-    connection->setSource(last);
-    connection->setDestination(processor);
+    connection->setSource(last.get());
+    connection->setDestination(processor.get());
 
     connection->setSourceUUID(last->getUUID());
     connection->setDestinationUUID(processor->getUUID());
-    last->addConnection(connection);
+    last->addConnection(connection.get());
     if (last != processor) {
-      processor->addConnection(connection);
+      processor->addConnection(connection.get());
     }
-    relationships_.push_back(connection);
+    relationships_.push_back(std::move(connection));
   }
-  std::shared_ptr<minifi::core::ProcessorNode> node = std::make_shared<minifi::core::ProcessorNode>(processor);
+  std::shared_ptr<minifi::core::ProcessorNode> node = std::make_shared<minifi::core::ProcessorNode>(processor.get());
   processor_nodes_.push_back(node);
-  // std::shared_ptr<core::ProcessContext> context = std::make_shared<core::ProcessContext>(node, controller_services_provider_, prov_repo_, flow_repo_, configuration_, content_repo_);
-  auto contextBuilder = minifi::core::ClassLoader::getDefaultClassLoader().instantiate<minifi::core::ProcessContextBuilder>("ProcessContextBuilder", "ProcessContextBuilder");
+  std::shared_ptr<minifi::core::ProcessContextBuilder> contextBuilder = minifi::core::ClassLoader::getDefaultClassLoader().instantiate<minifi::core::ProcessContextBuilder>("ProcessContextBuilder", "ProcessContextBuilder");
   contextBuilder = contextBuilder->withContentRepository(content_repo_)->withFlowFileRepository(flow_repo_)->withProvider(controller_services_provider_.get())->withProvenanceRepository(prov_repo_)->withConfiguration(configuration_);
   auto context = contextBuilder->build(node);
   processor_contexts_.push_back(context);
@@ -276,7 +275,7 @@ std::shared_ptr<minifi::core::Processor> TestPlan::addProcessor(const std::strin
   }
   std::lock_guard<std::recursive_mutex> guard(mutex);
 
-  auto ptr = minifi::core::ClassLoader::getDefaultClassLoader().instantiate(processor_name, uuid);
+  std::shared_ptr<core::CoreComponent> ptr = minifi::core::ClassLoader::getDefaultClassLoader().instantiate(processor_name, uuid);
   if (nullptr == ptr) {
     throw std::runtime_error{fmt::format("Failed to instantiate processor name: {0} uuid: {1}", processor_name, uuid.to_string().c_str())};
   }
@@ -296,34 +295,36 @@ std::shared_ptr<minifi::core::Processor> TestPlan::addProcessor(const std::strin
   return addProcessor(processor_name, minifi::utils::IdGenerator::getIdGenerator()->generate(), name, relationships, linkToPrevious);
 }
 
-std::shared_ptr<minifi::Connection> TestPlan::addConnection(const std::shared_ptr<minifi::core::Processor>& source_proc, const minifi::core::Relationship& source_relationship, const std::shared_ptr<minifi::core::Processor>& destination_proc) {
+minifi::Connection* TestPlan::addConnection(const std::shared_ptr<minifi::core::Processor>& source_proc, const minifi::core::Relationship& source_relationship, const std::shared_ptr<minifi::core::Processor>& destination_proc) {
   std::stringstream connection_name;
   connection_name
     << (source_proc ? source_proc->getUUIDStr().c_str() : "none")
     << "-to-"
     << (destination_proc ? destination_proc->getUUIDStr().c_str() : "none");
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
+  auto connection = std::make_unique<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
 
   connection->addRelationship(source_relationship);
 
   // link the connections so that we can test results at the end for this
 
   if (source_proc) {
-    connection->setSource(source_proc);
+    connection->setSource(source_proc.get());
     connection->setSourceUUID(source_proc->getUUID());
   }
   if (destination_proc) {
-    connection->setDestination(destination_proc);
+    connection->setDestination(destination_proc.get());
     connection->setDestinationUUID(destination_proc->getUUID());
   }
   if (source_proc) {
-    source_proc->addConnection(connection);
+    source_proc->addConnection(connection.get());
   }
   if (source_proc != destination_proc && destination_proc) {
-    destination_proc->addConnection(connection);
+    destination_proc->addConnection(connection.get());
   }
-  relationships_.push_back(connection);
-  return connection;
+
+  auto retVal = connection.get();
+  relationships_.push_back(std::move(connection));
+  return retVal;
 }
 
 std::shared_ptr<minifi::core::controller::ControllerServiceNode> TestPlan::addController(const std::string &controller_name, const std::string &name) {
@@ -535,7 +536,7 @@ std::shared_ptr<minifi::core::FlowFile> TestPlan::getCurrentFlowFile() {
 }
 
 std::vector<minifi::Connection*> TestPlan::getProcessorOutboundConnections(const std::shared_ptr<minifi::core::Processor>& processor) {
-  const auto is_processor_outbound_connection = [&processor] (const std::shared_ptr<minifi::Connection>& connection) {
+  const auto is_processor_outbound_connection = [&processor] (const std::unique_ptr<minifi::Connection>& connection) {
     // A connection is outbound from a processor if its source uuid matches the processor
     return connection->getSource()->getUUIDStr() == processor->getUUIDStr();
   };
@@ -553,29 +554,29 @@ std::shared_ptr<minifi::core::ProcessContext> TestPlan::getCurrentContext() {
   return processor_contexts_.at(location);
 }
 
-std::shared_ptr<minifi::Connection> TestPlan::buildFinalConnection(const std::shared_ptr<minifi::core::Processor>& processor, bool setDest) {
+std::unique_ptr<minifi::Connection> TestPlan::buildFinalConnection(const std::shared_ptr<minifi::core::Processor>& processor, bool setDest) {
   std::stringstream connection_name;
   connection_name << processor->getUUIDStr() << "-to-" << processor->getUUIDStr();
-  auto connection = std::make_shared<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
+  auto connection = std::make_unique<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
   connection->addRelationship(termination_);
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(processor);
+  connection->setSource(processor.get());
   if (setDest)
-    connection->setDestination(processor);
+    connection->setDestination(processor.get());
 
   minifi::utils::Identifier uuid_copy = processor->getUUID();
   connection->setSourceUUID(uuid_copy);
   if (setDest)
     connection->setDestinationUUID(uuid_copy);
 
-  processor->addConnection(connection);
+  processor->addConnection(connection.get());
   return connection;
 }
 
 void TestPlan::finalize() {
   std::lock_guard<std::recursive_mutex> guard(mutex);
-  if (relationships_.size() > 0) {
+  if (!relationships_.empty()) {
     relationships_.push_back(buildFinalConnection(processor_queue_.back()));
   } else {
     for (const auto& processor : processor_queue_) {
diff --git a/libminifi/test/TestBase.h b/libminifi/test/TestBase.h
index 664cd15..7363775 100644
--- a/libminifi/test/TestBase.h
+++ b/libminifi/test/TestBase.h
@@ -213,7 +213,7 @@ class TestPlan {
   std::shared_ptr<minifi::core::Processor> addProcessor(const std::string &processor_name, const std::string &name, const std::initializer_list<minifi::core::Relationship>& relationships, bool linkToPrevious = false); // NOLINT
   std::shared_ptr<minifi::core::Processor> addProcessor(const std::string &processor_name, const minifi::utils::Identifier& uuid, const std::string &name, const std::initializer_list<minifi::core::Relationship>& relationships, bool linkToPrevious = false); // NOLINT
 
-  std::shared_ptr<minifi::Connection> addConnection(const std::shared_ptr<minifi::core::Processor>& source_proc, const minifi::core::Relationship& source_relationship, const std::shared_ptr<minifi::core::Processor>& destination_proc); // NOLINT
+  minifi::Connection* addConnection(const std::shared_ptr<minifi::core::Processor>& source_proc, const minifi::core::Relationship& source_relationship, const std::shared_ptr<minifi::core::Processor>& destination_proc); // NOLINT
 
   std::shared_ptr<minifi::core::controller::ControllerServiceNode> addController(const std::string &controller_name, const std::string &name);
 
@@ -286,7 +286,7 @@ class TestPlan {
  protected:
   std::unique_ptr<TempDirectory> state_dir_;
 
-  std::shared_ptr<minifi::Connection> buildFinalConnection(const std::shared_ptr<minifi::core::Processor>& processor, bool setDest = false);
+  std::unique_ptr<minifi::Connection> buildFinalConnection(const std::shared_ptr<minifi::core::Processor>& processor, bool setDest = false);
 
   std::shared_ptr<minifi::io::StreamFactory> stream_factory;
 
@@ -319,7 +319,7 @@ class TestPlan {
   std::vector<std::shared_ptr<minifi::core::ProcessContext>> processor_contexts_;
   std::vector<std::shared_ptr<minifi::core::ProcessSession>> process_sessions_;
   std::vector<std::shared_ptr<minifi::core::ProcessSessionFactory>> factories_;  // Do not assume ordering
-  std::vector<std::shared_ptr<minifi::Connection>> relationships_;
+  std::vector<std::unique_ptr<minifi::Connection>> relationships_;
   minifi::core::Relationship termination_;
 
  private:
diff --git a/libminifi/test/archive-tests/CompressContentTests.cpp b/libminifi/test/archive-tests/CompressContentTests.cpp
index da1741a..bd19577 100644
--- a/libminifi/test/archive-tests/CompressContentTests.cpp
+++ b/libminifi/test/archive-tests/CompressContentTests.cpp
@@ -126,21 +126,21 @@ class CompressDecompressionTestController : public TestController{
     // connection from compress processor to log attribute
     output = std::make_shared<minifi::Connection>(repo, content_repo, "Output");
     output->addRelationship(core::Relationship("success", "compress successful output"));
-    output->setSource(processor);
+    output->setSource(processor.get());
     output->setSourceUUID(processoruuid);
-    processor->addConnection(output);
+    processor->addConnection(output.get());
     // connection to compress processor
     input = std::make_shared<minifi::Connection>(repo, content_repo, "Input");
-    input->setDestination(processor);
+    input->setDestination(processor.get());
     input->setDestinationUUID(processoruuid);
-    processor->addConnection(input);
+    processor->addConnection(input.get());
 
     processor->setAutoTerminatedRelationships({{"failure", ""}});
 
     processor->incrementActiveTasks();
     processor->setScheduledState(core::ScheduledState::RUNNING);
 
-    context = std::make_shared<core::ProcessContext>(std::make_shared<core::ProcessorNode>(processor), nullptr, repo, repo, content_repo);
+    context = std::make_shared<core::ProcessContext>(std::make_shared<core::ProcessorNode>(processor.get()), nullptr, repo, repo, content_repo);
   }
 
  public:
diff --git a/libminifi/test/archive-tests/MergeFileTests.cpp b/libminifi/test/archive-tests/MergeFileTests.cpp
index bfd920b..932ec04 100644
--- a/libminifi/test/archive-tests/MergeFileTests.cpp
+++ b/libminifi/test/archive-tests/MergeFileTests.cpp
@@ -155,67 +155,69 @@ class MergeTestController : public TestController {
     auto content_repo = std::make_shared<core::repository::VolatileContentRepository>();
     content_repo->initialize(std::make_shared<minifi::Configure>());
 
-    processor = std::make_shared<minifi::processors::MergeContent>("mergecontent");
-    processor->initialize();
-    utils::Identifier processoruuid = processor->getUUID();
+    merge_content_processor_ = std::make_unique<minifi::processors::MergeContent>("mergecontent");
+    merge_content_processor_->initialize();
+    utils::Identifier processoruuid = merge_content_processor_->getUUID();
     REQUIRE(processoruuid);
-    std::shared_ptr<core::Processor> logAttributeProcessor = std::make_shared<minifi::processors::LogAttribute>("logattribute");
-    utils::Identifier logAttributeuuid = logAttributeProcessor->getUUID();
+    log_attribute_processor_ = std::make_unique<minifi::processors::LogAttribute>("logattribute");
+    utils::Identifier logAttributeuuid = log_attribute_processor_->getUUID();
     REQUIRE(logAttributeuuid);
 
     // output from merge processor to log attribute
-    output = std::make_shared<minifi::Connection>(repo, content_repo, "logattributeconnection");
-    output->addRelationship(minifi::processors::MergeContent::Merge);
-    output->setSource(processor);
-    output->setDestination(logAttributeProcessor);
-    output->setSourceUUID(processoruuid);
-    output->setDestinationUUID(logAttributeuuid);
-    processor->addConnection(output);
+    output_ = std::make_unique<minifi::Connection>(repo, content_repo, "logattributeconnection");
+    output_->addRelationship(minifi::processors::MergeContent::Merge);
+    output_->setSource(merge_content_processor_.get());
+    output_->setDestination(log_attribute_processor_.get());
+    output_->setSourceUUID(processoruuid);
+    output_->setDestinationUUID(logAttributeuuid);
+    merge_content_processor_->addConnection(output_.get());
     // input to merge processor
-    input = std::make_shared<minifi::Connection>(repo, content_repo, "mergeinput");
-    input->setDestination(processor);
-    input->setDestinationUUID(processoruuid);
-    processor->addConnection(input);
+    input_ = std::make_unique<minifi::Connection>(repo, content_repo, "mergeinput");
+    input_->setDestination(merge_content_processor_.get());
+    input_->setDestinationUUID(processoruuid);
+    merge_content_processor_->addConnection(input_.get());
 
-    processor->setAutoTerminatedRelationships({minifi::processors::MergeContent::Original, minifi::processors::MergeContent::Failure});
+    merge_content_processor_->setAutoTerminatedRelationships({minifi::processors::MergeContent::Original, minifi::processors::MergeContent::Failure});
 
-    processor->incrementActiveTasks();
-    processor->setScheduledState(core::ScheduledState::RUNNING);
-    logAttributeProcessor->incrementActiveTasks();
-    logAttributeProcessor->setScheduledState(core::ScheduledState::RUNNING);
+    merge_content_processor_->incrementActiveTasks();
+    merge_content_processor_->setScheduledState(core::ScheduledState::RUNNING);
+    log_attribute_processor_->incrementActiveTasks();
+    log_attribute_processor_->setScheduledState(core::ScheduledState::RUNNING);
 
-    context = std::make_shared<core::ProcessContext>(std::make_shared<core::ProcessorNode>(processor), nullptr, repo, repo, content_repo);
+    context_ = std::make_shared<core::ProcessContext>(std::make_shared<core::ProcessorNode>(merge_content_processor_.get()), nullptr, repo, repo, content_repo);
 
     for (size_t i = 0; i < 6; ++i) {
-      flowFileContents[i] = utils::StringUtils::repeat(std::to_string(i), 32);
+      flowFileContents_[i] = utils::StringUtils::repeat(std::to_string(i), 32);
     }
   }
+
   ~MergeTestController() {
     LogTestController::getInstance().reset();
   }
 
-  std::string flowFileContents[6];
-  std::shared_ptr<core::ProcessContext> context;
-  std::shared_ptr<core::Processor> processor;
-  std::shared_ptr<minifi::Connection> input;
-  std::shared_ptr<minifi::Connection> output;
+  std::string flowFileContents_[6];
+  std::shared_ptr<core::ProcessContext> context_;
+  std::unique_ptr<core::Processor> merge_content_processor_;
+  std::unique_ptr<core::Processor> log_attribute_processor_;
+  std::unique_ptr<minifi::Connection> input_;
+  std::unique_ptr<minifi::Connection> output_;
 };
 
 TEST_CASE_METHOD(MergeTestController, "MergeFileDefragment", "[mergefiletest1]") {
   std::string expected[2]{
-    flowFileContents[0] + flowFileContents[1] + flowFileContents[2],
-    flowFileContents[3] + flowFileContents[4] + flowFileContents[5]
+          flowFileContents_[0] + flowFileContents_[1] + flowFileContents_[2],
+          flowFileContents_[3] + flowFileContents_[4] + flowFileContents_[5]
   };
 
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 6 flowfiles, first three merged to one, second three merged to one
   for (const int i : {0, 2, 5, 4, 1, 3}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     // three bundle
     if (i < 3)
       flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_ID_ATTRIBUTE, std::to_string(0));
@@ -227,20 +229,20 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileDefragment", "[mergefiletest1]")
       flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_INDEX_ATTRIBUTE, std::to_string(i-3));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_COUNT_ATTRIBUTE, std::to_string(3));
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 6; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   REQUIRE(flow1->getSize() == 96);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
@@ -257,26 +259,26 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileDefragment", "[mergefiletest1]")
 
 TEST_CASE_METHOD(MergeTestController, "MergeFileDefragmentDelimiter", "[mergefiletest2]") {
   std::string expected[2]{
-    "header" + flowFileContents[0] + "demarcator" + flowFileContents[1] + "demarcator" + flowFileContents[2] + "footer",
-    "header" + flowFileContents[3] + "demarcator" + flowFileContents[4] + "demarcator" + flowFileContents[5] + "footer"
+          "header" + flowFileContents_[0] + "demarcator" + flowFileContents_[1] + "demarcator" + flowFileContents_[2] + "footer",
+          "header" + flowFileContents_[3] + "demarcator" + flowFileContents_[4] + "demarcator" + flowFileContents_[5] + "footer"
   };
 
   std::ofstream(HEADER_FILE, std::ios::binary) << "header";
   std::ofstream(FOOTER_FILE, std::ios::binary) << "footer";
   std::ofstream(DEMARCATOR_FILE, std::ios::binary) << "demarcator";
 
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_FILENAME);
-  context->setProperty(minifi::processors::MergeContent::Header, HEADER_FILE);
-  context->setProperty(minifi::processors::MergeContent::Footer, FOOTER_FILE);
-  context->setProperty(minifi::processors::MergeContent::Demarcator, DEMARCATOR_FILE);
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_FILENAME);
+  context_->setProperty(minifi::processors::MergeContent::Header, HEADER_FILE);
+  context_->setProperty(minifi::processors::MergeContent::Footer, FOOTER_FILE);
+  context_->setProperty(minifi::processors::MergeContent::Demarcator, DEMARCATOR_FILE);
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 6 flowfiles, first three merged to one, second three merged to one
   for (const int i : {0, 2, 5, 4, 1, 3}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     // three bundle
     if (i < 3)
       flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_ID_ATTRIBUTE, std::to_string(0));
@@ -288,21 +290,21 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileDefragmentDelimiter", "[mergefil
       flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_INDEX_ATTRIBUTE, std::to_string(i-3));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_COUNT_ATTRIBUTE, std::to_string(3));
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 6; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   REQUIRE(flow1->getSize() == 128);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
@@ -320,20 +322,20 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileDefragmentDelimiter", "[mergefil
 TEST_CASE_METHOD(MergeTestController, "MergeFileDefragmentDropFlow", "[mergefiletest3]") {
   // drop record 4
   std::string expected[2]{
-    flowFileContents[0] + flowFileContents[1] + flowFileContents[2],
-    flowFileContents[3] + flowFileContents[5]
+          flowFileContents_[0] + flowFileContents_[1] + flowFileContents_[2],
+          flowFileContents_[3] + flowFileContents_[5]
   };
 
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::MergeContent::MaxBinAge, "1 sec");
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MaxBinAge, "1 sec");
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 5 flowfiles, first threes merged to one, the other two merged to one
   for (const int i : {0, 2, 5, 1, 3}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     // three bundle
     if (i < 3)
       flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_ID_ATTRIBUTE, std::to_string(0));
@@ -345,27 +347,27 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileDefragmentDropFlow", "[mergefile
       flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_INDEX_ATTRIBUTE, std::to_string(i-3));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_COUNT_ATTRIBUTE, std::to_string(3));
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 5; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   std::this_thread::sleep_for(std::chrono::milliseconds(2000));
   {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   REQUIRE(flow1->getSize() == 96);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
@@ -382,38 +384,38 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileDefragmentDropFlow", "[mergefile
 
 TEST_CASE_METHOD(MergeTestController, "MergeFileBinPack", "[mergefiletest4]") {
   std::string expected[2]{
-    flowFileContents[0] + flowFileContents[1] + flowFileContents[2],
-    flowFileContents[3] + flowFileContents[4] + flowFileContents[5]
+          flowFileContents_[0] + flowFileContents_[1] + flowFileContents_[2],
+          flowFileContents_[3] + flowFileContents_[4] + flowFileContents_[5]
   };
 
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::MergeContent::MinSize, "96");
-  context->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MinSize, "96");
+  context_->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 6 flowfiles, first threes merged to one, second thress merged to one
   for (const int i : {0, 1, 2, 3, 4, 5}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     flow->setAttribute("tag", "tag");
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 6; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   REQUIRE(flow1->getSize() == 96);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
@@ -430,34 +432,34 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileBinPack", "[mergefiletest4]") {
 
 
 TEST_CASE_METHOD(MergeTestController, "MergeFileTar", "[mergefiletest4]") {
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_TAR_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::MergeContent::MinSize, "96");
-  context->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_TAR_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MinSize, "96");
+  context_->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 6 flowfiles, first threes merged to one, second thress merged to one
   for (const int i : {0, 1, 2, 3, 4, 5}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     flow->setAttribute("tag", "tag");
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 6; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   REQUIRE(flow1->getSize() > 0);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
@@ -465,7 +467,7 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileTar", "[mergefiletest4]") {
     auto archives = read_archives(callback);
     REQUIRE(archives.size() == 3);
     for (int i = 0; i < 3; i++) {
-      REQUIRE(archives[i].to_string() == flowFileContents[i]);
+      REQUIRE(archives[i].to_string() == flowFileContents_[i]);
     }
   }
   REQUIRE(flow2->getSize() > 0);
@@ -475,40 +477,40 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileTar", "[mergefiletest4]") {
     auto archives = read_archives(callback);
     REQUIRE(archives.size() == 3);
     for (int i = 3; i < 6; i++) {
-      REQUIRE(archives[i-3].to_string() == flowFileContents[i]);
+      REQUIRE(archives[i-3].to_string() == flowFileContents_[i]);
     }
   }
 }
 
 TEST_CASE_METHOD(MergeTestController, "MergeFileZip", "[mergefiletest5]") {
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_ZIP_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::MergeContent::MinSize, "96");
-  context->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_ZIP_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MinSize, "96");
+  context_->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 6 flowfiles, first threes merged to one, second thress merged to one
   for (const int i : {0, 1, 2, 3, 4, 5}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     flow->setAttribute("tag", "tag");
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 6; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   REQUIRE(flow1->getSize() > 0);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
@@ -516,7 +518,7 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileZip", "[mergefiletest5]") {
     auto archives = read_archives(callback);
     REQUIRE(archives.size() == 3);
     for (int i = 0; i < 3; i++) {
-      REQUIRE(archives[i].to_string() == flowFileContents[i]);
+      REQUIRE(archives[i].to_string() == flowFileContents_[i]);
     }
   }
   REQUIRE(flow2->getSize() > 0);
@@ -526,48 +528,48 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileZip", "[mergefiletest5]") {
     auto archives = read_archives(callback);
     REQUIRE(archives.size() == 3);
     for (int i = 3; i < 6; i++) {
-      REQUIRE(archives[i-3].to_string() == flowFileContents[i]);
+      REQUIRE(archives[i-3].to_string() == flowFileContents_[i]);
     }
   }
 }
 
 TEST_CASE_METHOD(MergeTestController, "MergeFileOnAttribute", "[mergefiletest5]") {
   std::string expected[2]{
-      flowFileContents[0] + flowFileContents[2] + flowFileContents[4],
-      flowFileContents[1] + flowFileContents[3] + flowFileContents[5]
+          flowFileContents_[0] + flowFileContents_[2] + flowFileContents_[4],
+          flowFileContents_[1] + flowFileContents_[3] + flowFileContents_[5]
   };
 
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::MergeContent::MinEntries, "3");
-  context->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MinEntries, "3");
+  context_->setProperty(minifi::processors::MergeContent::CorrelationAttributeName, "tag");
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 6 flowfiles, even files are merged to one, odd files are merged to an other
   for (const int i : {0, 1, 2, 3, 4, 5}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     if (i % 2 == 0)
       flow->setAttribute("tag", "even");
     else
       flow->setAttribute("tag", "odd");
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 6; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
   {
     FixedBuffer callback(flow1->getSize());
     sessionGenFlowFile.read(flow1, &callback);
@@ -581,16 +583,16 @@ TEST_CASE_METHOD(MergeTestController, "MergeFileOnAttribute", "[mergefiletest5]"
 }
 
 TEST_CASE_METHOD(MergeTestController, "Test Merge File Attributes Keeping Only Common Attributes", "[testMergeFileKeepOnlyCommonAttributes]") {
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_TAR_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_TAR_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
 
   // Generate 3 flowfiles merging all into one
   for (const int i : {1, 2, 0}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_ID_ATTRIBUTE, std::to_string(0));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_INDEX_ATTRIBUTE, std::to_string(i));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_COUNT_ATTRIBUTE, std::to_string(3));
@@ -607,19 +609,19 @@ TEST_CASE_METHOD(MergeTestController, "Test Merge File Attributes Keeping Only C
     flow->setAttribute("tagCommon", "common");
 
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 3; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow = output_->poll(expiredFlowRecords);
 
   auto attributes = flow->getAttributes();
   REQUIRE(attributes.find("tagUncommon") == attributes.end());
@@ -630,16 +632,16 @@ TEST_CASE_METHOD(MergeTestController, "Test Merge File Attributes Keeping Only C
 }
 
 TEST_CASE_METHOD(MergeTestController, "Test Merge File Attributes Keeping All Unique Attributes", "[testMergeFileKeepAllUniqueAttributes]") {
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_TAR_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::MergeContent::AttributeStrategy, minifi::processors::merge_content_options::ATTRIBUTE_STRATEGY_KEEP_ALL_UNIQUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_TAR_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_DEFRAGMENT);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::MergeContent::AttributeStrategy, minifi::processors::merge_content_options::ATTRIBUTE_STRATEGY_KEEP_ALL_UNIQUE);
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // Generate 3 flowfiles merging all into one
   for (const int i : {1, 2, 0}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_ID_ATTRIBUTE, std::to_string(0));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_INDEX_ATTRIBUTE, std::to_string(i));
     flow->setAttribute(minifi::processors::BinFiles::FRAGMENT_COUNT_ATTRIBUTE, std::to_string(3));
@@ -656,19 +658,19 @@ TEST_CASE_METHOD(MergeTestController, "Test Merge File Attributes Keeping All Un
     flow->setAttribute("tagCommon", "common");
 
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   for (int i = 0; i < 3; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow = output->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow = output_->poll(expiredFlowRecords);
 
   auto attributes = flow->getAttributes();
   REQUIRE(attributes.find("tagUncommon") == attributes.end());
@@ -684,10 +686,10 @@ void writeString(const std::string& str, const std::shared_ptr<minifi::io::BaseS
 
 TEST_CASE("FlowFile serialization", "[testFlowFileSerialization]") {
   MergeTestController testController;
-  auto context = testController.context;
-  auto processor = testController.processor;
-  auto input = testController.input;
-  auto output = testController.output;
+  auto context = testController.context_;
+  auto& merge_content_processor = testController.merge_content_processor_;
+  auto& input = testController.input_;
+  auto& output = testController.output_;
 
   std::string header = "BEGIN{";
   std::string footer = "}END";
@@ -753,10 +755,10 @@ TEST_CASE("FlowFile serialization", "[testFlowFileSerialization]") {
   const auto expected = utils::span_to<std::string>(result->getBuffer().as_span<const char>());
 
   auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  merge_content_processor->onSchedule(context, factory);
   for (int i = 0; i < 3; i++) {
     auto mergeSession = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, mergeSession);
+    merge_content_processor->onTrigger(context, mergeSession);
     mergeSession->commit();
   }
 
@@ -775,38 +777,38 @@ TEST_CASE("FlowFile serialization", "[testFlowFileSerialization]") {
 
 TEST_CASE_METHOD(MergeTestController, "Batch Size", "[testMergeFileBatchSize]") {
   std::string expected[2]{
-    flowFileContents[0] + flowFileContents[1] + flowFileContents[2],
-    flowFileContents[3] + flowFileContents[4]
+          flowFileContents_[0] + flowFileContents_[1] + flowFileContents_[2],
+          flowFileContents_[3] + flowFileContents_[4]
   };
 
-  context->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
-  context->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
-  context->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
-  context->setProperty(minifi::processors::BinFiles::BatchSize, "3");
+  context_->setProperty(minifi::processors::MergeContent::MergeFormat, minifi::processors::merge_content_options::MERGE_FORMAT_CONCAT_VALUE);
+  context_->setProperty(minifi::processors::MergeContent::MergeStrategy, minifi::processors::merge_content_options::MERGE_STRATEGY_BIN_PACK);
+  context_->setProperty(minifi::processors::MergeContent::DelimiterStrategy, minifi::processors::merge_content_options::DELIMITER_STRATEGY_TEXT);
+  context_->setProperty(minifi::processors::BinFiles::BatchSize, "3");
 
-  core::ProcessSession sessionGenFlowFile(context);
+  core::ProcessSession sessionGenFlowFile(context_);
   // enqueue 5 (five) flowFiles
   for (const int i : {0, 1, 2, 3, 4}) {
     const auto flow = sessionGenFlowFile.create();
-    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents[i]), flow);
+    sessionGenFlowFile.importFrom(minifi::io::BufferStream(flowFileContents_[i]), flow);
     sessionGenFlowFile.flushContent();
-    input->put(flow);
+    input_->put(flow);
   }
 
-  REQUIRE(processor->getName() == "mergecontent");
-  auto factory = std::make_shared<core::ProcessSessionFactory>(context);
-  processor->onSchedule(context, factory);
+  REQUIRE(merge_content_processor_->getName() == "mergecontent");
+  auto factory = std::make_shared<core::ProcessSessionFactory>(context_);
+  merge_content_processor_->onSchedule(context_, factory);
   // two trigger is enough to process all five flowFiles
   for (int i = 0; i < 2; i++) {
-    auto session = std::make_shared<core::ProcessSession>(context);
-    processor->onTrigger(context, session);
+    auto session = std::make_shared<core::ProcessSession>(context_);
+    merge_content_processor_->onTrigger(context_, session);
     session->commit();
   }
   // validate the merge content
   std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords;
-  std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords);
-  std::shared_ptr<core::FlowFile> flow2 = output->poll(expiredFlowRecords);
-  REQUIRE(expiredFlowRecords.size() == 0);
+  std::shared_ptr<core::FlowFile> flow1 = output_->poll(expiredFlowRecords);
+  std::shared_ptr<core::FlowFile> flow2 = output_->poll(expiredFlowRecords);
+  REQUIRE(expiredFlowRecords.empty());
   REQUIRE(flow1);
   {
     FixedBuffer callback(gsl::narrow<size_t>(flow1->getSize()));
diff --git a/libminifi/test/flow-tests/CycleTest.cpp b/libminifi/test/flow-tests/CycleTest.cpp
index 595ba5c..889fd01 100644
--- a/libminifi/test/flow-tests/CycleTest.cpp
+++ b/libminifi/test/flow-tests/CycleTest.cpp
@@ -113,9 +113,9 @@ TEST_CASE("Flow with two long cycle", "[FlowWithCycle]") {
   auto controller = testController.controller_;
   auto root = testController.root_;
 
-  auto procGenerator = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestFlowFileGenerator>(root->findProcessorByName("Generator"));
-  auto procA = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestProcessor>(root->findProcessorByName("A"));
-  auto procB = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestProcessor>(root->findProcessorByName("B"));
+  auto procGenerator = static_cast<org::apache::nifi::minifi::processors::TestFlowFileGenerator*>(root->findProcessorByName("Generator"));
+  auto procA = static_cast<org::apache::nifi::minifi::processors::TestProcessor*>(root->findProcessorByName("A"));
+  auto procB = static_cast<org::apache::nifi::minifi::processors::TestProcessor*>(root->findProcessorByName("B"));
 
   int tryCount = 0;
   while (tryCount++ < 10 && !(procA->trigger_count.load() >= 10 && procB->trigger_count.load() >= 10)) {
diff --git a/libminifi/test/flow-tests/FlowControllerTests.cpp b/libminifi/test/flow-tests/FlowControllerTests.cpp
index 3052f78..2000132 100644
--- a/libminifi/test/flow-tests/FlowControllerTests.cpp
+++ b/libminifi/test/flow-tests/FlowControllerTests.cpp
@@ -110,11 +110,11 @@ TEST_CASE("Flow shutdown drains connections", "[TestFlow1]") {
 
   testController.configuration_->set(minifi::Configure::nifi_flowcontroller_drain_timeout, "100 ms");
 
-  auto sinkProc = std::static_pointer_cast<minifi::processors::TestProcessor>(root->findProcessorByName("TestProcessor"));
+  auto sinkProc = static_cast<minifi::processors::TestProcessor*>(root->findProcessorByName("TestProcessor"));
   // prevent execution of the consumer processor
   sinkProc->yield(10s);
 
-  std::map<std::string, std::shared_ptr<minifi::Connection>> connectionMap;
+  std::map<std::string, minifi::Connection*> connectionMap;
 
   root->getConnections(connectionMap);
   // adds the single connection to the map both by name and id
@@ -145,8 +145,8 @@ TEST_CASE("Flow shutdown waits for a while", "[TestFlow2]") {
 
   testController.configuration_->set(minifi::Configure::nifi_flowcontroller_drain_timeout, "10 s");
 
-  auto sourceProc = std::static_pointer_cast<minifi::processors::TestFlowFileGenerator>(root->findProcessorByName("Generator"));
-  auto sinkProc = std::static_pointer_cast<minifi::processors::TestProcessor>(root->findProcessorByName("TestProcessor"));
+  auto sourceProc = static_cast<minifi::processors::TestFlowFileGenerator*>(root->findProcessorByName("Generator"));
+  auto sinkProc = static_cast<minifi::processors::TestProcessor*>(root->findProcessorByName("TestProcessor"));
 
   std::promise<void> execSinkPromise;
   std::future<void> execSinkFuture = execSinkPromise.get_future();
@@ -176,8 +176,8 @@ TEST_CASE("Flow stopped after grace period", "[TestFlow3]") {
 
   testController.configuration_->set(minifi::Configure::nifi_flowcontroller_drain_timeout, "1000 ms");
 
-  auto sourceProc = std::static_pointer_cast<minifi::processors::TestFlowFileGenerator>(root->findProcessorByName("Generator"));
-  auto sinkProc = std::static_pointer_cast<minifi::processors::TestProcessor>(root->findProcessorByName("TestProcessor"));
+  auto sourceProc = static_cast<minifi::processors::TestFlowFileGenerator*>(root->findProcessorByName("Generator"));
+  auto sinkProc = static_cast<minifi::processors::TestProcessor*>(root->findProcessorByName("TestProcessor"));
 
   std::promise<void> execSinkPromise;
   std::future<void> execSinkFuture = execSinkPromise.get_future();
@@ -215,8 +215,8 @@ TEST_CASE("Extend the waiting period during shutdown", "[TestFlow4]") {
 
   testController.configuration_->set(minifi::Configure::nifi_flowcontroller_drain_timeout, std::to_string(timeout_ms) + " ms");
 
-  auto sourceProc = std::static_pointer_cast<minifi::processors::TestFlowFileGenerator>(root->findProcessorByName("Generator"));
-  auto sinkProc = std::static_pointer_cast<minifi::processors::TestProcessor>(root->findProcessorByName("TestProcessor"));
+  auto sourceProc = static_cast<minifi::processors::TestFlowFileGenerator*>(root->findProcessorByName("Generator"));
+  auto sinkProc = static_cast<minifi::processors::TestProcessor*>(root->findProcessorByName("TestProcessor"));
 
   std::promise<void> execSinkPromise;
   std::future<void> execSinkFuture = execSinkPromise.get_future();
diff --git a/libminifi/test/flow-tests/LoopTest.cpp b/libminifi/test/flow-tests/LoopTest.cpp
index 6aa491e..aa7ca2c 100644
--- a/libminifi/test/flow-tests/LoopTest.cpp
+++ b/libminifi/test/flow-tests/LoopTest.cpp
@@ -91,8 +91,8 @@ TEST_CASE("Flow with a single loop", "[SingleLoopFlow]") {
   auto controller = testController.controller_;
   auto root = testController.root_;
 
-  auto procGenerator = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestFlowFileGenerator>(root->findProcessorByName("Generator"));
-  auto procA = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestProcessor>(root->findProcessorByName("A"));
+  auto procGenerator = static_cast<org::apache::nifi::minifi::processors::TestFlowFileGenerator*>(root->findProcessorByName("Generator"));
+  auto procA = static_cast<org::apache::nifi::minifi::processors::TestProcessor*>(root->findProcessorByName("A"));
 
   int tryCount = 0;
   // wait for the procA to get triggered 15 times
diff --git a/libminifi/test/flow-tests/MultiLoopTest.cpp b/libminifi/test/flow-tests/MultiLoopTest.cpp
index e27e063..e30b077 100644
--- a/libminifi/test/flow-tests/MultiLoopTest.cpp
+++ b/libminifi/test/flow-tests/MultiLoopTest.cpp
@@ -100,11 +100,11 @@ TEST_CASE("Flow with two loops", "[MultiLoopFlow]") {
   auto controller = testController.controller_;
   auto root = testController.root_;
 
-  auto procGenerator = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestFlowFileGenerator>(root->findProcessorByName("Generator"));
-  auto procA = std::static_pointer_cast<org::apache::nifi::minifi::processors::TestProcessor>(root->findProcessorByName("A"));
+  auto procGenerator = static_cast<org::apache::nifi::minifi::processors::TestFlowFileGenerator*>(root->findProcessorByName("Generator"));
+  auto procA = static_cast<org::apache::nifi::minifi::processors::TestProcessor*>(root->findProcessorByName("A"));
 
   int tryCount = 0;
-  while (tryCount++ < 10 && !(procA->trigger_count.load() > 15)) {
+  while (tryCount++ < 10 && procA->trigger_count.load() <= 15) {
     std::this_thread::sleep_for(std::chrono::milliseconds{1000});
   }
 
diff --git a/libminifi/test/flow-tests/SessionTests.cpp b/libminifi/test/flow-tests/SessionTests.cpp
index e4936f5..24e63a3 100644
--- a/libminifi/test/flow-tests/SessionTests.cpp
+++ b/libminifi/test/flow-tests/SessionTests.cpp
@@ -27,6 +27,7 @@
 #include "utils/Id.h"
 #include "io/BufferStream.h"
 #include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
 #include "core/ProcessorNode.h"
 #include "core/Processor.h"
 #include "repository/VolatileContentRepository.h"
@@ -76,11 +77,11 @@ TEST_CASE("Import null data") {
 
   auto processor = std::make_shared<core::Processor>("dummy");
   utils::Identifier uuid = processor->getUUID();
-  auto output = std::make_shared<minifi::Connection>(ff_repository, content_repo, "output");
+  auto output = std::make_unique<minifi::Connection>(ff_repository, content_repo, "output");
   output->addRelationship({"out", ""});
   output->setSourceUUID(uuid);
-  processor->addConnection(output);
-  auto node = std::make_shared<core::ProcessorNode>(processor);
+  processor->addConnection(output.get());
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
   auto context = std::make_shared<core::ProcessContext>(node, nullptr, prov_repo, ff_repository, content_repo);
   core::ProcessSession session(context);
 
diff --git a/libminifi/test/flow-tests/TestControllerWithFlow.h b/libminifi/test/flow-tests/TestControllerWithFlow.h
index 90c8bba..9841ea8 100644
--- a/libminifi/test/flow-tests/TestControllerWithFlow.h
+++ b/libminifi/test/flow-tests/TestControllerWithFlow.h
@@ -55,15 +55,16 @@ class TestControllerWithFlow: public TestController{
     std::shared_ptr<minifi::io::StreamFactory> stream_factory = minifi::io::StreamFactory::getInstance(configuration_);
 
     auto flow = std::make_unique<core::YamlConfiguration>(prov_repo, ff_repo, content_repo, stream_factory, configuration_, yamlPath);
-    root_ = flow->getRoot();
+    auto root = flow->getRoot();
+    root_ = root.get();
     controller_ = std::make_shared<minifi::FlowController>(
         prov_repo, ff_repo, configuration_,
         std::move(flow),
         content_repo, DEFAULT_ROOT_GROUP_NAME);
+    controller_->load(std::move(root));
   }
 
   void startFlow() {
-    controller_->load(root_);
     controller_->start();
   }
 
@@ -75,5 +76,5 @@ class TestControllerWithFlow: public TestController{
 
   std::shared_ptr<minifi::Configure> configuration_;
   std::shared_ptr<minifi::FlowController> controller_;
-  std::shared_ptr<core::ProcessGroup> root_;
+  core::ProcessGroup* root_;
 };
diff --git a/libminifi/test/integration/IntegrationBase.h b/libminifi/test/integration/IntegrationBase.h
index d62218c..db64e13 100644
--- a/libminifi/test/integration/IntegrationBase.h
+++ b/libminifi/test/integration/IntegrationBase.h
@@ -79,12 +79,12 @@ class IntegrationBase {
   virtual void configureFullHeartbeat() {
   }
 
-  virtual void updateProperties(std::shared_ptr<minifi::FlowController> /*fc*/) {
+  virtual void updateProperties(minifi::FlowController& /*fc*/) {
   }
 
   void configureSecurity();
   std::shared_ptr<minifi::Configure> configuration;
-  std::shared_ptr<minifi::FlowController> flowController_;
+  std::unique_ptr<minifi::FlowController> flowController_;
   std::chrono::milliseconds wait_time_;
   std::string port, scheme;
   std::string key_dir;
@@ -152,9 +152,9 @@ void IntegrationBase::run(const std::optional<std::string>& test_file_location,
 
   std::shared_ptr<TestRepository> repo = std::static_pointer_cast<TestRepository>(test_repo);
 
-  flowController_ = std::make_shared<minifi::FlowController>(test_repo, test_flow_repo, configuration, std::move(flow_config), content_repo, DEFAULT_ROOT_GROUP_NAME);
+  flowController_ = std::make_unique<minifi::FlowController>(test_repo, test_flow_repo, configuration, std::move(flow_config), content_repo, DEFAULT_ROOT_GROUP_NAME);
   flowController_->load();
-  updateProperties(flowController_);
+  updateProperties(*flowController_);
   flowController_->start();
 
   runAssertions();
diff --git a/libminifi/test/integration/OnScheduleErrorHandlingTests.cpp b/libminifi/test/integration/OnScheduleErrorHandlingTests.cpp
index ade9557..575cf71 100644
--- a/libminifi/test/integration/OnScheduleErrorHandlingTests.cpp
+++ b/libminifi/test/integration/OnScheduleErrorHandlingTests.cpp
@@ -21,11 +21,10 @@
 #include "IntegrationBase.h"
 #include "core/logging/Logger.h"
 #include "core/Scheduling.h"
-#include "core/state/UpdateController.h"
 #include "core/state/ProcessorController.h"
 #include "../TestBase.h"
 #include "../Catch.h"
-#include "../KamikazeProcessor.h"
+#include "../../../extensions/test-processors/KamikazeProcessor.h"
 #include "utils/StringUtils.h"
 #include "utils/IntegrationTestUtils.h"
 
@@ -76,8 +75,8 @@ class KamikazeErrorHandlingTests : public IntegrationBase {
 /*Verify that event driven processors without incoming connections are not scheduled*/
 class EventDriverScheduleErrorHandlingTests: public IntegrationBase {
  public:
-  void updateProperties(std::shared_ptr<minifi::FlowController> fc) override {
-    auto controller_vec = fc->getAllComponents();
+  void updateProperties(minifi::FlowController& fc) override {
+    auto controller_vec = fc.getAllComponents();
     /* This tests depends on a configuration that contains only one KamikazeProcessor named kamikaze
      * (See testOnScheduleRetry.yml)
      * In this case there are two components in the flowcontroller: first is the controller itself,
@@ -88,7 +87,7 @@ class EventDriverScheduleErrorHandlingTests: public IntegrationBase {
     assert(controller_vec[0]->getComponentName() == "FlowController");
     assert(controller_vec[1]->getComponentName() == "kamikaze");
 
-    auto process_controller = dynamic_cast<org::apache::nifi::minifi::state::ProcessorController*>(controller_vec[1].get());
+    auto process_controller = dynamic_cast<org::apache::nifi::minifi::state::ProcessorController*>(controller_vec[1]);
     assert(process_controller != nullptr);
 
     process_controller->getProcessor()->setSchedulingStrategy(org::apache::nifi::minifi::core::SchedulingStrategy::EVENT_DRIVEN);
diff --git a/libminifi/test/integration/StateTransactionalityTests.cpp b/libminifi/test/integration/StateTransactionalityTests.cpp
index 9405b92..66671dd 100644
--- a/libminifi/test/integration/StateTransactionalityTests.cpp
+++ b/libminifi/test/integration/StateTransactionalityTests.cpp
@@ -55,8 +55,8 @@ class StatefulIntegrationTest : public IntegrationBase {
     logger_->log_info("Running test case \"%s\"", test_case_);
   }
 
-  void updateProperties(std::shared_ptr<minifi::FlowController> fc) override {
-    const auto controllerVec = fc->getAllComponents();
+  void updateProperties(minifi::FlowController& fc) override {
+    const auto controllerVec = fc.getAllComponents();
     /* This tests depends on a configuration that contains only one StatefulProcessor named statefulProcessor
      * (See TestStateTransactionality.yml)
      * In this case there are two components in the flowcontroller: first is the controller itself,
@@ -68,9 +68,9 @@ class StatefulIntegrationTest : public IntegrationBase {
     assert(controllerVec[1]->getComponentName() == "statefulProcessor");
 
     // set hooks
-    const auto processController = std::dynamic_pointer_cast<ProcessorController>(controllerVec[1]);
+    const auto processController = dynamic_cast<ProcessorController*>(controllerVec[1]);
     assert(processController != nullptr);
-    stateful_processor_ = std::dynamic_pointer_cast<StatefulProcessor>(processController->getProcessor());
+    stateful_processor_ = dynamic_cast<StatefulProcessor*>(processController->getProcessor());
     assert(stateful_processor_ != nullptr);
     stateful_processor_->setHooks(on_schedule_hook_, on_trigger_hooks_);
   }
@@ -87,7 +87,7 @@ class StatefulIntegrationTest : public IntegrationBase {
   const std::vector<StatefulProcessor::HookType> on_trigger_hooks_;
   const LogChecker log_checker_;
   const std::string test_case_;
-  std::shared_ptr<StatefulProcessor> stateful_processor_;
+  StatefulProcessor* stateful_processor_;
   std::shared_ptr<logging::Logger> logger_{logging::LoggerFactory<StatefulIntegrationTest>::getLogger()};
 };
 
diff --git a/libminifi/test/pcap-tests/PcapTest.cpp b/libminifi/test/pcap-tests/PcapTest.cpp
index e2be059..236e0eb 100644
--- a/libminifi/test/pcap-tests/PcapTest.cpp
+++ b/libminifi/test/pcap-tests/PcapTest.cpp
@@ -77,10 +77,10 @@ class PcapTestHarness : public IntegrationBase {
         "because it matches .*"));
   }
 
-  void updateProperties(std::shared_ptr<minifi::FlowController> fc) override {
-    auto components = fc->getComponents("pcap");
+  void updateProperties(minifi::FlowController& fc) override {
+    auto components = fc.getComponents("pcap");
     for (const auto& component : components) {
-      auto proccontroller = std::dynamic_pointer_cast<minifi::state::ProcessorController>(component);
+      auto proccontroller = dynamic_cast<minifi::state::ProcessorController*>(component);
       if (proccontroller) {
         auto processor = proccontroller->getProcessor();
         processor->setProperty(minifi::processors::CapturePacket::BaseDir.getName(), dir);
diff --git a/libminifi/test/persistence-tests/PersistenceTests.cpp b/libminifi/test/persistence-tests/PersistenceTests.cpp
index 3b670a3..d280115 100644
--- a/libminifi/test/persistence-tests/PersistenceTests.cpp
+++ b/libminifi/test/persistence-tests/PersistenceTests.cpp
@@ -50,50 +50,53 @@ const std::string PERSISTENCETEST_FLOWFILE_CHECKPOINT_DIR = "./persistencetest_f
 
 struct TestFlow{
   TestFlow(const std::shared_ptr<core::Repository>& ff_repository, const std::shared_ptr<core::ContentRepository>& content_repo, const std::shared_ptr<core::Repository>& prov_repo,
-        const std::function<std::shared_ptr<core::Processor>(utils::Identifier&)>& processorGenerator, const core::Relationship& relationshipToOutput)
+        const std::function<std::unique_ptr<core::Processor>(utils::Identifier&)>& processorGenerator, const core::Relationship& relationshipToOutput)
       : ff_repository(ff_repository), content_repo(content_repo), prov_repo(prov_repo) {
     // setup processor
+    auto processor = processorGenerator(mainProcUUID());
     {
-      processor = processorGenerator(mainProcUUID());
-      std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
+      processor_ = processor.get();
+      auto node = std::make_shared<core::ProcessorNode>(processor_);
       processorContext = std::make_shared<core::ProcessContext>(node, nullptr, prov_repo, ff_repository, content_repo);
     }
 
     // setup INPUT processor
     {
       inputProcessor = std::make_shared<core::Processor>("source", inputProcUUID());
-      std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(inputProcessor);
+      auto node = std::make_shared<core::ProcessorNode>(inputProcessor.get());
       inputContext = std::make_shared<core::ProcessContext>(node, nullptr, prov_repo,
                                                             ff_repository, content_repo);
     }
 
     // setup Input Connection
+    auto input = std::make_unique<Connection>(ff_repository, content_repo, "Input", inputConnUUID());
     {
-      input = std::make_shared<Connection>(ff_repository, content_repo, "Input", inputConnUUID());
+      input_ = input.get();
       input->setRelationship({"input", "d"});
       input->setDestinationUUID(mainProcUUID());
       input->setSourceUUID(inputProcUUID());
-      inputProcessor->addConnection(input);
+      inputProcessor->addConnection(input.get());
     }
 
     // setup Output Connection
+    auto output = std::make_unique<Connection>(ff_repository, content_repo, "Output", outputConnUUID());
     {
-      output = std::make_shared<Connection>(ff_repository, content_repo, "Output", outputConnUUID());
+      output_ = output.get();
       output->setRelationship(relationshipToOutput);
       output->setSourceUUID(mainProcUUID());
     }
 
     // setup ProcessGroup
     {
-      root = std::make_shared<core::ProcessGroup>(core::ProcessGroupType::ROOT_PROCESS_GROUP, "root");
-      root->addProcessor(processor);
-      root->addConnection(input);
-      root->addConnection(output);
+      root_ = std::make_unique<core::ProcessGroup>(core::ProcessGroupType::ROOT_PROCESS_GROUP, "root");
+      root_->addProcessor(std::move(processor));
+      root_->addConnection(std::move(input));
+      root_->addConnection(std::move(output));
     }
 
     // prepare Merge Processor for execution
-    processor->setScheduledState(core::ScheduledState::RUNNING);
-    processor->onSchedule(processorContext.get(), new core::ProcessSessionFactory(processorContext));
+    processor_->setScheduledState(core::ScheduledState::RUNNING);
+    processor_->onSchedule(processorContext.get(), new core::ProcessSessionFactory(processorContext));
   }
   std::shared_ptr<core::FlowFile> write(const std::string& data) {
     minifi::io::BufferStream stream(data);
@@ -111,13 +114,13 @@ struct TestFlow{
   }
   void trigger() {
     auto session = std::make_shared<core::ProcessSession>(processorContext);
-    processor->onTrigger(processorContext, session);
+    processor_->onTrigger(processorContext, session);
     session->commit();
   }
 
-  std::shared_ptr<Connection> input;
-  std::shared_ptr<Connection> output;
-  std::shared_ptr<core::ProcessGroup> root;
+  Connection* input_;
+  Connection* output_;
+  std::unique_ptr<core::ProcessGroup> root_;
 
  private:
   static utils::Identifier& mainProcUUID() {static auto id = utils::IdGenerator::getIdGenerator()->generate(); return id;}
@@ -126,7 +129,7 @@ struct TestFlow{
   static utils::Identifier& outputConnUUID() {static auto id = utils::IdGenerator::getIdGenerator()->generate(); return id;}
 
   std::shared_ptr<core::Processor> inputProcessor;
-  std::shared_ptr<core::Processor> processor;
+  core::Processor* processor_;
   std::shared_ptr<core::Repository> ff_repository;
   std::shared_ptr<core::ContentRepository> content_repo;
   std::shared_ptr<core::Repository> prov_repo;
@@ -134,8 +137,8 @@ struct TestFlow{
   std::shared_ptr<core::ProcessContext> processorContext;
 };
 
-std::shared_ptr<MergeContent> setupMergeProcessor(const utils::Identifier& id) {
-  auto processor = std::make_shared<MergeContent>("MergeContent", id);
+std::unique_ptr<MergeContent> setupMergeProcessor(const utils::Identifier& id) {
+  auto processor = std::make_unique<MergeContent>("MergeContent", id);
   processor->initialize();
   processor->setAutoTerminatedRelationships({{"original", "d"}});
 
@@ -171,14 +174,14 @@ TEST_CASE("Processors Can Store FlowFiles", "[TestP1]") {
   ff_repository->initialize(config);
   content_repo->initialize(config);
 
-  auto flowConfig = std::unique_ptr<core::FlowConfiguration>{new core::FlowConfiguration(prov_repo, ff_repository, content_repo, nullptr, config, "")};
+  auto flowConfig = std::make_unique<core::FlowConfiguration>(prov_repo, ff_repository, content_repo, nullptr, config, "");
   auto flowController = std::make_shared<minifi::FlowController>(
       prov_repo, ff_repository, config, std::move(flowConfig), content_repo, "");
 
   {
     TestFlow flow(ff_repository, content_repo, prov_repo, setupMergeProcessor, MergeContent::Merge);
 
-    flowController->load(flow.root);
+    flowController->load(std::move(flow.root_));
     ff_repository->start();
 
     // write two files into the input
@@ -193,11 +196,11 @@ TEST_CASE("Processors Can Store FlowFiles", "[TestP1]") {
 
     // check if the processor has taken ownership
     std::set<std::shared_ptr<core::FlowFile>> expired;
-    auto file = flow.input->poll(expired);
+    auto file = flow.input_->poll(expired);
     REQUIRE(!file);
     REQUIRE(expired.empty());
 
-    file = flow.output->poll(expired);
+    file = flow.output_->poll(expired);
     REQUIRE(!file);
     REQUIRE(expired.empty());
   }
@@ -206,7 +209,7 @@ TEST_CASE("Processors Can Store FlowFiles", "[TestP1]") {
   {
     TestFlow flow(ff_repository, content_repo, prov_repo, setupMergeProcessor, MergeContent::Merge);
 
-    flowController->load(flow.root);
+    flowController->load(std::move(flow.root_));
     ff_repository->start();
     // wait for FlowFileRepository to start and notify the owners of
     // the resurrected FlowFiles
@@ -222,7 +225,7 @@ TEST_CASE("Processors Can Store FlowFiles", "[TestP1]") {
     std::shared_ptr<org::apache::nifi::minifi::core::FlowFile> file = nullptr;
     std::set<std::shared_ptr<core::FlowFile>> expired;
     const auto flowFileArrivedInOutput = [&file, &expired, &flow] {
-      file = flow.output->poll(expired);
+      file = flow.output_->poll(expired);
       return file != nullptr;
     };
     assert(verifyEventHappenedInPollTime(std::chrono::seconds(1), flowFileArrivedInOutput, std::chrono::milliseconds(50)));
@@ -246,8 +249,8 @@ class ContentUpdaterProcessor : public core::Processor{
   }
 };
 
-std::shared_ptr<core::Processor> setupContentUpdaterProcessor(const utils::Identifier& id) {
-  return std::make_shared<ContentUpdaterProcessor>("Updater", id);
+std::unique_ptr<core::Processor> setupContentUpdaterProcessor(const utils::Identifier& id) {
+  return std::make_unique<ContentUpdaterProcessor>("Updater", id);
 }
 
 TEST_CASE("Persisted flowFiles are updated on modification", "[TestP1]") {
@@ -285,14 +288,14 @@ TEST_CASE("Persisted flowFiles are updated on modification", "[TestP1]") {
   ff_repository->initialize(config);
   content_repo->initialize(config);
 
-  auto flowConfig = std::unique_ptr<core::FlowConfiguration>{new core::FlowConfiguration(prov_repo, ff_repository, content_repo, nullptr, config, "")};
+  auto flowConfig = std::make_unique<core::FlowConfiguration>(prov_repo, ff_repository, content_repo, nullptr, config, "");
   auto flowController = std::make_shared<minifi::FlowController>(
       prov_repo, ff_repository, config, std::move(flowConfig), content_repo, "");
 
   {
     TestFlow flow(ff_repository, content_repo, prov_repo, setupContentUpdaterProcessor, {"success", "d"});
 
-    flowController->load(flow.root);
+    flowController->load(std::move(flow.root_));
     ff_repository->start();
 
     std::string removedResource;
@@ -328,7 +331,7 @@ TEST_CASE("Persisted flowFiles are updated on modification", "[TestP1]") {
   {
     TestFlow flow(ff_repository, content_repo, prov_repo, setupContentUpdaterProcessor, {"success", "d"});
 
-    flowController->load(flow.root);
+    flowController->load(std::move(flow.root_));
     ff_repository->start();
     // wait for FlowFileRepository to start and notify the owners of
     // the resurrected FlowFiles
@@ -337,7 +340,7 @@ TEST_CASE("Persisted flowFiles are updated on modification", "[TestP1]") {
     std::shared_ptr<org::apache::nifi::minifi::core::FlowFile> file = nullptr;
     using org::apache::nifi::minifi::utils::verifyEventHappenedInPollTime;
     const auto flowFileArrivedInOutput = [&file, &expired, &flow] {
-      file = flow.output->poll(expired);
+      file = flow.output_->poll(expired);
       return file != nullptr;
     };
     assert(verifyEventHappenedInPollTime(std::chrono::seconds(1), flowFileArrivedInOutput, std::chrono::milliseconds(50)));
diff --git a/libminifi/test/rocksdb-tests/EncryptionTests.cpp b/libminifi/test/rocksdb-tests/EncryptionTests.cpp
index dff6ef8..6441898 100644
--- a/libminifi/test/rocksdb-tests/EncryptionTests.cpp
+++ b/libminifi/test/rocksdb-tests/EncryptionTests.cpp
@@ -38,7 +38,7 @@ class FFRepoFixture : public TestController {
     checkpoint_dir_ = home_ / "checkpoint_dir";
     config_ = std::make_shared<minifi::Configure>();
     config_->setHome(home_.str());
-    container_ = std::make_shared<minifi::Connection>(nullptr, nullptr, "container");
+    container_ = std::make_unique<minifi::Connection>(nullptr, nullptr, "container");
     content_repo_ = std::make_shared<core::repository::VolatileContentRepository>();
     content_repo_->initialize(config_);
   }
@@ -54,8 +54,8 @@ class FFRepoFixture : public TestController {
   void runWithNewRepository(Fn&& fn) {
     auto repository = std::make_shared<FlowFileRepository>("ff", checkpoint_dir_.str(), repo_dir_.str());
     repository->initialize(config_);
-    std::map<std::string, std::shared_ptr<core::Connectable>> container_map;
-    container_map[container_->getUUIDStr()] = container_;
+    std::map<std::string, core::Connectable*> container_map;
+    container_map[container_->getUUIDStr()] = container_.get();
     repository->setContainers(container_map);
     repository->loadComponent(content_repo_);
     repository->start();
@@ -64,7 +64,7 @@ class FFRepoFixture : public TestController {
   }
 
  protected:
-  std::shared_ptr<minifi::Connection> container_;
+  std::unique_ptr<minifi::Connection> container_;
   Path home_;
   Path repo_dir_;
   Path checkpoint_dir_;
@@ -88,7 +88,7 @@ TEST_CASE_METHOD(FFRepoFixture, "FlowFileRepository creates checkpoint and loads
   runWithNewRepository([&] (const std::shared_ptr<core::repository::FlowFileRepository>& repo) {
     auto flowfile = std::make_shared<minifi::FlowFileRecord>();
     flowfile->setAttribute("my little pony", "my horse is amazing");
-    flowfile->setConnection(container_);
+    flowfile->setConnection(container_.get());
     putFlowFile(flowfile, repo);
   });
 
diff --git a/libminifi/test/rocksdb-tests/RepoTests.cpp b/libminifi/test/rocksdb-tests/RepoTests.cpp
index 65304d5..3ca9f95 100644
--- a/libminifi/test/rocksdb-tests/RepoTests.cpp
+++ b/libminifi/test/rocksdb-tests/RepoTests.cpp
@@ -281,13 +281,14 @@ TEST_CASE("Test FlowFile Restore", "[TestFFR6]") {
   content_repo->initialize(config);
 
   core::Relationship inputRel{"Input", "dummy"};
-  std::shared_ptr<minifi::Connection> input = std::make_shared<minifi::Connection>(ff_repository, content_repo, "Input");
+  auto input = std::make_unique<minifi::Connection>(ff_repository, content_repo, "Input");
   input->setRelationship(inputRel);
 
-  auto root = std::make_shared<core::ProcessGroup>(core::ProcessGroupType::ROOT_PROCESS_GROUP, "root");
-  root->addConnection(input);
+  auto root = std::make_unique<core::ProcessGroup>(core::ProcessGroupType::ROOT_PROCESS_GROUP, "root");
+  auto inputPtr = input.get();
+  root->addConnection(std::move(input));
 
-  auto flowConfig = std::unique_ptr<core::FlowConfiguration>{new core::FlowConfiguration(prov_repo, ff_repository, content_repo, nullptr, config, "")};
+  auto flowConfig = std::make_unique<core::FlowConfiguration>(prov_repo, ff_repository, content_repo, nullptr, config, "");
   auto flowController = std::make_shared<minifi::FlowController>(
       prov_repo, ff_repository, config, std::move(flowConfig), content_repo, "");
 
@@ -305,9 +306,9 @@ TEST_CASE("Test FlowFile Restore", "[TestFFR6]") {
     std::shared_ptr<core::Processor> processor = std::make_shared<core::Processor>("dummy");
     utils::Identifier uuid = processor->getUUID();
     REQUIRE(uuid);
-    input->setSourceUUID(uuid);
-    processor->addConnection(input);
-    std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
+    inputPtr->setSourceUUID(uuid);
+    processor->addConnection(inputPtr);
+    auto node = std::make_shared<core::ProcessorNode>(processor.get());
     auto context = std::make_shared<core::ProcessContext>(node, nullptr, prov_repo, ff_repository, content_repo);
     core::ProcessSession sessionGenFlowFile(context);
     std::shared_ptr<core::FlowFile> flow = std::static_pointer_cast<core::FlowFile>(sessionGenFlowFile.create());
@@ -319,14 +320,14 @@ TEST_CASE("Test FlowFile Restore", "[TestFFR6]") {
   // remove flow from the connection but it is still present in the
   // flowFileRepo
   std::set<std::shared_ptr<core::FlowFile>> expiredFiles;
-  auto oldFlow = input->poll(expiredFiles);
+  auto oldFlow = inputPtr->poll(expiredFiles);
   REQUIRE(oldFlow);
   REQUIRE(expiredFiles.empty());
 
   // this notifies the FlowFileRepository of the flow structure
   // i.e. what Connections are present (more precisely what Connectables
   // are present)
-  flowController->load(root);
+  flowController->load(std::move(root));
   // this will first check the persisted repo and restore all FlowFiles
   // that still has an owner Connectable
   ff_repository->start();
@@ -336,8 +337,8 @@ TEST_CASE("Test FlowFile Restore", "[TestFFR6]") {
   // upon the FlowFileRepository's startup
   std::shared_ptr<org::apache::nifi::minifi::core::FlowFile> newFlow = nullptr;
   using org::apache::nifi::minifi::utils::verifyEventHappenedInPollTime;
-  const auto flowFileArrivedInOutput = [&newFlow, &expiredFiles, &input] {
-    newFlow = input->poll(expiredFiles);
+  const auto flowFileArrivedInOutput = [&newFlow, &expiredFiles, inputPtr] {
+    newFlow = inputPtr->poll(expiredFiles);
     return newFlow != nullptr;
   };
   assert(verifyEventHappenedInPollTime(std::chrono::seconds(10), flowFileArrivedInOutput, std::chrono::milliseconds(50)));
@@ -371,7 +372,7 @@ TEST_CASE("Flush deleted flowfiles before shutdown", "[TestFFR7]") {
   auto content_repo = std::make_shared<core::repository::VolatileContentRepository>();
 
   auto connection = std::make_shared<minifi::Connection>(nullptr, nullptr, "Connection");
-  std::map<std::string, std::shared_ptr<core::Connectable>> connectionMap{{connection->getUUIDStr(), connection}};
+  std::map<std::string, core::Connectable*> connectionMap{{connection->getUUIDStr(), connection.get()}};
   // initialize repository
   {
     std::shared_ptr<TestFlowFileRepository> ff_repository = std::make_shared<TestFlowFileRepository>("flowFileRepository");
@@ -393,7 +394,7 @@ TEST_CASE("Flush deleted flowfiles before shutdown", "[TestFFR7]") {
 
       for (int keyIdx = 0; keyIdx < 100; ++keyIdx) {
         auto file = std::make_shared<minifi::FlowFileRecord>();
-        file->setConnection(connection);
+        file->setConnection(connection.get());
         // Serialize is sync
         REQUIRE(file->Persist(ff_repository));
         if (keyIdx % 2 == 0) {
diff --git a/libminifi/test/sensors-tests/SensorTests.cpp b/libminifi/test/sensors-tests/SensorTests.cpp
index 41a5a0a..f5a90c9 100644
--- a/libminifi/test/sensors-tests/SensorTests.cpp
+++ b/libminifi/test/sensors-tests/SensorTests.cpp
@@ -70,10 +70,10 @@ class PcapTestHarness : public IntegrationBase {
   }
 
   void queryRootProcessGroup(std::shared_ptr<core::ProcessGroup> pg) override {
-    std::shared_ptr<core::Processor> proc = pg->findProcessorByName("pcap");
+    const auto proc = pg->findProcessorByName("pcap");
     assert(proc != nullptr);
 
-    auto inv = std::dynamic_pointer_cast<minifi::processors::GetEnvironmentalSensors>(proc);
+    auto inv = dynamic_cast<minifi::processors::GetEnvironmentalSensors*>(proc);
     assert(inv != nullptr);
 
     configuration->set("nifi.c2.enable", "false");
diff --git a/libminifi/test/sql-tests/SQLTestPlan.h b/libminifi/test/sql-tests/SQLTestPlan.h
index 488c685..a7304ad 100644
--- a/libminifi/test/sql-tests/SQLTestPlan.h
+++ b/libminifi/test/sql-tests/SQLTestPlan.h
@@ -101,6 +101,6 @@ class SQLTestPlan {
  private:
   std::shared_ptr<TestPlan> plan_;
   std::shared_ptr<core::Processor> processor_;
-  std::shared_ptr<minifi::Connection> input_;
-  std::map<core::Relationship, std::shared_ptr<minifi::Connection>> outputs_;
+  minifi::Connection* input_;
+  std::map<core::Relationship, minifi::Connection*> outputs_;
 };
diff --git a/libminifi/test/unit/C2MetricsTests.cpp b/libminifi/test/unit/C2MetricsTests.cpp
index 64fec91..5333706 100644
--- a/libminifi/test/unit/C2MetricsTests.cpp
+++ b/libminifi/test/unit/C2MetricsTests.cpp
@@ -75,13 +75,13 @@ TEST_CASE("QueueMetricsTestConnections", "[c2m3]") {
 
   std::shared_ptr<core::Repository> repo = std::make_shared<TestRepository>();
 
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(repo, content_repo, "testconnection");
-
-  metrics.addConnection(connection);
+  auto connection = std::make_unique<minifi::Connection>(repo, content_repo, "testconnection");
 
   connection->setMaxQueueDataSize(1024);
   connection->setMaxQueueSize(1024);
 
+  metrics.addConnection(std::move(connection));
+
   REQUIRE(1 == metrics.serialize().size());
 
   minifi::state::response::SerializedResponseNode resp = metrics.serialize().at(0);
diff --git a/libminifi/test/unit/ControllerTests.cpp b/libminifi/test/unit/ControllerTests.cpp
index feb6952..bd7cf9b 100644
--- a/libminifi/test/unit/ControllerTests.cpp
+++ b/libminifi/test/unit/ControllerTests.cpp
@@ -82,16 +82,12 @@ class TestUpdateSink : public minifi::state::StateMonitor {
         controller(controller),
         update_calls(0) {
   }
-  std::vector<std::shared_ptr<StateController>> getComponents(const std::string& /*name*/) override {
-    std::vector<std::shared_ptr<StateController>> vec;
-    vec.push_back(controller);
-    return vec;
+  std::vector<StateController*> getComponents(const std::string& /*name*/) override {
+    return std::vector<StateController*>{ controller.get() };
   }
 
-  std::vector<std::shared_ptr<StateController>> getAllComponents() override {
-    std::vector<std::shared_ptr<StateController>> vec;
-    vec.push_back(controller);
-    return vec;
+  std::vector<StateController*> getAllComponents() override {
+    return std::vector<StateController*>{ controller.get() };
   }
 
   std::string getComponentName() const override {
@@ -198,9 +194,9 @@ TEST_CASE("TestGet", "[test1]") {
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
   configuration->set("controller.socket.host", "localhost");
   configuration->set("controller.socket.port", "9997");
-  auto ptr = std::make_shared<TestUpdateSink>(controller);
+  auto ptr = std::make_unique<TestUpdateSink>(controller);
   minifi::c2::ControllerSocketProtocol protocol("testprotocol");
-  protocol.initialize(nullptr, ptr, configuration);
+  protocol.initialize(nullptr, ptr.get(), configuration);
 
   auto stream_factory = minifi::io::StreamFactory::getInstance(configuration);
 
@@ -231,9 +227,9 @@ TEST_CASE("TestClear", "[test1]") {
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
   configuration->set("controller.socket.host", "localhost");
   configuration->set("controller.socket.port", "9997");
-  auto ptr = std::make_shared<TestUpdateSink>(controller);
+  auto ptr = std::make_unique<TestUpdateSink>(controller);
   minifi::c2::ControllerSocketProtocol protocol("testprotocol");
-  protocol.initialize(nullptr, ptr, configuration);
+  protocol.initialize(nullptr, ptr.get(), configuration);
 
   auto stream_factory = minifi::io::StreamFactory::getInstance(configuration);
 
@@ -267,9 +263,9 @@ TEST_CASE("TestUpdate", "[test1]") {
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
   configuration->set("controller.socket.host", "localhost");
   configuration->set("controller.socket.port", "9997");
-  auto ptr = std::make_shared<TestUpdateSink>(controller);
+  auto ptr = std::make_unique<TestUpdateSink>(controller);
   minifi::c2::ControllerSocketProtocol protocol("testprotocol");
-  protocol.initialize(nullptr, ptr, configuration);
+  protocol.initialize(nullptr, ptr.get(), configuration);
 
   auto stream_factory = minifi::io::StreamFactory::getInstance(configuration);
 
diff --git a/libminifi/test/unit/ProcessorConfigUtilsTests.cpp b/libminifi/test/unit/ProcessorConfigUtilsTests.cpp
index e1d2784..63f4582 100644
--- a/libminifi/test/unit/ProcessorConfigUtilsTests.cpp
+++ b/libminifi/test/unit/ProcessorConfigUtilsTests.cpp
@@ -39,7 +39,7 @@ TEST_CASE("Parse enum property") {
       ->build();
   auto proc = std::make_shared<TestProcessor>("test-proc");
   proc->setSupportedProperties({prop});
-  ProcessContext context(std::make_shared<ProcessorNode>(proc), nullptr, nullptr, nullptr, nullptr, nullptr);
+  ProcessContext context(std::make_shared<ProcessorNode>(proc.get()), nullptr, nullptr, nullptr, nullptr, nullptr);
   SECTION("Valid") {
     proc->setProperty(prop, "B");
     TestEnum val = utils::parseEnumProperty<TestEnum>(context, prop);
diff --git a/libminifi/test/unit/ProvenanceTestHelper.h b/libminifi/test/unit/ProvenanceTestHelper.h
index 49050eb..760904b 100644
--- a/libminifi/test/unit/ProvenanceTestHelper.h
+++ b/libminifi/test/unit/ProvenanceTestHelper.h
@@ -54,6 +54,10 @@ class TestRepository : public org::apache::nifi::minifi::core::Repository {
         Repository("repo_name", "./dir", 1s, 100, 0ms) {
   }
 
+  ~TestRepository() override {
+    stop();
+  }
+
   bool initialize(const std::shared_ptr<org::apache::nifi::minifi::Configure> &) override {
     return true;
   }
@@ -62,16 +66,10 @@ class TestRepository : public org::apache::nifi::minifi::core::Repository {
     running_ = true;
   }
 
-  void stop() override {
-    running_ = false;
-  }
-
   void setFull() {
     repo_full_ = true;
   }
 
-  ~TestRepository() override = default;
-
   bool isNoop() override {
     return false;
   }
@@ -180,12 +178,14 @@ class TestFlowRepository : public org::apache::nifi::minifi::core::Repository {
         org::apache::nifi::minifi::core::Repository("ff", "./dir", 1s, 100, 0ms) {
   }
 
+  ~TestFlowRepository() override {
+    stop();
+  }
+
   bool initialize(const std::shared_ptr<org::apache::nifi::minifi::Configure> &) override {
     return true;
   }
 
-  ~TestFlowRepository() override = default;
-
   bool Put(std::string key, const uint8_t *buf, size_t bufLen) override {
     std::lock_guard<std::mutex> lock{repository_results_mutex_};
     repository_results_.emplace(key, std::string{reinterpret_cast<const char*>(buf), bufLen});
@@ -249,7 +249,7 @@ class TestFlowController : public org::apache::nifi::minifi::FlowController {
 
   ~TestFlowController() override = default;
 
-  void load(const std::shared_ptr<org::apache::nifi::minifi::core::ProcessGroup>& /*root*/ = nullptr, bool /*reload*/ = false) override {
+  void load(std::unique_ptr<org::apache::nifi::minifi::core::ProcessGroup> /*root*/ = nullptr, bool /*reload*/ = false) override {
   }
 
   int16_t start() override {
diff --git a/main/MiNiFiMain.cpp b/main/MiNiFiMain.cpp
index 4763423..e90b866 100644
--- a/main/MiNiFiMain.cpp
+++ b/main/MiNiFiMain.cpp
@@ -311,7 +311,7 @@ int main(int argc, char **argv) {
       prov_repo, flow_repo, content_repo, configure, stream_factory, nifi_configuration_class_name,
       configure->get(minifi::Configure::nifi_flow_configuration_file), filesystem);
 
-  const auto controller = std::make_shared<minifi::FlowController>(
+  const auto controller = std::make_unique<minifi::FlowController>(
       prov_repo, flow_repo, configure, std::move(flow_configuration), content_repo, filesystem);
 
   const bool disk_space_watchdog_enable = (configure->get(minifi::Configure::minifi_disk_space_watchdog_enable) | utils::map([](const std::string& v){ return v == "true"; })).value_or(true);
diff --git a/nanofi/include/cxx/C2CallbackAgent.h b/nanofi/include/cxx/C2CallbackAgent.h
index 2d4dd54..e2d5853 100644
--- a/nanofi/include/cxx/C2CallbackAgent.h
+++ b/nanofi/include/cxx/C2CallbackAgent.h
@@ -49,7 +49,7 @@ class C2CallbackAgent : public c2::C2Agent {
   explicit C2CallbackAgent(
       core::controller::ControllerServiceProvider* controller,
       state::Pausable* pause_handler,
-      const std::shared_ptr<state::StateMonitor> &updateSink,
+      state::StateMonitor* updateSink,
       const std::shared_ptr<Configure> &configure);
 
   ~C2CallbackAgent() override = default;
diff --git a/nanofi/include/cxx/Instance.h b/nanofi/include/cxx/Instance.h
index 6196c6b..8f310a4 100644
--- a/nanofi/include/cxx/Instance.h
+++ b/nanofi/include/cxx/Instance.h
@@ -85,7 +85,7 @@ class Instance {
     utils::Identifier uuid;
     uuid = port;
     rpg_ = std::make_shared<minifi::RemoteProcessorGroupPort>(stream_factory_, url, url, configure_, uuid);
-    proc_node_ = std::make_shared<core::ProcessorNode>(rpg_);
+    proc_node_ = std::make_shared<core::ProcessorNode>(rpg_.get());
     core::extension::ExtensionManager::get().initialize(configure_);
     content_repo_->initialize(configure_);
   }
diff --git a/nanofi/include/cxx/Plan.h b/nanofi/include/cxx/Plan.h
index 3079967..6914ba5 100644
--- a/nanofi/include/cxx/Plan.h
+++ b/nanofi/include/cxx/Plan.h
@@ -207,7 +207,7 @@ class ExecutionPlan {
 
   std::shared_ptr<minifi::Connection> buildFinalConnection(std::shared_ptr<core::Processor> processor, bool set_dst = false);
 
-  std::shared_ptr<minifi::Connection> connectProcessors(std::shared_ptr<core::Processor> src_proc, std::shared_ptr<core::Processor> dst_proc,
+  std::unique_ptr<minifi::Connection> connectProcessors(std::shared_ptr<core::Processor> src_proc, std::shared_ptr<core::Processor> dst_proc,
                                                         core::Relationship relationship = core::Relationship("success", "description"), bool set_dst = false);
 
   std::shared_ptr<org::apache::nifi::minifi::io::StreamFactory> stream_factory;
diff --git a/nanofi/src/api/nanofi.cpp b/nanofi/src/api/nanofi.cpp
index f2bd8d9..0cd129b 100644
--- a/nanofi/src/api/nanofi.cpp
+++ b/nanofi/src/api/nanofi.cpp
@@ -179,7 +179,7 @@ void get_proc_uuid_from_processor(standalone_processor * proc, char * uuid_targe
 }
 
 void get_proc_uuid_from_context(const processor_context * ctx, char * uuid_target) {
-    standalone_processor * proc = static_cast<standalone_processor*>(ctx->getProcessorNode()->getProcessor().get());
+    standalone_processor * proc = static_cast<standalone_processor*>(ctx->getProcessorNode()->getProcessor());
     get_proc_uuid_from_processor(proc, uuid_target);
 }
 
diff --git a/nanofi/src/cxx/C2CallbackAgent.cpp b/nanofi/src/cxx/C2CallbackAgent.cpp
index 31710a2..9a7c755 100644
--- a/nanofi/src/cxx/C2CallbackAgent.cpp
+++ b/nanofi/src/cxx/C2CallbackAgent.cpp
@@ -34,7 +34,7 @@ namespace nifi {
 namespace minifi {
 namespace c2 {
 
-C2CallbackAgent::C2CallbackAgent(core::controller::ControllerServiceProvider* controller, state::Pausable* pause_handler, const std::shared_ptr<state::StateMonitor> &updateSink,
+C2CallbackAgent::C2CallbackAgent(core::controller::ControllerServiceProvider* controller, state::Pausable* pause_handler, state::StateMonitor* updateSink,
                                  const std::shared_ptr<Configure> &configuration)
     : C2Agent(controller, pause_handler, updateSink, configuration),
       stop(nullptr) {
diff --git a/nanofi/src/cxx/Plan.cpp b/nanofi/src/cxx/Plan.cpp
index 55816c4..3e61d23 100644
--- a/nanofi/src/cxx/Plan.cpp
+++ b/nanofi/src/cxx/Plan.cpp
@@ -18,6 +18,7 @@
 
 #include "cxx/Plan.h"
 #include "cxx/CallbackProcessor.h"
+#include "core/ProcessSessionFactory.h"
 #include <memory>
 #include <vector>
 #include <set>
@@ -107,7 +108,7 @@ std::shared_ptr<core::Processor> ExecutionPlan::addProcessor(const std::shared_p
     relationships_.push_back(connectProcessors(last, processor, relationship, true));
   }
 
-  std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(processor);
+  auto node = std::make_shared<core::ProcessorNode>(processor.get());
 
   processor_nodes_.push_back(node);
 
@@ -221,7 +222,7 @@ void ExecutionPlan::finalize() {
       }
     }
 
-    std::shared_ptr<core::ProcessorNode> node = std::make_shared<core::ProcessorNode>(failure_proc);
+    auto node = std::make_shared<core::ProcessorNode>(failure_proc.get());
 
     processor_nodes_.push_back(node);
 
@@ -266,7 +267,7 @@ std::shared_ptr<core::Processor> ExecutionPlan::createProcessor(const std::strin
   }
 
 
-  auto ptr = core::ClassLoader::getDefaultClassLoader().instantiate(processor_name, uuid);
+  std::shared_ptr<core::CoreComponent> ptr = core::ClassLoader::getDefaultClassLoader().instantiate(processor_name, uuid);
   if (nullptr == ptr) {
     return nullptr;
   }
@@ -289,25 +290,25 @@ std::shared_ptr<core::Processor> ExecutionPlan::createCallback(void *obj,
   return ptr;
 }
 
-std::shared_ptr<minifi::Connection> ExecutionPlan::connectProcessors(std::shared_ptr<core::Processor> src_proc, std::shared_ptr<core::Processor> dst_proc, core::Relationship relationship,
+std::unique_ptr<minifi::Connection> ExecutionPlan::connectProcessors(std::shared_ptr<core::Processor> src_proc, std::shared_ptr<core::Processor> dst_proc, core::Relationship relationship,
                                                                      bool set_dst) {
   std::stringstream connection_name;
   connection_name << src_proc->getUUIDStr() << "-to-" << dst_proc->getUUIDStr();
-  std::shared_ptr<minifi::Connection> connection = std::make_shared<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
+  auto connection = std::make_unique<minifi::Connection>(flow_repo_, content_repo_, connection_name.str());
   connection->addRelationship(relationship);
 
   // link the connections so that we can test results at the end for this
-  connection->setSource(src_proc);
+  connection->setSource(src_proc.get());
 
   connection->setSourceUUID(src_proc->getUUID());
   if (set_dst) {
-    connection->setDestination(dst_proc);
+    connection->setDestination(dst_proc.get());
     connection->setDestinationUUID(dst_proc->getUUID());
     if (src_proc != dst_proc) {
-      dst_proc->addConnection(connection);
+      dst_proc->addConnection(connection.get());
     }
   }
-  src_proc->addConnection(connection);
+  src_proc->addConnection(connection.get());
 
   return connection;
 }