The `string()` function doesn't work for a context with custom value types
saig0 opened this issue · 1 comments
Describe the bug
The string()
function doesn't return the expected string representation from a context value if it contains custom value types.
The problem doesn't occur with standard Java/Scala types but with custom types. See the issue here on how to reproduce the issue in Camunda 8.
string(myContextVar)
// --> "{key1:UnsafeBuffer{addressOffset=16, capacity=12, byteArray=byte[12], byteBuffer=null}}"
To Reproduce
Steps to reproduce the behavior:
- Run the following unit test
- Verify that the test fails on the second case
case class CustomValue(value: Int)
class MyCustomValueMapper extends CustomValueMapper {
def toVal(x: Any, innerValueMapper: Any => Val): Option[Val] = x match {
case CustomValue(value) => Some(ValNumber(value))
case _ => None
}
override def unpackVal(value: Val, innerValueMapper: Val => Any): Option[Any] = None
}
it should "convert a custom context" in {
val engine = FeelEngineBuilder()
.withCustomValueMapper(new MyCustomValueMapper())
.build()
engine.evaluateExpression(
expression = " string(context) ",
variables = Map("context" -> Map("a" -> CustomValue(1)))
) should returnResult("{a:1}") // --> works
engine.evaluateExpression(
expression = " string(context) ",
variables = Map("context" -> ValContext(new MyCustomContext(Map("a" -> CustomValue(1)))))
) should returnResult("{a:1}") // --> fails with "the evaluation didn't returned '{a:1}' but '{a:CustomValue(1)}'"
}
Expected behavior
The string()
function returns the string representation for custom value types. It uses the configured value mapper of the engine to transform the custom types.
Environment
- FEEL engine version:
1.17.1
- Affects:
- Camunda Automation Platform 7: [7.x]
- Zeebe broker:
8.3.2
camunda/camunda#15209 - Support: https://jira.camunda.com/browse/SUPPORT-19836
NVM, that was a problem with my intellij runner, it ran another test after adding the lines.
@saig0
I was trying the test case attached in the description for curiosity, the problem in the above test case lies in the test setup.
in the MyCustomValueMapper
provided the method unpackVal
resolves to None
while if you change it a tiny bit to match the implementation of DefaultValueMapper
as follows, The test will succeed.
override def unpackVal(value: Val, innerValueMapper: Val => Any): Option[Any] = value match {
case ValContext(c: Context) =>
Some(
c.variableProvider.getVariables.map { case (key, value) =>
value match {
case packed: Val => key -> innerValueMapper(packed)
case unpacked => key -> unpacked
}
}
)
case _ => None
}