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]

Reply via email to