AndriiTsepukh opened a new issue, #7144:
URL: https://github.com/apache/incubator-kie/issues/7144
### Describe the bug
A contains constraint gives a different result after the constraint is
jitted. This happens when the left operand has the static type Object but holds
a String at runtime, the typical case being Map.get(...).
The interpreted (MVEL) evaluator does a substring check and matches. The
jitted evaluator returns false. With the default drools.jittingThreshold (20),
the rule works for the first 20 evaluations on a KieBase and stops matching
after that. A new KieBase resets the counter, so in production this looks like
an intermittent failure that "fixes itself" after a rules reload.
### Expected behavior
The jitted and interpreted evaluators return the same result. Map(
get("key") contains "T80011" ) matches Map.of("key", "FAILURE.T80011") on every
evaluation.
### Actual behavior
Evaluations 1-20 match. From evaluation 21 on, the constraint returns
`false`.
| Setting | Evaluations 1-20 |
Evaluations 21-30 |
|-------------------------------------------------|------------------|-------------------|
| default (`drools.jittingThreshold=20`) | match | **no
match** |
| `-Ddrools.jittingThreshold=5` | 1-5 match | 6+
**no match** |
| `-Ddrools.jittingThreshold=-1` (jitting off) | match | match
|
| DRL cast: `((String) get("key")) contains ...` | match | match
|
### How to Reproduce?
Plain Java, non-executable model (drools-compiler + drools-mvel):
```
public class Message {
private final Map<String, String> metadata;
public Message(Map<String, String> metadata) { this.metadata = metadata;
}
public Map<String, String> getMetadata() { return metadata; }
}
```
package repro;
import repro.Message;
global java.util.List fired;
rule "contains on Map.get"
when
Message( metadata.get("codes") contains "T80011" )
then
fired.add("hit");
end
1. Build one KieBase from the DRL with
KieServices.newKieBuilder(kfs).buildAll().
2. 30 times: create a session, insert new Message(Map.of("codes",
"FAILURE.T80011")), call fireAllRules(), dispose.
3. The rule fires in runs 1-20 and not in runs 21-30.
With ConstraintJittingThresholdOption.get(0) the constraint is jitted on its
first evaluation and never matches.
### Output of `uname -a` or `ver`
_No response_
### Output of `java -version`
_No response_
### GraalVM version (if different from Java)
_No response_
### Kogito version or git rev (or at least Quarkus version if you are using
Kogito via Quarkus platform BOM)
_No response_
### Build tool (ie. output of `mvnw --version` or `gradlew --version`)
_No response_
### Additional information
### Cause
- The build accepts the constraint. `PatternBuilder` resolves
`metadata.get("codes")` to `String` from the generic type `Map<String,
String>`, so the compile-time `contains` type check passes. With a raw `Map` or
a plain `Object` getter, the build rejects the same rule with `Cannot use
contains on class java.lang.Object`.
- MVEL resolves `contains` against the runtime value
(`ParseTools.containsCheck`). For a `String`, this is
`String.contains(String.valueOf(item))`.
- `ASMConditionEvaluatorJitter`, `case CONTAINS`, uses the erased type. It
emits `String.contains` only when `leftType == String.class`. For `Map.get()`
it sees `Object`, so it emits `EvaluatorHelper.contains(Object, Object)`.
- `EvaluatorHelper.contains(Object, Object)` handles `Collection`,
`Object[]` and primitive arrays only. For a `String`, it falls through to
`return false`.
- The executable model is not affected: the same `JittingTest` case passes
there.
### Suggested fix
Add a `String` branch to `EvaluatorHelper.contains(Object, Object)`, the
same as MVEL does. I am opening a PR with this change and a regression test in
`JittingTest`.
### Workarounds
- Cast in the DRL: `((String) metadata.get("codes")) contains "T80011"`.
- Use `matches ".*T80011.*"`.
- Turn jitting off: `-Ddrools.jittingThreshold=-1`, or
`drools.jittingThreshold=-1` in `META-INF/kie.properties.conf`.
- Use the executable model.
### Environment
- Drools: reproduced on 8.44.2.Final and 10.2.0. The code is unchanged on
`main`.
- Java: OpenJDK 21.0.6
- Build tool: Apache Maven 3.9.9
- Non-executable model (MVEL), no Quarkus or Spring Boot extension.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]