[rules-users] Cannot invoke method because of ArrayIndexOutOfBoundsException

Wolfgang Laun wolfgang.laun at gmail.com
Thu Mar 7 10:42:11 EST 2013


The problem is not the loop in isEqualMore. I think the problem is caused
by MVEL not handling the signature (Ann...) correctly.

@Mario: should MVEL be able to deal with such a function call?

-W


On 07/03/2013, Bojan Janisch <bojan.janisch at scai.fraunhofer.de> wrote:
> I've tested all 4 cases. It is strange that each Rule fired exactly one
> time,
> directly before the exception occurs. Here the rules, I've built them
> exactly
> for this problem.
> ============================================
> Test 1(isEqualMore):
> rule "Test Experiment 1"
> no-loop
>     when
>         $a1:ODMAnswer()
>
>         $a2:ODMAnswer(
>         !isEqual($a1,$a2),
>         comesAfter($a1,$a2,50))
>
>         $a3:ODMAnswer(
>         comesAfter($a2,$a3,20),
>         !isEqualMore($a1,$a2,$a3))
>     then
>         System.out.println("Test 1 works");
> end
>
> Result:
> Same Runtime exception
> ============================================
> Test 2(isEqualThree):
> rule "Test Experiment 2"
> no-loop
>     when
>         $a1:ODMAnswer()
>
>         $a2:ODMAnswer(
>         !isEqual($a1,$a2),
>         comesAfter($a1,$a2,50))
>
>         $a3:ODMAnswer(
>         comesAfter($a2,$a3,20),
>         !isEqualThree($a1,$a2,$a3))
>     then
>         System.out.println("Test 2 works");
> end
> Result:
> Works perfect without errors.
> ============================================
> Test 3(isEqualMore):
> rule "Test Experiment 3"
> no-loop
>     when
>         $a1:ODMAnswer()
>
>         $a2:ODMAnswer(
>         !isEqual($a1,$a2),
>         comesAfter($a1,$a2,5))
>
>         ($a3:ODMAnswer(
>         comesAfter($a2,$a3,5)) and
>         eval(!isEqualMore($a1,$a2,$a3)))
>     then
>         System.out.println("Test 3 works");
> end
> Result:
> Works also without errors (I'm surprised).
> ============================================
> Test 4(isEqualThree):
> rule "Test Experiment 4"
> no-loop
>     when
>         $a1:ODMAnswer()
>
>         $a2:ODMAnswer(
>         !isEqual($a1,$a2),
>         comesAfter($a1,$a2,5))
>
>         ($a3:ODMAnswer(
>         comesAfter($a2,$a3,5)) and
>         eval(!isEqualThree($a1,$a2,$a3)))
>     then
>         System.out.println("Test 4 works");
> end
> Result:
> Works perfect, but seems to get more matches
> than the 3. experiment.
> ============================================
> Fazit:
>
> In my eyes there seems to be a problem using a loop in a constraint.
> Even if I use different names (see Test 2), I'm still getting the
> runtime exception. As bonus test-case I've tried using Test 3 and
> overloading the function, rather than using a different function name,
> but this also failed.
>
> Seems that I have to use eval() and different names if I want to compare
> multiple named entities, though I still don't know why. Maybe the isEqual
> call in the loop is calling itself and generating an out of bounds exception
> at the last array entity.
>
> Thank you wolfgang.
>
> JB
> ----- Ursprüngliche Mail -----
> Von: "Wolfgang Laun" <wolfgang.laun at gmail.com>
> An: "Rules Users List" <rules-users at lists.jboss.org>
> Gesendet: Donnerstag, 7. März 2013 13:36:12
> Betreff: Re: [rules-users] Cannot invoke method because
> of	ArrayIndexOutOfBoundsException
>
> You have lost me - I'm not sure anymore what works and what doesn't.
>
> Please check or rewrite, using the names
> isEqualMore(Annotation... annos)
> isEqualThree(Annotation a1, Annotation a2, Annotation a3)
>
> 1) not $a5:ODMAnswer(..., ! isEqualX($a3,$a4,$a5) )
> does not work for X==More and
> does not work for X==Three
>
> 2) not( $a5:ODMAnswer(...) and eval( ! isEqualX($a3,$a4,$a5) )
> works for X==More and
> works for X==Three
>
> -W
>
>
>
>
> On 07/03/2013, Bojan Janisch <bojan.janisch at scai.fraunhofer.de> wrote:
>>> Experiment 1
>>> Please write isEqualThree for 3 Annotation arguments and use this,
>>> just to make sure that these Problems are caused by Drools. (Do NOT
>>> rely on overloading, use another name.)
>>
>> I've created an isEqualThree function
>>
>> public static boolean isEqualThree(Annotation a, Annotation b, Annotation
>> c){
>> 	if(isEqual(a,b) || isEqual(b,c) || isEqual(a,c)){
>> 		return true;
>> 	}
>> 	return false;
>> }
>>
>> By the way, it works also with overloading, I've never had problems with
>> overloading in Drools. And I've tested also with different names, the
>> problem
>> remains, even using different function names.
>>
>>> Experiment 2
>>> Using the isEqual as it is now, rewrite the last pattern as:
>>>
>>> not ( $a5:ODMAnswer(
>>>               isInAnnotation($a1,$a5),
>>>               isBigger($a3,$a5) )
>>>          and
>>>          eval( ! isEqual($a3,$a4,$a5) )
>>>        )
>>
>> Your condition works without problems using the isEqualThree function, it
>> works
>> also if I overload the function. It also works if I put the isEqual
>> condition out
>> of the eval, into the object constraints. But if I want to use my primary
>> idea, using
>> different names,
>>
>> public static boolean isEqualMore(Annotation... a)
>>
>> I still get the same error from the isEqualMore function.
>>
>> java.lang.RuntimeException: cannot invoke method: isEqualMore
>> 	at
>> de.fraunhofer.scai.bio.uima.core.deploy.StatusCallbackListenerImpl.entityProcessComplete(StatusCallbackListenerImpl.java:151)
>> 	at
>> org.apache.uima.collection.impl.cpm.engine.CPMThreadGroup.notifyListener(CPMThreadGroup.java:103)
>> 	at
>> org.apache.uima.collection.impl.cpm.engine.CPMThreadGroup.uncaughtException(CPMThreadGroup.java:86)
>> 	at java.lang.Thread.dispatchUncaughtException(Thread.java:1888)
>> Caused by: java.lang.ArrayIndexOutOfBoundsException: 3
>> 	at
>> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.executeAll(MethodAccessor.java:149)
>> 	at
>> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.getValue(MethodAccessor.java:48)
>> 	at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:108)
>> 	at
>> org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:38)
>> 	at org.mvel2.ast.Negation.getReducedValueAccelerated(Negation.java:48)
>> 	at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
>> 	at
>> org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:123)
>> 	at
>> org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:116)
>> 	at org.mvel2.MVEL.executeExpression(MVEL.java:930)
>> 	at
>> org.drools.rule.constraint.MvelConditionEvaluator.evaluate(MvelConditionEvaluator.java:70)
>> 	at
>> org.drools.rule.constraint.MvelConditionEvaluator.ensureBranchEvaluation(MvelConditionEvaluator.java:113)
>> 	at
>> org.drools.rule.constraint.MvelConditionEvaluator.ensureCompleteEvaluation(MvelConditionEvaluator.java:106)
>> 	at
>> org.drools.rule.constraint.MvelConditionEvaluator.ensureCompleteEvaluation(MvelConditionEvaluator.java:90)
>> 	at
>> org.drools.rule.constraint.MvelConditionEvaluator.getAnalyzedCondition(MvelConditionEvaluator.java:82)
>> 	at
>> org.drools.rule.constraint.MvelConstraint.executeJitting(MvelConstraint.java:214)
>> 	at
>> org.drools.rule.constraint.MvelConstraint.access$000(MvelConstraint.java:41)
>> 	at
>> org.drools.rule.constraint.MvelConstraint$1.run(MvelConstraint.java:201)
>> 	at
>> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
>> 	at
>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
>> 	at java.lang.Thread.run(Thread.java:679)
>>
>> JB
>>
>> ----- Ursprüngliche Mail -----
>> Von: "Wolfgang Laun" <wolfgang.laun at gmail.com>
>> An: "Rules Users List" <rules-users at lists.jboss.org>
>> Gesendet: Donnerstag, 7. März 2013 06:46:29
>> Betreff: Re: [rules-users] Cannot invoke method because
>> of	ArrayIndexOutOfBoundsException
>>
>> On 06/03/2013, Bojan Janisch <bojan.janisch at scai.fraunhofer.de> wrote:
>>> But that's exactly what java is doing if you say the Arguments are
>>> method(X... xs).
>>> Java is then generating an array of the type you set and you can work
>>> with
>>> xs like an
>>> normal array.
>>
>> Yes, Java, but.
>>
>>> By the way, seems I get this Error
>>>
>>> Unable to Analyse Expression isEqual(new Annotation[]{$a3,$a4,$a5})
>>> [Error: could not instantiate class]
>>> [Near : {... isEqual(new Annotation[]{$a3,$a4,$a5}) ....}]
>>>                                      ^
>>> [Line: 129, Column: 8]
>>
>> Suspicious, may have to raise a JIRA.
>>
>> Experiment 1
>> Please write isEqualThree for 3 Annotation arguments and use this,
>> just to make sure that these Problems are caused by Drools. (Do NOT
>> rely on overloading, use another name.)
>>
>> Experiment 2
>> Using the isEqual as it is now, rewrite the last pattern as:
>>
>>  not ( $a5:ODMAnswer(
>>                isInAnnotation($a1,$a5),
>>                isBigger($a3,$a5) )
>>           and
>>           eval( ! isEqual($a3,$a4,$a5) )
>>         )
>>
>>
>> -W
>>
>>>
>>>
>>> The changed method is:
>>>
>>> public static boolean isEqual(Annotation[] a){
>>> 	ArrayList<Annotation> outLoop = new
>>> ArrayList<Annotation>(Arrays.asList(a));
>>> 	ArrayList<Annotation> inLoop = new
>>> ArrayList<Annotation>(Arrays.asList(a));
>>> 	
>>> 	for (Annotation anno1 : outLoop) {
>>> 		inLoop.remove(anno1);
>>> 		for (Annotation anno2 : inLoop) {
>>> 			if(isEqual(anno1,anno2)){
>>> 				return true;
>>> 			}
>>> 		}
>>> 	}
>>> 	
>>> 	return false;
>>> }
>>>
>>> ----- Ursprüngliche Mail -----
>>> Von: "Wolfgang Laun" <wolfgang.laun at gmail.com>
>>> An: "Rules Users List" <rules-users at lists.jboss.org>
>>> Gesendet: Mittwoch, 6. März 2013 17:11:43
>>> Betreff: Re: [rules-users] Cannot invoke method because
>>> of	ArrayIndexOutOfBoundsException
>>>
>>> I wouldn't use (X... xs) in this context.
>>>
>>> Try the simple modification of isEqual( Annotation[] annos ) and
>>> call it with isEqual( new Annotation[]{$a3,$a4,$a5})
>>> and we'll see what we'll see.
>>>
>>> -W
>>>
>>>
>>> On 06/03/2013, Bojan Janisch <bojan.janisch at scai.fraunhofer.de> wrote:
>>>> Like you wish wolfgang. The complete Rule is:
>>>>
>>>> rule "Generate Finding_ConceptId"
>>>> no-loop
>>>>     when
>>>>        	$a1:ODMAnswer(
>>>>         q1:QuestionId,
>>>>         q1.toLowerCase.contains("diagnose") ||
>>>>         q1.toLowerCase.contains("indication"),
>>>>         q1.toLowerCase.contains("sections"),
>>>>         a1_begin:begin,
>>>>         label1:ResponseAttribute)
>>>>
>>>>         $a2:ODMAnswer(
>>>>        	ResponseAttribute.contains(label1),
>>>>         QuestionId.contains("sectionheader"),
>>>>         comesBefore($a1,$a2));
>>>>
>>>>         $a3:ODMAnswer(
>>>>         q3:QuestionId,
>>>>         !q3.contains("finding.conceptId"),
>>>>         !q3.contains("itemGroup"),
>>>>         !q3.contains("section"),
>>>>         a3_begin:begin,
>>>>         a3_end:end,
>>>>         label2:ResponseAttribute,
>>>>         isInAnnotation($a1,$a3))
>>>>
>>>>         $a4:ODMAnswer(
>>>>         q4:QuestionId.contains("finding.conceptId"),
>>>>         a4_begin:begin,
>>>>         comesAfter($a2,$a4),
>>>>         isBetween($a2,$a3,$a4),
>>>>         isInAnnotation($a1,$a4))
>>>>
>>>>         not $a5:ODMAnswer(
>>>>         isInAnnotation($a1,$a5),
>>>>         isBigger($a3,$a5),
>>>>        	!isEqual($a3,$a4,$a5))           	
>>>>     then
>>>>         String questionId = "finding.conceptId";
>>>>     	String attribute = label1 +" "+ label2;
>>>>     	int begin = a4_begin;
>>>>     	int ende = a3_end;
>>>>     	boolean addToIndexes = true;
>>>>     	
>>>>     	
>>>>     	insert(annotate(aJCas, questionId, attribute, begin, ende,
>>>> addToIndexes));
>>>> end
>>>>
>>>> The functions are in a seperate FactChecker class, because the
>>>> "incode-comparison"
>>>> was too much of a chaos. So I wrote functions which explains themselves
>>>> what
>>>> they do:
>>>> ==================================================================
>>>> public static boolean isInAnnotation(Annotation a, Annotation b){
>>>> 	if(isNull(a,b)){
>>>> 		return false;
>>>> 	}
>>>> 	if(b.getBegin() > a.getBegin() && b.getEnd() < a.getEnd()){
>>>> 		return true;
>>>> 	}
>>>> 	if(a.getBegin() > b.getBegin() && a.getEnd() < b.getEnd()){
>>>> 		return true;
>>>> 	}
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean isInAnnotation(Annotation... a){
>>>> 	for (int i = 0; i < a.length; i++){
>>>> 		if(i+1 == a.length){
>>>> 			return false;
>>>> 		}
>>>> 		if(isInAnnotation(a[i], a[i+1])){
>>>> 			return true;
>>>> 		}
>>>> 	}
>>>> 	
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean comesBefore(Annotation a, Annotation b){
>>>> 	if(isNull(a,b)){
>>>> 		return false;
>>>> 	}
>>>> 	if(b.getEnd() <= a.getBegin()){
>>>> 		return true;
>>>> 	}
>>>>
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean comesAfter(Annotation a, Annotation b){
>>>> 	if(isNull(a,b)){
>>>> 		return false;
>>>> 	}
>>>> 	if(a.getEnd() <= b.getBegin()){
>>>> 		return true;
>>>> 	}
>>>>
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean isEqual(Annotation a, Annotation b){
>>>> 	if(isNull(a,b)){
>>>> 		return false;
>>>> 	}
>>>> 	if(a.equals(b)){
>>>> 		return true;
>>>> 	}
>>>> 	
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean isEqual(Annotation... a){
>>>> 	ArrayList<Annotation> outLoop = new
>>>> ArrayList<Annotation>(Arrays.asList(a));
>>>> 	ArrayList<Annotation> inLoop = new
>>>> ArrayList<Annotation>(Arrays.asList(a));
>>>> 	
>>>> 	for (Annotation anno1 : outLoop) {
>>>> 		if(anno1 == null){
>>>> 			
>>>> 		}
>>>> 		inLoop.remove(anno1);
>>>> 		for (Annotation anno2 : inLoop) {
>>>> 			if(isEqual(anno1,anno2)){
>>>> 				return true;
>>>> 			}
>>>> 		}
>>>> 	}
>>>> 	
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean isNull(Annotation... a){
>>>> 	for (Annotation annotation : a) {
>>>> 		if(annotation == null){
>>>> 			return true;
>>>> 		}
>>>> 	}
>>>>
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean isBigger(Annotation a, Annotation b){
>>>> 	if(isNull(a,b)){
>>>> 		return false;
>>>> 	}
>>>> 	if(a.getBegin() == b.getBegin() && a.getEnd() < b.getEnd()){
>>>> 		return true;
>>>> 	}		
>>>> 	if(b.getBegin() < a.getBegin() && a.getEnd() == b.getEnd()){
>>>> 		return true;
>>>> 	}
>>>> 	if(b.getBegin() < a.getBegin() && a.getEnd() < b.getEnd()){
>>>> 		return true;
>>>> 	}
>>>> 	
>>>> 	return false;
>>>> }
>>>> ==================================================================
>>>> public static boolean isBetween(Annotation a, Annotation b, Annotation
>>>> c){
>>>> 	if(isNull(a,b,c)){
>>>> 		return false;
>>>> 	}
>>>> 	Annotation min = getMin(a,b);
>>>> 	Annotation max = getMax(a,b);
>>>> 	
>>>> 	if(isOverlapping(a,c) || isOverlapping(b,c)){
>>>> 		return true;
>>>> 	}
>>>> 	
>>>> 	if(c.getBegin() > min.getEnd() && c.getEnd() < max.getBegin()){
>>>> 		return true;
>>>> 	}
>>>>
>>>> 	return false;	
>>>> }
>>>> ==================================================================
>>>> public static Annotation getMax(Annotation a, Annotation b){
>>>> 	isNull(a,b);
>>>> 	if(a.getBegin() >= b.getBegin()){
>>>> 		return a;
>>>> 	}
>>>> 	
>>>> 	return b;
>>>> }
>>>> ==================================================================
>>>> public static Annotation getMin(Annotation a, Annotation b){
>>>> 	isNull(a,b);
>>>> 	if(a.getEnd() <= b.getEnd()){
>>>> 		return a;
>>>> 	}
>>>> 	
>>>> 	return b;
>>>> }
>>>> ==================================================================
>>>>
>>>> I've posted all functions that are used by the rule. Actually it crushes
>>>> if I use more than 2 statements in the isEqual() call in $a5.
>>>> It works with !isEqual($a3,$a4) && !isEqual($a3,$a5) &&
>>>> !isEqual($a4,$a5)
>>>> but not with !isEqual($a3,$a4,$a5).
>>>>
>>>> So do you got an idea where the problem comes from?
>>>>
>>>> JB
>>>>
>>>>
>>>> ----- Ursprüngliche Mail -----
>>>> Von: "Wolfgang Laun" <wolfgang.laun at gmail.com>
>>>> An: "Rules Users List" <rules-users at lists.jboss.org>
>>>> Gesendet: Mittwoch, 6. März 2013 15:09:47
>>>> Betreff: Re: [rules-users] Cannot invoke method because
>>>> of	ArrayIndexOutOfBoundsException
>>>>
>>>> Nice try - but, please, don't. Kindly post the code that actually
>>>> causes your problem.
>>>>
>>>> -W
>>>>
>>>>
>>>> On 06/03/2013, Bojan Janisch <bojan.janisch at scai.fraunhofer.de> wrote:
>>>>> Hello Guys,
>>>>>
>>>>> sorry to bother you with this problem, but I'm out of ideas.
>>>>> I'm using Drools in textmining-context and in basic I have
>>>>> a function that checks 2 named entites for equality to
>>>>> ensure that the entities are all different and that the rules
>>>>> do work only on different named entity objects:
>>>>>
>>>>> public static boolean isEqual(Annotation a, Annotation b){
>>>>> if(a.equals(b)){
>>>>>    return true;
>>>>> }
>>>>> 	
>>>>> return false;
>>>>> }
>>>>>
>>>>> Sometimes there are conditions that need tests of more than
>>>>> 2 named entites. For this I've written a super method that
>>>>> calls the isEqual method in a loop:
>>>>>
>>>>> public static boolean isEqual(Annotation... a){
>>>>> ArrayList<Annotation> outLoop = new
>>>>> ArrayList<Annotation>(Arrays.asList(a));
>>>>> ArrayList<Annotation> inLoop = new
>>>>> ArrayList<Annotation>(Arrays.asList(a));
>>>>> 		
>>>>> for (Annotation anno1 : outLoop) {
>>>>>    inLoop.remove(anno1);
>>>>>    for (Annotation anno2 : inLoop) {
>>>>>       if(isEqual(anno1,anno2)){
>>>>>       return true;
>>>>>       }
>>>>>    }
>>>>> }
>>>>>
>>>>> return false;
>>>>> }
>>>>>
>>>>>
>>>>> My rules could (theoretically) now call the function
>>>>> eval(isEqual($ne1,$ne2)) or
>>>>> eval(isEqual($ne1,$ne2,$ne3) or even
>>>>> eval(isEqual($ne1,$ne2,$ne3,$ne4,$ne5)) and so on.
>>>>>
>>>>> So there starts my problem:
>>>>>
>>>>> Each time I'm getting an ArrayIndexOutOfBounds Exception from the
>>>>> second
>>>>> method that looks like this:
>>>>>
>>>>> java.lang.RuntimeException: cannot invoke method: isEqual
>>>>>         ...
>>>>> 	at java.lang.Thread.dispatchUncaughtException(Thread.java:1888)
>>>>> Caused by: java.lang.ArrayIndexOutOfBoundsException: 3
>>>>> 	at
>>>>> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.executeAll(MethodAccessor.java:149)
>>>>> 	at
>>>>> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.getValue(MethodAccessor.java:48)
>>>>> 	at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:108)
>>>>> 	at
>>>>> org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:38)
>>>>>         ...
>>>>>
>>>>> Could someone explain me what's wrong with my code? Thanks for any
>>>>> help.
>>>>>
>>>>> Greetings
>>>>> JB
>>>>> _______________________________________________
>>>>> rules-users mailing list
>>>>> rules-users at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>>>
>>>> _______________________________________________
>>>> rules-users mailing list
>>>> rules-users at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>>
>>>> _______________________________________________
>>>> rules-users mailing list
>>>> rules-users at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users



More information about the rules-users mailing list