将对象插入Drools AbstractWorkingMemory时出现NullPointerException

时间:2013-12-17 21:52:08

标签: grails drools

我有一个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

0 个答案:

没有答案