handle IllegalArgumentException when fact type does not match parameter type

pull/94/head
Mahmoud Ben Hassine 8 years ago
parent 90ec13b00a
commit 9124cdddc3

@ -23,11 +23,11 @@
*/ */
package org.jeasy.rules.core; package org.jeasy.rules.core;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.annotation.Action; import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition; import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Priority; import org.jeasy.rules.annotation.Priority;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule; import org.jeasy.rules.api.Rule;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
@ -36,6 +36,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.*; import java.util.*;
import static java.lang.String.format;
/** /**
* Main class to create rule proxies from annotated objects. * Main class to create rule proxies from annotated objects.
* *
@ -87,7 +89,12 @@ public class RuleProxy implements InvocationHandler {
Facts facts = (Facts) args[0]; Facts facts = (Facts) args[0];
Method conditionMethod = getConditionMethod(); Method conditionMethod = getConditionMethod();
List<Object> actualParameters = getActualParameters(conditionMethod, facts); List<Object> actualParameters = getActualParameters(conditionMethod, facts);
return conditionMethod.invoke(target, actualParameters.toArray()); // validated upfront try {
return conditionMethod.invoke(target, actualParameters.toArray()); // validated upfront
} catch (IllegalArgumentException e) {
String error = "Types of injected facts in method '%s' in rule '%s' do not match parameters types";
throw new RuntimeException(format(error, conditionMethod.getName(), target.getClass().getName()), e);
}
} }
if (methodName.equals("execute")) { if (methodName.equals("execute")) {
for (ActionMethodOrderBean actionMethodBean : getActionMethodBeans()) { for (ActionMethodOrderBean actionMethodBean : getActionMethodBeans()) {
@ -121,19 +128,18 @@ public class RuleProxy implements InvocationHandler {
private List<Object> getActualParameters(Method method, Facts facts) { private List<Object> getActualParameters(Method method, Facts facts) {
List<Object> actualParameters = new ArrayList<>(); List<Object> actualParameters = new ArrayList<>();
Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for(Annotation[] ann : parameterAnnotations){ for (Annotation[] annotations : parameterAnnotations) {
if(ann.length == 1){ if (annotations.length == 1) {
String factName = ((Fact) (ann[0])).value(); //validated upfront. String factName = ((Fact) (annotations[0])).value(); //validated upfront.
Object fact = facts.get(factName); Object fact = facts.get(factName);
if(fact == null){ if (fact == null) {
throw new RuntimeException(String.format("No fact named %s found in known facts", factName)); throw new RuntimeException(format("No fact named %s found in known facts", factName));
} }
actualParameters.add(fact); actualParameters.add(fact);
} else { } else {
actualParameters.add(facts); //validated upfront, there may be only one parameter not annotated and which is of type Facts.class actualParameters.add(facts); //validated upfront, there may be only one parameter not annotated and which is of type Facts.class
} }
} }
return actualParameters; return actualParameters;
} }

@ -32,6 +32,8 @@ import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine; import org.jeasy.rules.api.RulesEngine;
import org.junit.Test; import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class AnnotatedRulesTest { public class AnnotatedRulesTest {
@Test @Test
@ -40,10 +42,23 @@ public class AnnotatedRulesTest {
facts.add("rain", true); facts.add("rain", true);
facts.add("age", 18); facts.add("age", 18);
Rules rules = new Rules( WeatherRule weatherRule = new WeatherRule();
new WeatherRule(), AgeRule ageRule = new AgeRule();
new AgeRule() Rules rules = new Rules(weatherRule, ageRule);
);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
assertThat(ageRule.isExecuted()).isTrue();
assertThat(weatherRule.isExecuted()).isTrue();
}
@Test(expected = RuntimeException.class)
public void whenFactTypeDoesNotMatchParameterType_thenShouldThrowRuntimeException() throws Exception {
Facts facts = new Facts();
facts.add("age", "foo");
Rules rules = new Rules(new AgeRule());
RulesEngine rulesEngine = new DefaultRulesEngine(); RulesEngine rulesEngine = new DefaultRulesEngine();
@ -53,22 +68,30 @@ public class AnnotatedRulesTest {
@Rule @Rule
class AgeRule { class AgeRule {
private boolean isExecuted;
@Condition @Condition
public boolean isAdult(@Fact("age") int age) { public boolean isAdult(@Fact("age") int age) {
return age >= 18; return age >= 18;
} }
@Action @Action
public void then() { public void printYourAreAdult() {
System.out.println("You are an adult"); System.out.println("You are an adult");
isExecuted = true;
} }
public boolean isExecuted() {
return isExecuted;
}
} }
@Rule @Rule
class WeatherRule { class WeatherRule {
private boolean isExecuted;
@Condition @Condition
public boolean itRains(@Fact("rain") boolean rain) { public boolean itRains(@Fact("rain") boolean rain) {
return rain; return rain;
@ -77,7 +100,11 @@ public class AnnotatedRulesTest {
@Action @Action
public void takeAnUmbrella(Facts facts) { public void takeAnUmbrella(Facts facts) {
System.out.println("It rains, take an umbrella!"); System.out.println("It rains, take an umbrella!");
isExecuted = true;
} }
public boolean isExecuted() {
return isExecuted;
}
} }
} }

Loading…
Cancel
Save