[
https://issues.jboss.org/browse/DROOLS-185?page=com.atlassian.jira.plugin...
]
Liu Yan commented on DROOLS-185:
--------------------------------
In hope my case could help you and others, I past some pseud code here:
In java:
ClassA extends ClassBase
ClassB extends ClassBase
In DRL:
rule prepare
when
$base: ClassBase()
then
update($base);
end
rule process
when
$B: ClassB()
then
$B.doThings_ClassB_Specific()
end
The CCE would likely be something like ClassB can't cast to ClassA at update($base) in
rule prepare.
When I first saw this, it's pretty odd because ClassA never appeared anywhere. My work
was blocked here for 2 days, finally I tried to comment out "rule process" and
the CCE disappeared. This give me some idea of how this happen.
ClassCastException at ConditionEvaluator
----------------------------------------
Key: DROOLS-185
URL:
https://issues.jboss.org/browse/DROOLS-185
Project: Drools
Issue Type: Bug
Affects Versions: 5.5.0.Final
Reporter: Sergey Alaev
Assignee: Mario Fusco
Stacktrace:
Caused by: java.lang.ClassCastException: ***** cannot be cast to ******
at ConditionEvaluator443abf2927ca4f64a4ad86407ae34799.evaluate(Unknown Source)
at org.drools.rule.constraint.MvelConstraint.evaluate(MvelConstraint.java:200)
at org.drools.rule.constraint.MvelConstraint.isAllowed(MvelConstraint.java:157)
at org.drools.reteoo.FromNode.checkConstraintsAndPropagate(FromNode.java:318)
at org.drools.reteoo.FromNode.assertLeftTuple(FromNode.java:164)
at
org.drools.reteoo.CompositeLeftTupleSinkAdapter.doPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:232)
at
org.drools.reteoo.CompositeLeftTupleSinkAdapter.createAndPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:116)
at org.drools.reteoo.LeftInputAdapterNode.assertObject(LeftInputAdapterNode.java:154)
at
org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:59)
Reason:
ConditionEvaluator seems to be using lazy initializing and then caches generated class to
evaluate this expression with another arguments.
Given following:
interface A {
String getString();
}
interface B {
String getString();
}
class X implements B, A {}
class Y implements A{}
rule "test rule"
when:
A(string != null)
then:
end
When rule engine is called for the first time with instance of class X,
ConditionEvaluator will bind itself to first found interface implementing method
getString(), i.e. interface B.
Thus second call with instance of class Y will cause ClassCastException of casting Y to
B.
Solution: force MVEL to bind bytecode generated methods to class/interface declared in
the rule explicitly, in our case - to interface A.
Quickfix: use following declaration of class X:
class X implements A, B {}
Because ConditionEvaluator binds to first available interface, it will bind now to
correct interface - to interface A.
--
This message was sent by Atlassian JIRA
(v6.3.11#6341)