我有一个Grails应用程序,我正在从v 1.3.7升级到2.3.4。我们有一些与Drools相关的功能在1.3.7中工作但不适用于2.3.4。我不太清楚问题是什么,因为Drools的依赖关系没有改变,我无法理解我所得到的错误,所以我希望有人可能会对可能导致这种情况的原因有所了解。错误。
这是代码的片段,它正在爆炸:
def session = ruleBase.newStatefulSession()
// put objects in session
objList.each {obj ->
session.insert(obj)
}
objList的内容是此类型的单个复合对象:
public class ConsumerPrequalificationComposite extends PrequalificationComposite {
InsuranceApplicationPerson insAppPerson
List<Person> applicants
public boolean isDisabled(String questionKey, String answer) {
return getAnswerToQuestion(questionKey).equals(answer);
}
String getAnswerToQuestion(String questionTypeOrUserDefinedKey) {
if (!person) {
return null
}
def answerList = person.answers ? person.answers : insAppPerson.answers
if (answerList) {
return getAnswerToQuestion(answerList, questionTypeOrUserDefinedKey)
} else {
return null
}
}
@Override
boolean benefitIncludesIndividualYoungerThanOnRequestedEffectiveDate(int years, int months, int days) {
if (super.benefitIncludesIndividualYoungerThanOnRequestedEffectiveDate(years, months, days)) {
return true
}
for (Person applicant in applicants) {
if (onDateWillBeYoungerThan(applicant, this.requestedEffectiveDate, years, months, days)) {
return true
}
}
return false
}
boolean isSingleApplicant() {
return applicants?.size() == 1
}
}
abstract class PrequalificationComposite extends DroolsComposite {
List planRuleHandles = []
Map<InsuranceType, Date> requestedEffectiveDates = [:]
Map insTypeFailureReasons = [:]
List selectedInsuranceTypes = []
String agentId
boolean validLocation
List<PaymentDurationType> paymentDurationTypes = []
// Added these because grails adds a get for booleans and drools looks for a is
boolean isValidLocation() {
return this.validLocation
}
boolean getValidLocation() {
return this.validLocation
}
void setValidLocation(boolean isValid) {
this.validLocation = isValid
}
void addPlan(String ruleHandle){
planRuleHandles << ruleHandle
}
void addPaymentDurationType(PaymentDurationType paymentDurationType) {
paymentDurationTypes.add(paymentDurationType)
}
void addFailureReason(InsuranceType insType, ContentKey contentKey) {
insTypeFailureReasons.put(insType, contentKey)
}
boolean hasFailureReason(InsuranceType insuranceType) {
return insTypeFailureReasons.get(insuranceType) != null
}
String getAnswerToQuestion(String questionTypeOrUserDefinedKey){
if(!person){
return null
}
return getAnswerToQuestion(person.answers, questionTypeOrUserDefinedKey)
}
Date getAnswerToQuestionAsDate(String questionTypeOrUserDefinedKey){
def answer = getAnswerToQuestion(questionTypeOrUserDefinedKey)
if (answer) {
Date dateAvailable = DateUtil.parse(answer)
return dateAvailable
}
return null
}
boolean olderThanOnJanOneOfRequestedEffectiveDateForInsuranceType(InsuranceType insType, int years, int months, int days) {
def requestedEffectiveDate = requestedEffectiveDates[insType] ?: new Date()
def cal = Calendar.getInstance()
cal.setTime(requestedEffectiveDate)
cal.set(Calendar.MONTH, 0)
cal.set(Calendar.DATE, 1)
def janOne = cal.getTime()
onDateWillBeOlderThan(janOne, years, months, days) // have to add 1 to the year becuase needs to be "older than"
}
boolean youngerThanOnRequestedEffective(int years, int months, int days) {
onDateWillBeYoungerThan(this.requestedEffectiveDate, years, months, days)
}
boolean olderThanOnRequestedEffective(int years, int months, int days) {
onDateWillBeOlderThan(this.requestedEffectiveDate, years, months, days)
}
boolean olderThanOnRequestedEffectiveForInsuranceType(InsuranceType insType, int years, int months, int days) {
onDateWillBeOlderThan(getEffectiveDate(insType), years, months, days)
}
boolean heightWeightAgeValid(int minYears, int minMonths, int maxYears, int maxMonths, int minHeight, int maxHeight, int minWeight, int maxWeight) {
def result = false
if (olderThanNow(minYears, minMonths, 0) && !olderThanNow(maxYears, maxMonths, 0)) {
if (person.height > minHeight && person.height < maxHeight && person.weight > minWeight && person.weight < maxWeight) {
result = true
}
}
return result
}
public void setState(String state) {
person.address.state = state
}
boolean checkEffectiveDates(InsuranceType insType, String dateAvailableString) {
def requestedEffectiveDate = this.requestedEffectiveDates[insType] ?: new Date()
def dateAvailable = DateUtil.parse(dateAvailableString)
return (dateAvailable.equals(requestedEffectiveDate) || dateAvailable.before(requestedEffectiveDate))
}
public abstract boolean isDisabled( String questionKey, String answer );
boolean hasSelectedInsuranceType(InsuranceType insType) {
return selectedInsuranceTypes.any { it == insType }
}
String getAgentId() {
return agentId
}
Date getEffectiveDate(InsuranceType insType) {
Date requestedEffectiveDate = this.requestedEffectiveDates[insType] ?: new Date()
return requestedEffectiveDate
}
/**
* Checks all individuals to be covered on the benefit and returns true if any of them are/will be younger than the
* specified age as of the requested effective date
*/
boolean benefitIncludesIndividualYoungerThanOnRequestedEffectiveDate(int years, int months, int days) {
if (person && onDateWillBeYoungerThan(person, this.requestedEffectiveDate, years, months, days)) {
return true
}
for (InsuranceApplicationPlanPerson planPerson in insuranceApplicationPlan?.insuranceApplicationPlanPersons) {
if (onDateWillBeYoungerThan(planPerson.insuranceApplicationPerson.person, this.requestedEffectiveDate, years, months, days)) {
return true
}
}
return false
}
boolean isFfm() {
return person.ffmEligibilityInfo != null
}
boolean isQhpEligibility() {
return person.ffmEligibilityInfo ? person.ffmEligibilityInfo.qhpEligibilityIndicator : false
}
boolean isCsrEligibility() {
return person.ffmEligibilityInfo ? person.ffmEligibilityInfo.csrEligibilityIndicator : false
}
}
abstract class DroolsComposite {
InsuranceApplicationPlan insuranceApplicationPlan
Person person
Date requestedEffectiveDate
String getAnswerToQuestion(Collection<Answer> answers, String questionTypeOrUserDefinedKey) {
def answerString = null
def answer = null
try{
def questionType = QuestionType.valueOf(QuestionType.class, questionTypeOrUserDefinedKey)
answer = answers.find {
it.question.questionType == questionType
}
} catch (Exception e){
Logger.getLogger(this.class).debug("QuestionType could not be determined for $questionTypeOrUserDefinedKey this is not an error. The value could be referencing a question user defined key value")
}
if (!answer){
answer = answers.find {
if (it.question == null) {
println "OH MY GOLLY!"
}
it.question.userDefinedKey.equals(questionTypeOrUserDefinedKey)
}
}
if (answer) {
if (answer.question.multiListAnswerType == PossibleAnswerType.USER_CONFIGURED) {
def possibleAnswer = answer.question.possibleAnswers.find {
it.id.toString().equals(answer.stringValue)
}
answerString = possibleAnswer.userDefinedKey
} else {
answerString = answer.toString()
}
}
return answerString
}
boolean olderThanNow(int years, int months, int days) {
onDateWillBeOlderThan(new Date(), years, months, days)
}
boolean onDateWillBeOlderThan(Date date, int years, int months, int days) {
def result = false
def target = Calendar.getInstance()
target.setTime(date)
target.add(Calendar.HOUR, 1)
def ageCal = Calendar.getInstance()
ageCal.setTime(person.dateOfBirth)
ageCal.add(Calendar.YEAR, years)
ageCal.add(Calendar.MONTH, months)
ageCal.add(Calendar.DAY_OF_MONTH, days)
if (ageCal.before(target)) {
result = true
}
return result
}
boolean youngerThanNow(int years, int months, int days) {
onDateWillBeYoungerThan(new Date(), years, months, days)
}
boolean onDateWillBeYoungerThan(Date date, int years, int months, int days) {
def result = false
def target = Calendar.getInstance()
target.setTime(date)
def ageCal = Calendar.getInstance()
ageCal.setTime(person.dateOfBirth)
ageCal.add(Calendar.YEAR, years)
ageCal.add(Calendar.MONTH, months)
ageCal.add(Calendar.DAY_OF_MONTH, days)
if (ageCal.after(target)) {
result = true
}
return result
}
boolean onDateWillBeYoungerThan(Person personToCheck, Date date, int years, int months, int days) {
Calendar targetDate = Calendar.getInstance()
targetDate.setTime(date)
Calendar dateAgeReached = Calendar.getInstance()
dateAgeReached.setTime(personToCheck.dateOfBirth)
dateAgeReached.add(Calendar.YEAR, years)
dateAgeReached.add(Calendar.MONTH, months)
dateAgeReached.add(Calendar.DAY_OF_MONTH,days)
return dateAgeReached.after(targetDate)
}
boolean olderThanOnJanOneOfRequestedEffective(int years, int months, int days) {
def cal = Calendar.getInstance()
cal.setTime(this.requestedEffectiveDate)
cal.set(Calendar.MONTH, 0)
cal.set(Calendar.DATE, 1)
def janOne = cal.getTime()
onDateWillBeOlderThan(janOne, years, months, days) // have to add 1 to the year becuase needs to be "older than"
}
boolean getDisability() {
return insuranceApplicationPlan != null ? insuranceApplicationPlan.policyOwner?.insuranceApplicationPerson?.disability : null
}
Relationship getRelationshipToOwner() {
return person.relationshipToOwner
}
Date getRequestedEffectiveDate() {
return requestedEffectiveDate
}
public InsuranceApplicationPlan getInsuranceApplicationPlan() {
return insuranceApplicationPlan
}
public Date getDateOfBirth() {
return person.dateOfBirth
}
public String getCsrLevel() {
return person?.ffmEligibilityInfo?.csrLevel ?: null
}
public Integer getRequestedEffectiveDateYear() {
Calendar cal = Calendar.getInstance()
if (getRequestedEffectiveDate() != null) {
return 0
}
cal.setTime(insuranceApplicationPlan.getEffectiveDateOrRequestedIfNull())
return cal.get(Calendar.YEAR)
}
}
ruleBase是一个ReteooRuleBase,session是一个AbstractWorkingMemory。我得到的例外情况发生在插入调用上,它是:
java.lang.NullPointerException
at org.drools.core.rule.PredicateConstraint.isAllowed(PredicateConstraint.java:299)
at org.drools.core.reteoo.AlphaNode.assertObject(AlphaNode.java:134)
at org.drools.core.reteoo.CompositeObjectSinkAdapter.doPropagateAssertObject(CompositeObjectSinkAdapter.java:502)
at org.drools.core.reteoo.CompositeObjectSinkAdapter.propagateAssertObject(CompositeObjectSinkAdapter.java:387)
at org.drools.core.reteoo.ObjectTypeNode.assertObject(ObjectTypeNode.java:288)
at org.drools.core.reteoo.EntryPointNode.assertObject(EntryPointNode.java:260)
at org.drools.core.common.NamedEntryPoint.insert(NamedEntryPoint.java:360)
at org.drools.core.common.NamedEntryPoint.insert(NamedEntryPoint.java:279)
at org.drools.core.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:1149)
at org.drools.core.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:1093)
在将其他对象插入会话时似乎确实有效,但是我试图插入的这个特定对象并没有什么特别之处,只是它扩展了另一个抽象类,而后者又扩展了另一个抽象类。但是,所有这些都适用于Grails 1.3.7。我已经尝试过调试Drools源码,但我也没有真正获得任何好的线索。
我正在使用Drools 6.0.0.Final