This is an automated email from the ASF dual-hosted git repository.
martinzink pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
The following commit(s) were added to refs/heads/main by this push:
new 45eca0ceb MINIFICPP-2816 Add controller_service::api_implementations
to C api (#2176)
45eca0ceb is described below
commit 45eca0ceb2d4ccb6d23656aac75591228710f666
Author: Martin Zink <[email protected]>
AuthorDate: Wed Jun 24 14:25:51 2026 +0200
MINIFICPP-2816 Add controller_service::api_implementations to C api (#2176)
---
.clang-format | 4 +-
.../ubuntu_22_04_clang_arm_manifest.json | 93 +++++++++++++++++++
.github/workflows/ci.yml | 6 +-
core-framework/include/core/ObjectFactory.h | 12 +--
.../core/controller/ControllerServiceFactoryImpl.h | 10 +--
.../cpp-extension-lib/include/api/core/Resource.h | 23 +++++
.../AnimalControllerServiceApis.h | 28 +++---
.../AnimalControllerServices.cpp | 25 +++---
.../stable-api-testing/AnimalControllerServices.h | 69 ++++++++++++++
extensions/stable-api-testing/CMakeLists.txt | 31 +++++++
.../stable-api-testing/ExtensionInitializer.cpp | 38 ++++++++
extensions/stable-api-testing/ZooProcessor.cpp | 46 ++++++++++
extensions/stable-api-testing/ZooProcessor.h | 65 ++++++++++++++
extensions/stable-api-testing/tests/CMakeLists.txt | 35 ++++++++
extensions/stable-api-testing/tests/ZooTests.cpp | 69 ++++++++++++++
.../standard-processors/controllers/XMLReader.cpp | 3 +-
.../include/core/state/nodes/AgentInformation.h | 2 -
libminifi/src/core/ClassLoader.cpp | 66 +++++++-------
.../src/core/state/nodes/AgentInformation.cpp | 100 +++++++++++++++------
libminifi/src/minifi-c.cpp | 38 +++++---
libminifi/test/unit/ComponentManifestTests.cpp | 62 ++++++++++---
.../core/ProvidedControllerServiceInterface.h | 48 ++++++++++
minifi-api/include/minifi-c/minifi-c.h | 3 +
.../minifi-cpp/controllers/RecordSetReader.h | 9 +-
minifi-api/include/minifi-cpp/core/ClassLoader.h | 2 +-
.../minifi-cpp/core/ControllerServiceType.h | 19 +++-
minifi-api/include/minifi-cpp/core/ObjectFactory.h | 2 +-
.../core/controller/ControllerServiceFactory.h | 2 +-
28 files changed, 764 insertions(+), 146 deletions(-)
diff --git a/.clang-format b/.clang-format
index 1207baf97..013a12279 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,6 +1,6 @@
BasedOnStyle: Google
AccessModifierOffset: -1
-AlignAfterOpenBracket: DontAlign
+AlignAfterOpenBracket: false
AlignConsecutiveAssignments: None
AlignOperands: DontAlign
AllowAllParametersOfDeclarationOnNextLine: true
@@ -31,7 +31,7 @@ MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
-PenaltyIndentedWhitespace: 1
+PenaltyIndentedWhitespace: 10
PointerAlignment: Left
ReferenceAlignment: Left
ReflowComments: true
diff --git a/.github/references/ubuntu_22_04_clang_arm_manifest.json
b/.github/references/ubuntu_22_04_clang_arm_manifest.json
index 976ba021b..8cabb5440 100644
--- a/.github/references/ubuntu_22_04_clang_arm_manifest.json
+++ b/.github/references/ubuntu_22_04_clang_arm_manifest.json
@@ -10860,6 +10860,52 @@
"supportsDynamicRelationships": "false",
"supportsDynamicProperties": "true",
"type": "org.apache.nifi.minifi.processors.UpdateAttribute"
+ },
+ {
+ "propertyDescriptors": {
+ "Can fly service": {
+ "typeProvidedByValue": {
+ "type":
"org.apache.nifi.minifi.api_testing.CanFlyControllerApi",
+ "group": "org.apache.nifi.minifi",
+ "artifact": "minifi-stable-api-testing"
+ },
+ "name": "Can fly service",
+ "description": "Test CanFlyService",
+ "validator": "VALID",
+ "required": "true",
+ "sensitive": "false",
+ "expressionLanguageScope": "NONE"
+ },
+ "Number of legs service": {
+ "typeProvidedByValue": {
+ "type":
"org.apache.nifi.minifi.api_testing.NumberOfLegsControllerApi",
+ "group": "org.apache.nifi.minifi",
+ "artifact": "minifi-stable-api-testing"
+ },
+ "name": "Number of legs service",
+ "description": "Test NumberOfLegsService",
+ "validator": "VALID",
+ "required": "true",
+ "sensitive": "false",
+ "expressionLanguageScope": "NONE"
+ }
+ },
+ "inputRequirement": "INPUT_FORBIDDEN",
+ "isSingleThreaded": "true",
+ "supportedRelationships": [
+ {
+ "name": "failure",
+ "description": "failure"
+ },
+ {
+ "name": "success",
+ "description": "success"
+ }
+ ],
+ "typeDescription": "Test ZooProcessor",
+ "supportsDynamicRelationships": "false",
+ "supportsDynamicProperties": "false",
+ "type": "org.apache.nifi.minifi.api_testing.ZooProcessor"
}
],
"controllerServices": [
@@ -11019,6 +11065,53 @@
"supportsDynamicProperties": "false",
"type":
"org.apache.nifi.minifi.couchbase.controllers.CouchbaseClusterService"
},
+ {
+ "propertyDescriptors": {
+ "Has Jetpack": {
+ "name": "Has Jetpack",
+ "description": "Whether or not the dog has a jetpack",
+ "validator": "BOOLEAN_VALIDATOR",
+ "required": "false",
+ "sensitive": "false",
+ "expressionLanguageScope": "NONE",
+ "defaultValue": "false"
+ }
+ },
+ "typeDescription": "Test DogController",
+ "supportsDynamicRelationships": "false",
+ "supportsDynamicProperties": "false",
+ "type": "org.apache.nifi.minifi.api_testing.DogController",
+ "providedApiImplementations": [
+ {
+ "artifact": "minifi-system",
+ "group": "org.apache.nifi.minifi",
+ "type":
"org.apache.nifi.minifi.api_testing.CanFlyControllerApi"
+ },
+ {
+ "artifact": "minifi-system",
+ "group": "org.apache.nifi.minifi",
+ "type":
"org.apache.nifi.minifi.api_testing.NumberOfLegsControllerApi"
+ }
+ ]
+ },
+ {
+ "typeDescription": "Test DuckController",
+ "supportsDynamicRelationships": "false",
+ "supportsDynamicProperties": "false",
+ "type": "org.apache.nifi.minifi.api_testing.DuckController",
+ "providedApiImplementations": [
+ {
+ "artifact": "minifi-system",
+ "group": "org.apache.nifi.minifi",
+ "type":
"org.apache.nifi.minifi.api_testing.CanFlyControllerApi"
+ },
+ {
+ "artifact": "minifi-system",
+ "group": "org.apache.nifi.minifi",
+ "type":
"org.apache.nifi.minifi.api_testing.NumberOfLegsControllerApi"
+ }
+ ]
+ },
{
"propertyDescriptors": {
"API Key": {
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8fa667fa8..c1d5f8896 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -52,7 +52,7 @@ jobs:
-DENABLE_SFTP=ON
-DENABLE_SPLUNK=ON
-DENABLE_SQL=ON
- -DENABLE_TEST_PROCESSORS=OFF
+ -DENABLE_TEST_PROCESSORS=ON
-DFORCE_COLORED_OUTPUT=OFF
-DLIBC_STATIC=OFF
-DMINIFI_ADVANCED_ASAN_BUILD=OFF
@@ -159,7 +159,7 @@ jobs:
-DENABLE_SMB=ON
-DENABLE_SPLUNK=ON
-DENABLE_SQL=ON
- -DENABLE_TEST_PROCESSORS=OFF
+ -DENABLE_TEST_PROCESSORS=ON
-DENABLE_WEL=ON
-DFORCE_COLORED_OUTPUT=ON
-DINSTALLER_MERGE_MODULES=OFF
@@ -261,7 +261,7 @@ jobs:
-DENABLE_SPLUNK=ON
-DENABLE_SQL=ON
-DENABLE_SYSTEMD=ON
- -DENABLE_TEST_PROCESSORS=OFF
+ -DENABLE_TEST_PROCESSORS=ON
-DFORCE_COLORED_OUTPUT=ON
-DMINIFI_FAIL_ON_WARNINGS=ON
-DPORTABLE=ON
diff --git a/core-framework/include/core/ObjectFactory.h
b/core-framework/include/core/ObjectFactory.h
index dda11ab96..e8ebb43dd 100644
--- a/core-framework/include/core/ObjectFactory.h
+++ b/core-framework/include/core/ObjectFactory.h
@@ -27,16 +27,16 @@ namespace org::apache::nifi::minifi::core {
class ObjectFactoryImpl : public ObjectFactory {
public:
- explicit ObjectFactoryImpl(std::string group) : group_(std::move(group)) {}
+ explicit ObjectFactoryImpl(std::string module_name) :
module_name_(std::move(module_name)) {}
ObjectFactoryImpl() = default;
- std::string getGroupName() const override {
- return group_;
+ std::string getModuleName() const override {
+ return module_name_;
}
protected:
- std::string group_;
+ std::string module_name_;
};
/**
@@ -50,8 +50,8 @@ class DefaultObjectFactory : public ObjectFactoryImpl {
: className(core::className<T>()) {
}
- explicit DefaultObjectFactory(std::string group_name)
- : ObjectFactoryImpl(std::move(group_name)),
+ explicit DefaultObjectFactory(std::string module_name)
+ : ObjectFactoryImpl(std::move(module_name)),
className(core::className<T>()) {
}
diff --git
a/core-framework/include/core/controller/ControllerServiceFactoryImpl.h
b/core-framework/include/core/controller/ControllerServiceFactoryImpl.h
index a30bd48c6..32f1525a2 100644
--- a/core-framework/include/core/controller/ControllerServiceFactoryImpl.h
+++ b/core-framework/include/core/controller/ControllerServiceFactoryImpl.h
@@ -34,13 +34,13 @@ class ControllerServiceFactoryImpl : public
ControllerServiceFactory {
: class_name_(core::className<T>()) {
}
- explicit ControllerServiceFactoryImpl(std::string group_name)
- : group_name_(std::move(group_name)),
+ explicit ControllerServiceFactoryImpl(std::string module_name)
+ : module_name_(std::move(module_name)),
class_name_(core::className<T>()) {
}
- std::string getGroupName() const override {
- return group_name_;
+ std::string getModuleName() const override {
+ return module_name_;
}
std::unique_ptr<ControllerServiceApi> create(ControllerServiceMetadata
metadata) override {
@@ -52,7 +52,7 @@ class ControllerServiceFactoryImpl : public
ControllerServiceFactory {
}
protected:
- std::string group_name_;
+ std::string module_name_;
std::string_view class_name_;
};
diff --git a/extension-framework/cpp-extension-lib/include/api/core/Resource.h
b/extension-framework/cpp-extension-lib/include/api/core/Resource.h
index 60766741c..b121f0197 100644
--- a/extension-framework/cpp-extension-lib/include/api/core/Resource.h
+++ b/extension-framework/cpp-extension-lib/include/api/core/Resource.h
@@ -154,12 +154,22 @@ void useControllerServiceClassDefinition(Fn&& fn) {
const auto full_name = minifi::core::className<Class>();
std::vector<MinifiPropertyDefinition> class_properties =
utils::toProperties(Class::Properties, string_vector_cache);
+ std::vector<MinifiStringView> provided_interfaces;
+ if constexpr (requires { Class::ProvidedInterfaces; }) {
+ provided_interfaces.reserve(Class::ProvidedInterfaces.size());
+ for (const auto& iface : Class::ProvidedInterfaces) {
+ provided_interfaces.push_back(utils::minifiStringView(iface.name));
+ }
+ }
MinifiControllerServiceClassDefinition definition{.full_name =
utils::minifiStringView(full_name),
.description = utils::minifiStringView(Class::Description),
.class_properties_count = gsl::narrow<uint32_t>(class_properties.size()),
.class_properties_ptr = class_properties.data(),
+ .provided_interfaces_count =
gsl::narrow<uint32_t>(provided_interfaces.size()),
+ .provided_interfaces_ptr = provided_interfaces.data(),
+
.callbacks = MinifiControllerServiceCallbacks{
.create = [](MinifiControllerServiceMetadata metadata) ->
MINIFI_OWNED void* {
try {
@@ -181,6 +191,19 @@ void useControllerServiceClassDefinition(Fn&& fn) {
static_cast<Class*>(self)->disable();
} catch (...) {}
},
+ .get_interface = [](void* self, MinifiStringView interface_name) ->
void* {
+ try {
+ if constexpr (requires { Class::ProvidedInterfaces; }) {
+ const std::string_view name_view{interface_name.data,
interface_name.length};
+ for (const auto& iface : Class::ProvidedInterfaces) {
+ if (iface.name == name_view) {
+ return iface.cast(self);
+ }
+ }
+ }
+ return nullptr;
+ } catch (...) { return nullptr; }
+ }
}};
fn(definition);
diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
b/extensions/stable-api-testing/AnimalControllerServiceApis.h
similarity index 58%
copy from minifi-api/include/minifi-cpp/core/ControllerServiceType.h
copy to extensions/stable-api-testing/AnimalControllerServiceApis.h
index 6d5b39de3..49c45cee0 100644
--- a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
+++ b/extensions/stable-api-testing/AnimalControllerServiceApis.h
@@ -1,5 +1,5 @@
/**
-* Licensed to the Apache Software Foundation (ASF) under one or more
+ * 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
@@ -14,22 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-#include <string>
-#include "minifi-cpp/core/ControllerServiceTypeDefinition.h"
+#pragma once
-namespace org::apache::nifi::minifi::core {
+#include <cinttypes>
-struct ControllerServiceType {
- std::string artifact;
- std::string group;
- std::string type;
+namespace org::apache::nifi::minifi::api_testing {
+class NumberOfLegsControllerApi {
+ public:
+ virtual ~NumberOfLegsControllerApi() = default;
+ virtual uint8_t numberOfLegs() const = 0;
+};
- ControllerServiceType(const ControllerServiceTypeDefinition& definition) //
NOLINT(runtime/explicit)
- : artifact(definition.artifact),
- group(definition.group),
- type(definition.type) {}
+class CanFlyControllerApi {
+ public:
+ virtual ~CanFlyControllerApi() = default;
+ virtual bool canFly() const = 0;
};
-} // namespace org::apache::nifi::minifi::core
+} // namespace org::apache::nifi::minifi::api_testing
diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
b/extensions/stable-api-testing/AnimalControllerServices.cpp
similarity index 56%
copy from minifi-api/include/minifi-cpp/core/ControllerServiceType.h
copy to extensions/stable-api-testing/AnimalControllerServices.cpp
index 6d5b39de3..f05ab6eea 100644
--- a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
+++ b/extensions/stable-api-testing/AnimalControllerServices.cpp
@@ -1,5 +1,5 @@
/**
-* Licensed to the Apache Software Foundation (ASF) under one or more
+ * 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
@@ -14,22 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-#include <string>
-#include "minifi-cpp/core/ControllerServiceTypeDefinition.h"
+#include "AnimalControllerServices.h"
-namespace org::apache::nifi::minifi::core {
+#include "api/utils/ProcessorConfigUtils.h"
+namespace org::apache::nifi::minifi::api_testing {
-struct ControllerServiceType {
- std::string artifact;
- std::string group;
- std::string type;
+MinifiStatus DogController::enableImpl(api::core::ControllerServiceContext&
ctx) {
+ this->has_jetpack_ = ctx.getProperty(HasJetpack) |
minifi::utils::andThen(parsing::parseBool) |
+ minifi::utils::orThrow(fmt::format("Expected parsable bool from \"{}\"",
HasJetpack.name));
- ControllerServiceType(const ControllerServiceTypeDefinition& definition) //
NOLINT(runtime/explicit)
- : artifact(definition.artifact),
- group(definition.group),
- type(definition.type) {}
-};
+ return MINIFI_STATUS_SUCCESS;
+}
-} // namespace org::apache::nifi::minifi::core
+} // namespace org::apache::nifi::minifi::api_testing
diff --git a/extensions/stable-api-testing/AnimalControllerServices.h
b/extensions/stable-api-testing/AnimalControllerServices.h
new file mode 100644
index 000000000..6a6e1e78e
--- /dev/null
+++ b/extensions/stable-api-testing/AnimalControllerServices.h
@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+#pragma once
+
+#include "AnimalControllerServiceApis.h"
+#include "api/core/ControllerServiceImpl.h"
+#include "api/utils/Export.h"
+#include "core/PropertyDefinitionBuilder.h"
+#include "minifi-cpp/core/ProvidedControllerServiceInterface.h"
+
+namespace org::apache::nifi::minifi::api_testing {
+/// DogController and DuckController are testing that one ControllerService
type can implement multiple interfaces
+class DogController : public api::core::ControllerServiceImpl, public
CanFlyControllerApi, public NumberOfLegsControllerApi {
+ public:
+ EXTENSIONAPI static constexpr const char* Description = "Test DogController";
+ EXTENSIONAPI static constexpr auto HasJetpack =
+ core::PropertyDefinitionBuilder<>::createProperty("Has Jetpack")
+ .withDescription("Whether or not the dog has a jetpack")
+ .withDefaultValue("false")
+ .withValidator(core::StandardPropertyValidators::BOOLEAN_VALIDATOR)
+ .build();
+
+ EXTENSIONAPI static constexpr auto Properties =
std::to_array<core::PropertyReference>({
+ HasJetpack,
+ });
+ EXTENSIONAPI static constexpr auto ProvidedInterfaces =
+
std::to_array<core::ProvidedInterface>({core::createProvidedInterface<CanFlyControllerApi,
DogController>(),
+ core::createProvidedInterface<NumberOfLegsControllerApi,
DogController>()});
+
+ using ControllerServiceImpl::ControllerServiceImpl;
+ MinifiStatus enableImpl(api::core::ControllerServiceContext& ctx) override;
+
+ uint8_t numberOfLegs() const override { return 4; }
+ bool canFly() const override { return has_jetpack_; }
+
+ private:
+ bool has_jetpack_ = false;
+};
+
+class DuckController : public api::core::ControllerServiceImpl, public
CanFlyControllerApi, public NumberOfLegsControllerApi {
+ public:
+ EXTENSIONAPI static constexpr const char* Description = "Test
DuckController";
+
+ EXTENSIONAPI static constexpr std::array<core::PropertyReference, 0>
Properties = {};
+ EXTENSIONAPI static constexpr auto ProvidedInterfaces =
+
std::to_array<core::ProvidedInterface>({core::createProvidedInterface<CanFlyControllerApi,
DuckController>(),
+ core::createProvidedInterface<NumberOfLegsControllerApi,
DuckController>()});
+ using ControllerServiceImpl::ControllerServiceImpl;
+ MinifiStatus enableImpl(api::core::ControllerServiceContext&) override {
return MINIFI_STATUS_SUCCESS; }
+
+ uint8_t numberOfLegs() const override { return 2; }
+ bool canFly() const override { return true; }
+};
+} // namespace org::apache::nifi::minifi::api_testing
diff --git a/extensions/stable-api-testing/CMakeLists.txt
b/extensions/stable-api-testing/CMakeLists.txt
new file mode 100644
index 000000000..1f3a8e0de
--- /dev/null
+++ b/extensions/stable-api-testing/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.
+#
+
+if (NOT ENABLE_TEST_PROCESSORS)
+ return()
+endif ()
+
+include(${CMAKE_SOURCE_DIR}/extensions/ExtensionHeader.txt)
+file(GLOB SOURCES "*.cpp")
+
+add_minifi_library(minifi-stable-api-testing SHARED ${SOURCES})
+
+target_link_libraries(minifi-stable-api-testing minifi-cpp-extension-lib)
+
+register_c_api_extension(minifi-stable-api-testing "Stable API Sandbox"
SANDBOX-EXTENSION "Stable API Sandbox" "extensions/stable-api-testing/tests")
diff --git a/extensions/stable-api-testing/ExtensionInitializer.cpp
b/extensions/stable-api-testing/ExtensionInitializer.cpp
new file mode 100644
index 000000000..dae253407
--- /dev/null
+++ b/extensions/stable-api-testing/ExtensionInitializer.cpp
@@ -0,0 +1,38 @@
+/**
+ * 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 "AnimalControllerServices.h"
+#include "ZooProcessor.h"
+#include "api/core/Resource.h"
+#include "api/utils/minifi-c-utils.h"
+
+#define MKSOC(x) #x
+#define MAKESTRING(x) MKSOC(x) // NOLINT(cppcoreguidelines-macro-usage)
+
+namespace minifi = org::apache::nifi::minifi;
+
+CEXTENSIONAPI const uint32_t MinifiApiVersion = MINIFI_API_VERSION;
+
+CEXTENSIONAPI void MinifiInitExtension(MinifiExtensionContext*
extension_context) {
+ const MinifiExtensionDefinition extension_definition{.name =
minifi::api::utils::minifiStringView(MAKESTRING(EXTENSION_NAME)),
+ .version =
minifi::api::utils::minifiStringView(MAKESTRING(EXTENSION_VERSION)),
+ .deinit = nullptr,
+ .user_data = nullptr};
+ auto* extension = MinifiRegisterExtension(extension_context,
&extension_definition);
+
minifi::api::core::registerProcessors<minifi::api_testing::ZooProcessor>(extension);
+
minifi::api::core::registerControllerServices<minifi::api_testing::DogController,
minifi::api_testing::DuckController>(extension);
+}
diff --git a/extensions/stable-api-testing/ZooProcessor.cpp
b/extensions/stable-api-testing/ZooProcessor.cpp
new file mode 100644
index 000000000..79314c75b
--- /dev/null
+++ b/extensions/stable-api-testing/ZooProcessor.cpp
@@ -0,0 +1,46 @@
+/**
+ * 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 "ZooProcessor.h"
+
+#include "AnimalControllerServices.h"
+#include "api/core/ProcessContext.h"
+
+namespace org::apache::nifi::minifi::api_testing {
+
+MinifiStatus ZooProcessor::onTriggerImpl(api::core::ProcessContext&
process_context, api::core::ProcessSession& process_session) {
+ if (const auto can_fly_opaque =
process_context.getControllerService(CanFlyService)) {
+ if (*can_fly_opaque) {
+ const auto can_fly_controller_name =
process_context.getProperty(CanFlyService, nullptr) | utils::orThrow("Should be
here");
+ const CanFlyControllerApi* const can_fly =
reinterpret_cast<CanFlyControllerApi*>(*can_fly_opaque);
+ logger_->log_critical("Can {} fly? {}", can_fly_controller_name,
can_fly->canFly());
+ }
+ }
+ if (const auto num_of_legs_opaque =
process_context.getControllerService(NumberOfLegsService)) {
+ if (*num_of_legs_opaque) {
+ const auto num_of_legs_name =
process_context.getProperty(NumberOfLegsService, nullptr) |
utils::orThrow("Should be here");
+ const NumberOfLegsControllerApi* const num_legs =
reinterpret_cast<NumberOfLegsControllerApi*>(*num_of_legs_opaque);
+ logger_->log_critical("{} has {} legs", num_of_legs_name,
num_legs->numberOfLegs());
+ }
+ }
+ return ProcessorImpl::onTriggerImpl(process_context, process_session);
+}
+
+MinifiStatus ZooProcessor::onScheduleImpl(api::core::ProcessContext&
process_context) {
+ return ProcessorImpl::onScheduleImpl(process_context);
+}
+} // namespace org::apache::nifi::minifi::api_testing
diff --git a/extensions/stable-api-testing/ZooProcessor.h
b/extensions/stable-api-testing/ZooProcessor.h
new file mode 100644
index 000000000..7c028b7d8
--- /dev/null
+++ b/extensions/stable-api-testing/ZooProcessor.h
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+#pragma once
+
+#include "AnimalControllerServiceApis.h"
+#include "api/core/ProcessorImpl.h"
+#include "api/utils/Export.h"
+#include "core/PropertyDefinitionBuilder.h"
+#include "minifi-cpp/core/Annotation.h"
+
+namespace org::apache::nifi::minifi::api_testing {
+
+class ZooProcessor : public api::core::ProcessorImpl {
+ public:
+ EXTENSIONAPI static constexpr const char* Description = "Test ZooProcessor";
+
+ EXTENSIONAPI static constexpr auto CanFlyService =
+ core::PropertyDefinitionBuilder<>::createProperty("Can fly service")
+ .withDescription("Test CanFlyService")
+ .isRequired(true)
+ .withAllowedTypes<CanFlyControllerApi>()
+ .build();
+
+ EXTENSIONAPI static constexpr auto NumberOfLegsService =
+ core::PropertyDefinitionBuilder<>::createProperty("Number of legs
service")
+ .withDescription("Test NumberOfLegsService")
+ .isRequired(true)
+ .withAllowedTypes<NumberOfLegsControllerApi>()
+ .build();
+
+ EXTENSIONAPI static constexpr auto Properties =
std::to_array<core::PropertyReference>({
+ CanFlyService,
+ NumberOfLegsService,
+ });
+ EXTENSIONAPI static constexpr auto Success =
core::RelationshipDefinition{"success", "success"};
+ EXTENSIONAPI static constexpr auto Failure =
core::RelationshipDefinition{"failure", "failure"};
+ EXTENSIONAPI static constexpr auto Relationships = std::array{Success,
Failure};
+ EXTENSIONAPI static constexpr bool SupportsDynamicProperties = false;
+ EXTENSIONAPI static constexpr bool SupportsDynamicRelationships = false;
+ EXTENSIONAPI static constexpr core::annotation::Input InputRequirement =
core::annotation::Input::INPUT_FORBIDDEN;
+ EXTENSIONAPI static constexpr bool IsSingleThreaded = true;
+
+ using ProcessorImpl::ProcessorImpl;
+
+ protected:
+ MinifiStatus onTriggerImpl(api::core::ProcessContext&,
api::core::ProcessSession&) override;
+ MinifiStatus onScheduleImpl(api::core::ProcessContext&) override;
+};
+
+} // namespace org::apache::nifi::minifi::api_testing
diff --git a/extensions/stable-api-testing/tests/CMakeLists.txt
b/extensions/stable-api-testing/tests/CMakeLists.txt
new file mode 100644
index 000000000..55614119c
--- /dev/null
+++ b/extensions/stable-api-testing/tests/CMakeLists.txt
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+file(GLOB SOURCES "*.cpp")
+
+SET(EXTENSIONS_TEST_COUNT 0)
+FOREACH (testfile ${SOURCES})
+ get_filename_component(testfilename "${testfile}" NAME_WE)
+ add_minifi_executable(${testfilename} "${testfile}")
+ target_include_directories(${testfilename} BEFORE PRIVATE
"${CMAKE_SOURCE_DIR}/libminifi/include")
+ target_include_directories(${testfilename} BEFORE PRIVATE
"${CMAKE_SOURCE_DIR}/extensions/stable-api-testing")
+ createTests(${testfilename})
+ target_link_libraries(${testfilename} Catch2WithMain)
+ target_link_libraries(${testfilename} minifi-stable-api-testing)
+ target_link_libraries(${testfilename} libminifi-c-unittest)
+
+ MATH(EXPR EXTENSIONS_TEST_COUNT "${EXTENSIONS_TEST_COUNT}+1")
+ add_test(NAME ${testfilename} COMMAND ${testfilename} WORKING_DIRECTORY
${TEST_DIR})
+ENDFOREACH ()
diff --git a/extensions/stable-api-testing/tests/ZooTests.cpp
b/extensions/stable-api-testing/tests/ZooTests.cpp
new file mode 100644
index 000000000..d1f8c1735
--- /dev/null
+++ b/extensions/stable-api-testing/tests/ZooTests.cpp
@@ -0,0 +1,69 @@
+/**
+ *
+ * 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 "../AnimalControllerServices.h"
+#include "CProcessorTestUtils.h"
+#include "ZooProcessor.h"
+#include "api/core/Resource.h"
+#include "minifi-cpp/core/FlowFile.h"
+#include "unit/Catch.h"
+#include "unit/SingleProcessorTestController.h"
+#include "unit/TestBase.h"
+#include "unit/TestUtils.h"
+#include "utils/CProcessor.h"
+
+namespace org::apache::nifi::minifi::api_testing::test {
+TEST_CASE("ZooTest") {
+ minifi::test::SingleProcessorTestController
controller(minifi::test::utils::make_custom_c_processor<ZooProcessor>(
+ core::ProcessorMetadata{utils::Identifier{}, "ZooProcessor",
logging::LoggerFactory<ZooProcessor>::getLogger()}));
+ const auto dog_with_jetpack =
minifi::test::utils::make_custom_c_controller_service<DogController>(
+ core::ControllerServiceMetadata{utils::Identifier{}, "DogController",
logging::LoggerFactory<DogController>::getLogger()});
+ auto dog_with_jetpack_node =
controller.plan->addController("dog_with_jetpack", dog_with_jetpack);
+ CHECK(dog_with_jetpack->setProperty(DogController::HasJetpack.name, "true"));
+
+ const auto duck =
minifi::test::utils::make_custom_c_controller_service<DuckController>(core::ControllerServiceMetadata{utils::Identifier{},
+ "DuckController",
+ logging::LoggerFactory<DuckController>::getLogger()});
+ auto duck_node = controller.plan->addController("duck", duck);
+
+ {
+
CHECK(controller.getProcessor()->setProperty(ZooProcessor::CanFlyService.name,
"dog_with_jetpack"));
+
CHECK(controller.getProcessor()->setProperty(ZooProcessor::NumberOfLegsService.name,
"duck"));
+ controller.trigger();
+ CHECK(LogTestController::getInstance()
+ .contains("[org::apache::nifi::minifi::api_testing::ZooProcessor]
[critical] Can dog_with_jetpack fly? true"));
+
CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_testing::ZooProcessor]
[critical] duck has 2 legs"));
+ }
+ {
+ LogTestController::getInstance().clear();
+
CHECK(controller.getProcessor()->setProperty(ZooProcessor::CanFlyService.name,
"duck"));
+
CHECK(controller.getProcessor()->setProperty(ZooProcessor::NumberOfLegsService.name,
"dog_with_jetpack"));
+ controller.trigger();
+
CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_testing::ZooProcessor]
[critical] Can duck fly? true"));
+
CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_testing::ZooProcessor]
[critical] dog_with_jetpack has 4 legs"));
+ }
+ {
+ LogTestController::getInstance().clear();
+
CHECK(controller.getProcessor()->setProperty(ZooProcessor::CanFlyService.name,
"duck"));
+
CHECK(controller.getProcessor()->setProperty(ZooProcessor::NumberOfLegsService.name,
"invalid"));
+ controller.trigger();
+
CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_testing::ZooProcessor]
[critical] Can duck fly? true"));
+ }
+}
+
+} // namespace org::apache::nifi::minifi::api_testing::test
diff --git a/extensions/standard-processors/controllers/XMLReader.cpp
b/extensions/standard-processors/controllers/XMLReader.cpp
index 980ccc721..60f8a7cbb 100644
--- a/extensions/standard-processors/controllers/XMLReader.cpp
+++ b/extensions/standard-processors/controllers/XMLReader.cpp
@@ -21,8 +21,9 @@
#include <ranges>
#include "core/Resource.h"
-#include "utils/TimeUtil.h"
+#include "minifi-cpp/Exception.h"
#include "minifi-cpp/utils/gsl.h"
+#include "utils/TimeUtil.h"
namespace org::apache::nifi::minifi::standard {
diff --git a/libminifi/include/core/state/nodes/AgentInformation.h
b/libminifi/include/core/state/nodes/AgentInformation.h
index d76846b8e..89b238202 100644
--- a/libminifi/include/core/state/nodes/AgentInformation.h
+++ b/libminifi/include/core/state/nodes/AgentInformation.h
@@ -34,8 +34,6 @@
namespace org::apache::nifi::minifi::state::response {
-#define GROUP_STR "org.apache.nifi.minifi"
-
std::vector<SerializedResponseNode> serializeComponentManifest(const
Components& components);
class Bundles : public DeviceInformation {
diff --git a/libminifi/src/core/ClassLoader.cpp
b/libminifi/src/core/ClassLoader.cpp
index 463b2a2e4..ee97b3af9 100644
--- a/libminifi/src/core/ClassLoader.cpp
+++ b/libminifi/src/core/ClassLoader.cpp
@@ -18,14 +18,13 @@
#include "core/ClassLoader.h"
#include <memory>
+#include <ranges>
#include <string>
-#include "core/logging/LoggerFactory.h"
-#include "range/v3/action/sort.hpp"
-#include "range/v3/action/unique.hpp"
+#include "core/ObjectFactory.h"
#include "core/Processor.h"
#include "core/controller/ControllerService.h"
-#include "core/ObjectFactory.h"
+#include "core/logging/LoggerFactory.h"
namespace org::apache::nifi::minifi::core {
@@ -48,7 +47,7 @@ class ClassLoaderImpl : public ClassLoader {
void unregisterClass(const std::string& clazz) override;
- [[nodiscard]] std::optional<std::string> getGroupForClass(const std::string
&class_name) const override;
+ [[nodiscard]] std::optional<std::string> getModuleForClass(std::string_view
class_name) const override;
[[nodiscard]] std::unique_ptr<CoreComponent> instantiate(const std::string
&class_name, const std::string &name, std::function<bool(CoreComponent*)>
filter) override;
@@ -61,7 +60,7 @@ class ClassLoaderImpl : public ClassLoader {
~ClassLoaderImpl() override = default;
private:
- std::map<std::string, std::unique_ptr<ObjectFactory>> loaded_factories_;
+ std::map<std::string, std::unique_ptr<ObjectFactory>, std::less<>>
loaded_factories_;
std::map<std::string, ClassLoaderImpl> class_loaders_;
mutable std::mutex internal_mutex_;
std::shared_ptr<logging::Logger> logger_;
@@ -78,7 +77,7 @@ ClassLoader &ClassLoader::getDefaultClassLoader() {
}
ClassLoader& ClassLoaderImpl::getClassLoader(const std::string& child_name) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
auto it = class_loaders_.find(child_name);
if (it != class_loaders_.end()) {
return it->second;
@@ -95,7 +94,7 @@ ClassLoader& ClassLoaderImpl::getClassLoader(const
std::string& child_name) {
}
void ClassLoaderImpl::registerClass(const std::string &clazz,
std::unique_ptr<ObjectFactory> factory) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
if (loaded_factories_.contains(clazz)) {
logger_->log_error("Class '{}' is already registered at '{}'", clazz,
name_);
return;
@@ -125,10 +124,10 @@ class ProcessorFactoryWrapper : public ObjectFactoryImpl {
[[nodiscard]] gsl::owner<CoreComponent*> createRaw(const std::string &name,
const utils::Identifier &uuid) override {
auto logger = logging::LoggerFactoryBase::getAliasedLogger(getClassName(),
uuid);
- return new Processor(name, uuid, factory_->create({.uuid = uuid, .name =
name, .logger = std::move(logger)}));
+ return gsl::owner<CoreComponent*>{new Processor(name, uuid,
factory_->create({.uuid = uuid, .name = name, .logger = std::move(logger)}))};
}
- [[nodiscard]] std::string getGroupName() const override {
+ [[nodiscard]] std::string getModuleName() const override {
return factory_->getGroupName();
}
@@ -143,7 +142,7 @@ class ProcessorFactoryWrapper : public ObjectFactoryImpl {
class ControllerServiceFactoryWrapper : public ObjectFactoryImpl {
public:
explicit
ControllerServiceFactoryWrapper(std::unique_ptr<controller::ControllerServiceFactory>
factory)
- : ObjectFactoryImpl(factory->getGroupName()),
+ : ObjectFactoryImpl(factory->getModuleName()),
factory_(std::move(factory)) {}
[[nodiscard]] std::unique_ptr<CoreComponent> create(const std::string &name)
override {
@@ -160,11 +159,11 @@ class ControllerServiceFactoryWrapper : public
ObjectFactoryImpl {
[[nodiscard]] gsl::owner<CoreComponent*> createRaw(const std::string &name,
const utils::Identifier &uuid) override {
auto logger = logging::LoggerFactoryBase::getAliasedLogger(getClassName(),
uuid);
- return new controller::ControllerService(name, uuid,
factory_->create({.uuid = uuid, .name = name, .logger = std::move(logger)}));
+ return gsl::owner<CoreComponent*>{new controller::ControllerService(name,
uuid, factory_->create({.uuid = uuid, .name = name, .logger =
std::move(logger)}))};
}
- [[nodiscard]] std::string getGroupName() const override {
- return factory_->getGroupName();
+ [[nodiscard]] std::string getModuleName() const override {
+ return factory_->getModuleName();
}
[[nodiscard]] std::string getClassName() override {
@@ -186,7 +185,7 @@ void ClassLoaderImpl::registerClass(const std::string
&clazz, std::unique_ptr<co
}
void ClassLoaderImpl::unregisterClass(const std::string& clazz) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
if (loaded_factories_.erase(clazz) == 0) {
logger_->log_error("Could not unregister non-registered class '{}' at
'{}'", clazz, name_);
} else {
@@ -194,26 +193,25 @@ void ClassLoaderImpl::unregisterClass(const std::string&
clazz) {
}
}
-std::optional<std::string> ClassLoaderImpl::getGroupForClass(const std::string
&class_name) const {
- std::lock_guard<std::mutex> lock(internal_mutex_);
- for (const auto& child_loader : class_loaders_) {
- std::optional<std::string> group =
child_loader.second.getGroupForClass(class_name);
- if (group) {
+std::optional<std::string> ClassLoaderImpl::getModuleForClass(const
std::string_view class_name) const {
+ std::scoped_lock lock(internal_mutex_);
+ for (const auto &val : class_loaders_ | std::views::values) {
+ if (std::optional<std::string> group = val.getModuleForClass(class_name)) {
return group;
}
}
auto factory = loaded_factories_.find(class_name);
if (factory != loaded_factories_.end()) {
- return factory->second->getGroupName();
+ return factory->second->getModuleName();
}
return {};
}
std::unique_ptr<CoreComponent> ClassLoaderImpl::instantiate(const std::string
&class_name, const std::string &name, std::function<bool(CoreComponent*)>
filter) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
// allow subsequent classes to override functionality
- for (auto& child_loader : class_loaders_) {
- if (auto result = child_loader.second.instantiate(class_name, name,
filter)) {
+ for (auto &val : class_loaders_ | std::views::values) {
+ if (auto result = val.instantiate(class_name, name, filter)) {
return result;
}
}
@@ -228,10 +226,10 @@ std::unique_ptr<CoreComponent>
ClassLoaderImpl::instantiate(const std::string &c
}
std::unique_ptr<CoreComponent> ClassLoaderImpl::instantiate(const std::string
&class_name, const utils::Identifier &uuid, std::function<bool(CoreComponent*)>
filter) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
// allow subsequent classes to override functionality
- for (auto& child_loader : class_loaders_) {
- if (auto result = child_loader.second.instantiate(class_name, uuid,
filter)) {
+ for (auto &val : class_loaders_ | std::views::values) {
+ if (auto result = val.instantiate(class_name, uuid, filter)) {
return result;
}
}
@@ -246,10 +244,10 @@ std::unique_ptr<CoreComponent>
ClassLoaderImpl::instantiate(const std::string &c
}
std::unique_ptr<CoreComponent> ClassLoaderImpl::instantiate(const std::string
&class_name, const std::string &name, const utils::Identifier &uuid,
std::function<bool(CoreComponent*)> filter) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
// allow subsequent classes to override functionality
- for (auto& child_loader : class_loaders_) {
- if (auto result = child_loader.second.instantiate(class_name, name, uuid,
filter)) {
+ for (auto &val : class_loaders_ | std::views::values) {
+ if (auto result = val.instantiate(class_name, name, uuid, filter)) {
return result;
}
}
@@ -264,10 +262,10 @@ std::unique_ptr<CoreComponent>
ClassLoaderImpl::instantiate(const std::string &c
}
gsl::owner<CoreComponent*> ClassLoaderImpl::instantiateRaw(const std::string
&class_name, const std::string &name, std::function<bool(CoreComponent*)>
filter) {
- std::lock_guard<std::mutex> lock(internal_mutex_);
+ std::scoped_lock lock(internal_mutex_);
// allow subsequent classes to override functionality
- for (auto& child_loader : class_loaders_) {
- if (gsl::owner<CoreComponent*> result =
child_loader.second.instantiateRaw(class_name, name, filter)) {
+ for (auto &val : class_loaders_ | std::views::values) {
+ if (gsl::owner<CoreComponent*> result = val.instantiateRaw(class_name,
name, filter)) {
return result;
}
}
@@ -277,7 +275,7 @@ gsl::owner<CoreComponent*>
ClassLoaderImpl::instantiateRaw(const std::string &cl
if (filter(obj)) {
return obj;
}
- delete obj;
+ delete obj; // NOLINT(cppcoreguidelines-owning-memory)
}
return nullptr;
}
diff --git a/libminifi/src/core/state/nodes/AgentInformation.cpp
b/libminifi/src/core/state/nodes/AgentInformation.cpp
index a3165c588..1c73ee2a4 100644
--- a/libminifi/src/core/state/nodes/AgentInformation.cpp
+++ b/libminifi/src/core/state/nodes/AgentInformation.cpp
@@ -17,12 +17,18 @@
*/
#include "core/state/nodes/AgentInformation.h"
-#include "minifi-cpp/agent/agent_version.h"
-#include "core/Resource.h"
#include "core/ClassLoader.h"
-#include "utils/OsUtils.h"
+#include "core/Resource.h"
#include "core/state/nodes/SchedulingNodes.h"
#include "core/state/nodes/SupportedOperations.h"
+#include "minifi-c/minifi-c.h"
+#include "minifi-cpp/agent/agent_version.h"
+#include "minifi-cpp/controllers/AttributeProviderService.h"
+#include "minifi-cpp/controllers/ProxyConfigurationServiceInterface.h"
+#include "minifi-cpp/controllers/RecordSetReader.h"
+#include "minifi-cpp/controllers/RecordSetWriter.h"
+#include "minifi-cpp/controllers/SSLContextServiceInterface.h"
+#include "utils/OsUtils.h"
namespace org::apache::nifi::minifi::state::response {
@@ -30,33 +36,71 @@ utils::ProcessCpuUsageTracker
AgentStatus::cpu_load_tracker_;
std::mutex AgentStatus::cpu_load_tracker_mutex_;
namespace {
+
+std::string allowedTypeGroupName(const std::string_view allowed_type) {
+ constexpr std::string_view APACHE_GROUP_STR = "org.apache.nifi.minifi";
+ if (allowed_type.starts_with(APACHE_GROUP_STR)) {
+ return std::string{APACHE_GROUP_STR};
+ }
+ return std::string{allowed_type.substr(0, allowed_type.find_last_of('.'))};
+}
+
+constexpr std::string_view shortNameFromFullName(std::string_view sv) {
+ auto pos = sv.rfind('.');
+ return (pos == std::string_view::npos) ? sv : sv.substr(pos + 1);
+}
+
+bool minifiSystemAllowedType(const std::string_view allowed_type) {
+ return allowed_type ==
controllers::SSLContextServiceInterface::ProvidesApi.type
+ || allowed_type == core::RecordSetWriter::ProvidesApi.type
+ || allowed_type == core::RecordSetReader::ProvidesApi.type
+ || allowed_type ==
controllers::ProxyConfigurationServiceInterface::ProvidesApi.type
+ || allowed_type ==
controllers::AttributeProviderService::ProvidesApi.type;
+}
+
+std::string allowedTypeArtifactName(const std::string_view allowed_type, const
std::string_view prop_owner_type) {
+ if (minifiSystemAllowedType(allowed_type)) {
+ return "minifi-system";
+ }
+
+ auto& class_loader = core::ClassLoader::getDefaultClassLoader();
+
+ if (auto allowed_type_artifact =
class_loader.getModuleForClass(shortNameFromFullName(allowed_type))) {
+ return *allowed_type_artifact;
+ }
+ if (auto prop_owner_artifact =
class_loader.getModuleForClass(shortNameFromFullName(prop_owner_type))) {
+ return *prop_owner_artifact;
+ }
+
+ return "minifi-system";
+}
+
void serializeClassDescription(const std::vector<ClassDescription>&
descriptions, const std::string& name, SerializedResponseNode& response) {
if (descriptions.empty()) {
return;
}
SerializedResponseNode type{.name = name, .array = true};
std::vector<SerializedResponseNode> serialized;
- for (const auto& group : descriptions) {
- SerializedResponseNode desc{.name = group.full_name_};
+ for (const auto& class_description : descriptions) {
+ SerializedResponseNode desc{.name = class_description.full_name_};
- if (!group.class_properties_.empty()) {
+ if (!class_description.class_properties_.empty()) {
SerializedResponseNode props{.name = "propertyDescriptors"};
- for (auto&& prop : group.class_properties_) {
+ for (auto&& prop : class_description.class_properties_) {
SerializedResponseNode child = {.name = prop.getName()};
const auto &allowed_types = prop.getAllowedTypes();
if (!allowed_types.empty()) {
- SerializedResponseNode allowed_type;
- allowed_type.name = "typeProvidedByValue";
- for (const auto &type : allowed_types) {
- std::string class_name = utils::string::split(type, "::").back();
- std::string typeClazz = type;
+ SerializedResponseNode allowed_type_node;
+ allowed_type_node.name = "typeProvidedByValue";
+ for (const auto &allowed_type : allowed_types) {
+ std::string typeClazz = allowed_type;
utils::string::replaceAll(typeClazz, "::", ".");
- allowed_type.children.push_back({.name = "type", .value =
typeClazz});
- allowed_type.children.push_back({.name = "group", .value =
GROUP_STR});
- allowed_type.children.push_back({.name = "artifact", .value =
core::ClassLoader::getDefaultClassLoader().getGroupForClass(class_name).value_or("minifi-system")});
+ allowed_type_node.children.push_back({.name = "type", .value =
typeClazz});
+ allowed_type_node.children.push_back({.name = "group", .value =
allowedTypeGroupName(typeClazz)});
+ allowed_type_node.children.push_back({.name = "artifact", .value =
allowedTypeArtifactName(typeClazz, class_description.full_name_)});
}
- child.children.push_back(allowed_type);
+ child.children.push_back(allowed_type_node);
}
child.children.push_back({.name = "name", .value = prop.getName()});
@@ -99,12 +143,12 @@ void serializeClassDescription(const
std::vector<ClassDescription>& descriptions
}
// only for processors
- if (!group.class_relationships_.empty()) {
- desc.children.push_back({.name = "inputRequirement", .value =
group.inputRequirement_});
- desc.children.push_back({.name = "isSingleThreaded", .value =
group.isSingleThreaded_});
+ if (!class_description.class_relationships_.empty()) {
+ desc.children.push_back({.name = "inputRequirement", .value =
class_description.inputRequirement_});
+ desc.children.push_back({.name = "isSingleThreaded", .value =
class_description.isSingleThreaded_});
SerializedResponseNode relationships{.name = "supportedRelationships",
.array = true};
- for (const auto &relationship : group.class_relationships_) {
+ for (const auto &relationship : class_description.class_relationships_) {
SerializedResponseNode child{.name = "supportedRelationships"};
child.children.push_back({.name = "name", .value =
relationship.getName()});
child.children.push_back({.name = "description", .value =
relationship.getDescription()});
@@ -114,13 +158,13 @@ void serializeClassDescription(const
std::vector<ClassDescription>& descriptions
desc.children.push_back(relationships);
}
- desc.children.push_back({.name = "typeDescription", .value =
group.description_});
- desc.children.push_back({.name = "supportsDynamicRelationships", .value =
group.supports_dynamic_relationships_});
- desc.children.push_back({.name = "supportsDynamicProperties", .value =
group.supports_dynamic_properties_});
- desc.children.push_back({.name = "type", .value = group.full_name_});
- if (!group.api_implementations.empty()) {
+ desc.children.push_back({.name = "typeDescription", .value =
class_description.description_});
+ desc.children.push_back({.name = "supportsDynamicRelationships", .value =
class_description.supports_dynamic_relationships_});
+ desc.children.push_back({.name = "supportsDynamicProperties", .value =
class_description.supports_dynamic_properties_});
+ desc.children.push_back({.name = "type", .value =
class_description.full_name_});
+ if (!class_description.api_implementations.empty()) {
SerializedResponseNode provided_api_impls{.name =
"providedApiImplementations", .array = true};
- for (const auto& api_implementation : group.api_implementations) {
+ for (const auto& api_implementation :
class_description.api_implementations) {
SerializedResponseNode child{.name =
std::string(api_implementation.type)};
child.children.push_back({.name = "artifact", .value =
std::string(api_implementation.artifact)});
child.children.push_back({.name = "group", .value =
std::string(api_implementation.group)});
@@ -154,12 +198,12 @@ std::vector<SerializedResponseNode> Bundles::serialize() {
if (serialized_components[0].children.empty()) {
continue;
}
-
+ std::string serialized_comp_name = serialized_components[0].name;
SerializedResponseNode serialized_bundle {
.name = "bundles",
.children = {
serialized_components[0],
- {.name = "group", .value = GROUP_STR},
+ {.name = "group", .value = allowedTypeGroupName(serialized_comp_name)},
{.name = "artifact", .value = bundle.name},
{.name = "version", .value = bundle.version},
}
diff --git a/libminifi/src/minifi-c.cpp b/libminifi/src/minifi-c.cpp
index 220ec9513..68617d522 100644
--- a/libminifi/src/minifi-c.cpp
+++ b/libminifi/src/minifi-c.cpp
@@ -155,8 +155,8 @@ class CProcessorFactory : public
minifi::core::ProcessorFactory {
class CControllerServiceFactory : public
minifi::core::controller::ControllerServiceFactory {
public:
- CControllerServiceFactory(std::string group_name, std::string class_name,
minifi::utils::CControllerServiceClassDescription class_description)
- : group_name_(std::move(group_name)),
+ CControllerServiceFactory(std::string module_name, std::string class_name,
minifi::utils::CControllerServiceClassDescription class_description)
+ : module_name_(std::move(module_name)),
class_name_(std::move(class_name)),
class_description_(std::move(class_description)) {}
@@ -164,7 +164,7 @@ class CControllerServiceFactory : public
minifi::core::controller::ControllerSer
return
std::make_unique<minifi::utils::CControllerService>(class_description_,
std::move(metadata));
}
- [[nodiscard]] std::string getGroupName() const override { return
group_name_; }
+ [[nodiscard]] std::string getModuleName() const override { return
module_name_; }
[[nodiscard]] std::string getClassName() const override { return
class_name_; }
@@ -176,7 +176,7 @@ class CControllerServiceFactory : public
minifi::core::controller::ControllerSer
~CControllerServiceFactory() override = default;
private:
- std::string group_name_;
+ std::string module_name_;
std::string class_name_;
minifi::utils::CControllerServiceClassDescription class_description_;
};
@@ -277,15 +277,23 @@ void useCControllerServiceClassDescription(const
MinifiControllerServiceClassDef
auto name_segments =
minifi::utils::string::split(toStringView(class_description.full_name), "::");
gsl_Assert(!name_segments.empty());
- minifi::ClassDescription description{
- .type_ = minifi::ResourceType::ControllerService,
- .short_name_ = name_segments.back(),
- .full_name_ = minifi::utils::string::join(".", name_segments),
- .description_ = toString(class_description.description),
- .class_properties_ = properties,
+ std::vector<core::ControllerServiceType> implements_apis;
+ implements_apis.reserve(class_description.provided_interfaces_count);
+ for (size_t i = 0; i < class_description.provided_interfaces_count; ++i) {
+ auto api_segments =
string::split(toStringView(class_description.provided_interfaces_ptr[i]), "::");
+
implements_apis.push_back(core::ControllerServiceType::minifiSystemControllerServiceType(string::join(".",
api_segments)));
+ }
+
+ ClassDescription description{
+ .type_ = ResourceType::ControllerService,
+ .short_name_ = name_segments.back(),
+ .full_name_ = string::join(".", name_segments),
+ .description_ = toString(class_description.description),
+ .class_properties_ = properties,
+ .api_implementations = implements_apis,
};
- minifi::utils::CControllerServiceClassDescription c_class_description{
+ CControllerServiceClassDescription c_class_description{
.full_name = toString(class_description.full_name),
.class_properties = properties,
.callbacks = class_description.callbacks
@@ -613,6 +621,14 @@ MinifiStatus
MinifiProcessContextGetControllerServiceFromProperty(
*controller_service_out =
static_cast<MinifiControllerService*>(c_controller_service->getImpl());
return MINIFI_STATUS_SUCCESS;
}
+ if (class_description.callbacks.get_interface) {
+ const auto interface_res =
class_description.callbacks.get_interface(c_controller_service->getImpl(),
controller_service_type);
+ if (!interface_res) {
+ return MINIFI_STATUS_VALIDATION_FAILED;
+ }
+ *controller_service_out =
static_cast<MinifiControllerService*>(interface_res);
+ return MINIFI_STATUS_SUCCESS;
+ }
}
return MINIFI_STATUS_VALIDATION_FAILED;
}
diff --git a/libminifi/test/unit/ComponentManifestTests.cpp
b/libminifi/test/unit/ComponentManifestTests.cpp
index 7bc08750f..bfaaa3fa1 100644
--- a/libminifi/test/unit/ComponentManifestTests.cpp
+++ b/libminifi/test/unit/ComponentManifestTests.cpp
@@ -27,6 +27,7 @@
#include "core/Resource.h"
#include "core/state/nodes/AgentInformation.h"
#include "core/ProcessorImpl.h"
+#include "range/v3/algorithm/find_if.hpp"
using minifi::state::response::SerializedResponseNode;
@@ -38,6 +39,25 @@ SerializedResponseNode& get(SerializedResponseNode& node,
const std::string& fie
throw std::logic_error("No field '" + field + "'");
}
+namespace org::apache::nifi::minifi::test::apple {
+class ExampleApacheService : public core::controller::ControllerServiceBase,
public core::controller::ControllerServiceHandle {
+ public:
+ using ControllerServiceBase::ControllerServiceBase;
+
+ void initialize() override {}
+ void onEnable() override {}
+
+ [[nodiscard]] ControllerServiceHandle* getControllerServiceHandle() override
{ return this; }
+
+ static constexpr const char* Description = "An example service";
+ static constexpr auto Properties = std::array<core::PropertyReference, 0>{};
+ static constexpr bool SupportsDynamicProperties = false;
+ ADD_COMMON_VIRTUAL_FUNCTIONS_FOR_CONTROLLER_SERVICES
+};
+
+REGISTER_RESOURCE(ExampleApacheService, ControllerService);
+} // namespace org::apache::nifi::minifi::test::apple
+
namespace test::apple {
class ExampleService : public core::controller::ControllerServiceBase, public
core::controller::ControllerServiceHandle {
@@ -67,7 +87,12 @@ class ExampleProcessor : public core::ProcessorImpl {
.isRequired(false)
.withAllowedTypes<ExampleService>()
.build();
- static constexpr auto Properties =
std::to_array<core::PropertyReference>({ExampleProperty});
+ static constexpr auto ExampleApacheProperty =
core::PropertyDefinitionBuilder<>::createProperty("Example Apache Property")
+ .withDescription("An example property")
+ .isRequired(false)
+
.withAllowedTypes<org::apache::nifi::minifi::test::apple::ExampleApacheService>()
+ .build();
+ static constexpr auto Properties =
std::to_array<core::PropertyReference>({ExampleProperty,
ExampleApacheProperty});
static constexpr auto Relationships =
std::array<core::RelationshipDefinition, 0>{};
static constexpr bool SupportsDynamicProperties = false;
static constexpr bool SupportsDynamicRelationships = false;
@@ -93,27 +118,38 @@ TEST_CASE("Manifest indicates property type requirement") {
auto& processors = get(nodes.at(0), "processors").children;
- auto example_proc_it = std::find_if(processors.begin(), processors.end(),
[&] (auto& proc) {
+ auto example_proc_it = std::find_if(processors.begin(), processors.end(),
[&](auto& proc) {
return get(proc, "type").value == "test.apple.ExampleProcessor";
});
REQUIRE(example_proc_it != processors.end());
auto& properties = get(*example_proc_it, "propertyDescriptors").children;
- auto prop_it = std::find_if(properties.begin(), properties.end(), [&] (auto&
prop) {
- return get(prop, "name").value == "Example Property";
- });
+ {
+ auto prop_it = std::find_if(properties.begin(), properties.end(),
[&](auto& prop) { return get(prop, "name").value == "Example Property"; });
+
+ REQUIRE(prop_it != properties.end());
- REQUIRE(prop_it != properties.end());
+ // TODO(adebreceni): based on Property::types_ a property could accept
+ // multiple types, these would be dumped into the same object as the
type of
+ // field "typeProvidedByValue" is not an array but an object
+ auto& type = get(*prop_it, "typeProvidedByValue");
- // TODO(adebreceni): based on Property::types_ a property could accept
- // multiple types, these would be dumped into the same object as the type
of
- // field "typeProvidedByValue" is not an array but an object
- auto& type = get(*prop_it, "typeProvidedByValue");
+ CHECK(get(type, "type").value == "test.apple.ExampleService");
+ CHECK(get(type, "group").value == "test.apple");
+ CHECK(get(type, "artifact").value == "minifi-system");
+ }
+ {
+ auto prop_it = ranges::find_if(properties, [&](auto& prop) { return
get(prop, "name").value == "Example Apache Property"; });
+ REQUIRE(prop_it != properties.end());
- REQUIRE(get(type, "type").value == "test.apple.ExampleService");
- REQUIRE(get(type, "group").value == GROUP_STR); // fix string
- REQUIRE(get(type, "artifact").value == "minifi-system");
+ auto& type = get(*prop_it, "typeProvidedByValue");
+
+ CHECK(get(type, "type").value ==
"org.apache.nifi.minifi.test.apple.ExampleApacheService");
+ // Backward compatibility test, if the group starts with
org.apache.nifi.minifi we use that
+ CHECK(get(type, "group").value == "org.apache.nifi.minifi");
+ CHECK(get(type, "artifact").value == "minifi-system");
+ }
}
TEST_CASE("Processors do not get instantiated during manifest creation") {
diff --git
a/minifi-api/common/include/minifi-cpp/core/ProvidedControllerServiceInterface.h
b/minifi-api/common/include/minifi-cpp/core/ProvidedControllerServiceInterface.h
new file mode 100644
index 000000000..3b2af8cf9
--- /dev/null
+++
b/minifi-api/common/include/minifi-cpp/core/ProvidedControllerServiceInterface.h
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include <string_view>
+#include <type_traits>
+
+#include "core/ClassName.h"
+
+namespace org::apache::nifi::minifi::core {
+
+struct ProvidedInterface {
+ /// fully-qualified class name of the implemented ControllerService interface
+ std::string_view name;
+ /// casts a pointer of the ControllerService from its dynamic type to a
pointer of an implemented interface type. Needed to support cases where they
+ /// are not the same, like multiple inheritance, virtual inheritance, or
contained non-first member implementing the interface
+ void* (*cast)(void* instance);
+};
+
+/// casts a pointer of the ControllerService from its dynamic type to a
pointer of an implemented interface type. Needed to support cases where they
+/// are not the same, like multiple inheritance, virtual inheritance, or
contained non-first member implementing the interface
+template<typename Interface, typename ConcreteService>
+void* castProvidedControllerServiceToInterface(void* instance) {
+ auto* concrete = static_cast<ConcreteService*>(instance);
+ auto* interface_ptr = static_cast<Interface*>(concrete);
+ return interface_ptr;
+}
+
+template<typename Interface, typename ConcreteService>
+constexpr ProvidedInterface createProvidedInterface() {
+ return ProvidedInterface{className<Interface>(),
&castProvidedControllerServiceToInterface<Interface, ConcreteService>};
+}
+
+} // namespace org::apache::nifi::minifi::core
diff --git a/minifi-api/include/minifi-c/minifi-c.h
b/minifi-api/include/minifi-c/minifi-c.h
index 8294dd91f..1fdfe953c 100644
--- a/minifi-api/include/minifi-c/minifi-c.h
+++ b/minifi-api/include/minifi-c/minifi-c.h
@@ -186,6 +186,7 @@ typedef struct MinifiControllerServiceCallbacks {
void(*destroy)(MINIFI_OWNED void*);
MinifiStatus(*enable)(void*, MinifiControllerServiceContext*);
void(*disable)(void*);
+ void* (*get_interface)(void* ctx, MinifiStringView interface_type);
} MinifiControllerServiceCallbacks;
typedef struct MinifiProcessorClassDefinition {
@@ -212,6 +213,8 @@ typedef struct MinifiControllerServiceClassDefinition {
MinifiStringView description;
size_t class_properties_count;
const MinifiPropertyDefinition* class_properties_ptr;
+ size_t provided_interfaces_count;
+ const MinifiStringView* provided_interfaces_ptr;
MinifiControllerServiceCallbacks callbacks;
} MinifiControllerServiceClassDefinition;
diff --git a/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h
b/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h
index c05d20396..e9337d5e7 100644
--- a/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h
+++ b/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h
@@ -1,5 +1,5 @@
/**
-* Licensed to the Apache Software Foundation (ASF) under one or more
+ * 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
@@ -16,13 +16,12 @@
*/
#pragma once
-#include "minifi-cpp/core/controller/ControllerServiceHandle.h"
+#include <expected>
+
#include "minifi-cpp/core/ControllerServiceTypeDefinition.h"
#include "minifi-cpp/core/Record.h"
-#include "utils/Enum.h"
-#include "utils/ProcessorConfigUtils.h"
+#include "minifi-cpp/core/controller/ControllerServiceHandle.h"
#include "minifi-cpp/io/InputStream.h"
-#include "minifi-cpp/agent/agent_version.h"
namespace org::apache::nifi::minifi::core {
diff --git a/minifi-api/include/minifi-cpp/core/ClassLoader.h
b/minifi-api/include/minifi-cpp/core/ClassLoader.h
index 559ef0048..c377bca13 100644
--- a/minifi-api/include/minifi-cpp/core/ClassLoader.h
+++ b/minifi-api/include/minifi-cpp/core/ClassLoader.h
@@ -72,7 +72,7 @@ class ClassLoader {
virtual void unregisterClass(const std::string& clazz) = 0;
- [[nodiscard]] virtual std::optional<std::string> getGroupForClass(const
std::string &class_name) const = 0;
+ [[nodiscard]] virtual std::optional<std::string>
getModuleForClass(std::string_view class_name) const = 0;
[[nodiscard]] virtual std::unique_ptr<CoreComponent> instantiate(const
std::string &class_name, const std::string &name,
std::function<bool(CoreComponent*)> filter) = 0;
diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
index 6d5b39de3..f45a8e3fb 100644
--- a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
+++ b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h
@@ -1,5 +1,5 @@
/**
-* Licensed to the Apache Software Foundation (ASF) under one or more
+ * 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
@@ -17,6 +17,7 @@
#pragma once
#include <string>
+
#include "minifi-cpp/core/ControllerServiceTypeDefinition.h"
namespace org::apache::nifi::minifi::core {
@@ -27,9 +28,19 @@ struct ControllerServiceType {
std::string type;
ControllerServiceType(const ControllerServiceTypeDefinition& definition) //
NOLINT(runtime/explicit)
- : artifact(definition.artifact),
- group(definition.group),
- type(definition.type) {}
+ : artifact(definition.artifact),
+ group(definition.group),
+ type(definition.type) {}
+
+ static ControllerServiceType minifiSystemControllerServiceType(std::string
type) {
+ return ControllerServiceType("minifi-system", "org.apache.nifi.minifi",
std::move(type));
+ }
+
+ private:
+ ControllerServiceType(std::string artifact, std::string group, std::string
type)
+ : artifact(std::move(artifact)),
+ group(std::move(group)),
+ type(std::move(type)) {}
};
} // namespace org::apache::nifi::minifi::core
diff --git a/minifi-api/include/minifi-cpp/core/ObjectFactory.h
b/minifi-api/include/minifi-cpp/core/ObjectFactory.h
index 8058151ee..8ff5039a9 100644
--- a/minifi-api/include/minifi-cpp/core/ObjectFactory.h
+++ b/minifi-api/include/minifi-cpp/core/ObjectFactory.h
@@ -30,7 +30,7 @@ class ObjectFactory {
virtual gsl::owner<CoreComponent*> createRaw(const std::string& /*name*/) =
0;
virtual std::unique_ptr<CoreComponent> create(const std::string& /*name*/,
const utils::Identifier& /*uuid*/) = 0;
virtual gsl::owner<CoreComponent*> createRaw(const std::string& /*name*/,
const utils::Identifier& /*uuid*/) = 0;
- virtual std::string getGroupName() const = 0;
+ virtual std::string getModuleName() const = 0;
virtual std::string getClassName() = 0;
virtual ~ObjectFactory() = default;
diff --git
a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h
b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h
index aafc571dc..17b8637eb 100644
--- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h
+++ b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h
@@ -30,7 +30,7 @@ class ControllerServiceApi;
class ControllerServiceFactory {
public:
virtual std::unique_ptr<ControllerServiceApi>
create(ControllerServiceMetadata metadata) = 0;
- virtual std::string getGroupName() const = 0;
+ virtual std::string getModuleName() const = 0;
virtual std::string getClassName() const = 0;
virtual ~ControllerServiceFactory() = default;