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 ee21c293e5e29cf84533fee852e7f9ad98c2ba6d Author: Gabor Gyimesi <[email protected]> AuthorDate: Mon Jun 23 10:54:26 2025 +0200 MINIFICPP-2581 Fix EL evaluation in dynamic properties Signed-off-by: Ferenc Gerlits <[email protected]> Closes #1983 --- .../expression-language/ProcessContextExpr.cpp | 14 +++++++---- .../tests/ProcessContextExprTests.cpp | 29 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/extensions/expression-language/ProcessContextExpr.cpp b/extensions/expression-language/ProcessContextExpr.cpp index 4f1ca384b..d22447c5d 100644 --- a/extensions/expression-language/ProcessContextExpr.cpp +++ b/extensions/expression-language/ProcessContextExpr.cpp @@ -70,13 +70,17 @@ nonstd::expected<void, std::error_code> ProcessContextExpr::setDynamicProperty(s std::map<std::string, std::string> ProcessContextExpr::getDynamicProperties(const FlowFile* flow_file) const { auto dynamic_props = ProcessContextImpl::getDynamicProperties(flow_file); - for (auto& [dynamic_property_name, dynamic_property_value] : dynamic_props) { - if (!cached_dynamic_expressions_.contains(dynamic_property_name)) { + const expression::Parameters params{this, flow_file}; + for (auto& [dynamic_property_name, dynamic_property_value]: dynamic_props) { + auto cached_dyn_expr_it = cached_dynamic_expressions_.find(dynamic_property_name); + if (cached_dyn_expr_it == cached_dynamic_expressions_.end()) { auto expression = expression::compile(dynamic_property_value); - expression::Parameters p(this, flow_file); - dynamic_property_value = expression(p).asString(); - cached_dynamic_expressions_.emplace(std::string{dynamic_property_name}, std::move(expression)); + const auto [it, success] = cached_dynamic_expressions_.emplace(dynamic_property_name, expression); + gsl_Assert(success && "getDynamicProperties: no element with the key existed, yet insertion failed"); + cached_dyn_expr_it = it; } + auto& expression = cached_dyn_expr_it->second; + dynamic_property_value = expression(params).asString(); } return dynamic_props; } diff --git a/extensions/expression-language/tests/ProcessContextExprTests.cpp b/extensions/expression-language/tests/ProcessContextExprTests.cpp index 00d7c2d40..03b8a50e4 100644 --- a/extensions/expression-language/tests/ProcessContextExprTests.cpp +++ b/extensions/expression-language/tests/ProcessContextExprTests.cpp @@ -100,3 +100,32 @@ TEST_CASE("ProcessContextExpr can update existing processor properties", "[setPr } } } + +TEST_CASE("ProcessContextExpr can use expression language in dynamic properties", "[getDynamicProperty][getDynamicProperties]") { + TestController test_controller; + std::shared_ptr<TestPlan> test_plan = test_controller.createPlan(); + std::ignore = test_plan->addProcessor("DummyProcessor", "dummy_processor"); + test_plan->runNextProcessor(); + const auto context = test_plan->getCurrentContext(); + REQUIRE(dynamic_pointer_cast<core::ProcessContextExpr>(context) != nullptr); + + core::FlowFileImpl flow_file; + flow_file.setAttribute("attr_a", "myAttributeValue"); + context->setDynamicProperty("MyDynamicProperty", "${attr_a}"); + + SECTION("Use getDynamicProperties") { + for (size_t i = 0; i < 2; ++i) { + auto properties = context->getDynamicProperties(&flow_file); + REQUIRE(properties.size() == 1); + CHECK(properties["MyDynamicProperty"] == "myAttributeValue"); + } + } + + SECTION("Use getDynamicProperty") { + for (size_t i = 0; i < 2; ++i) { + auto property = context->getDynamicProperty("MyDynamicProperty", &flow_file); + REQUIRE(property); + CHECK(*property == "myAttributeValue"); + } + } +}
