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");
+    }
+  }
+}

Reply via email to