-
Bug Report
-
Resolution: Fixed
-
L3 - Default
-
7.17.0
-
None
Environment (Required on creation): Liberica Java 17
Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):
We have a conditionExpression:
#{status == "approve" && total.compareTo(0) >= 0}
balance is a BigDecimal. This seemed to work ok, but suddenly we had problems when switching JVMs from Eclipse Temurin to Liberica.
rg.camunda.bpm.engine.ProcessEngineException: Error while evaluating expression: #{status == "approve" && total.compareTo(0) >= 0}. Cause: java.lang.ClassCastException: class java.lang.Long cannot be cast to class java.math.BigDecimal (java.lang.Long and java.math.BigDecimal are in module java.base of loader 'bootstrap')
We eventually traced this down to:
BeanELResolver.findMethod() is called with no types defined, so it simply calls BigDecimal.getClass().getMethods() and iterates looking for `compareTo`.
Unfortunately, in our new JVM base container, the ordering of the methods is random:
This order works fine:
public int java.math.BigDecimal.compareTo(java.math.BigDecimal)
public int java.math.BigDecimal.compareTo(java.lang.Object)
However, sometimes the order returned is reversed and `compareTo(java.lang.Object)` is first. When that happens, TypeConverterImpl.coerceToType is called with a Long value and a type of Object.
It falls through to type.isInstance(value), which of course returns true, passing the original Long back without conversion.
This then throws an InvocationTargetException caused by the ClassCastException trying to pass a Long to a method that requires a BigDecimal.
Although I was slightly tempted to blame our new choice of JVM, the Javadoc for getMethods() is clear: "The elements in the returned array are not sorted and are not in any particular order."
Steps to reproduce (Required on creation):
Running on Liberica JVM (and presumably others), create an expression that would require a coercion as above.
Observed Behavior (Required on creation):
Long is cast to BigDecimal, which fails.
Expected behavior (Required on creation):
Long 0 is coerced to BigDecimal.
Root Cause (Required on prioritization):
Solution Ideas (Optional):
I'm not familiar enough with this code to know if the problem is that `findMethod` is called without any types, or if the fall-through call to `getMethods()` needs to be more selective, or even multi-pass.