[jboss-jira] [JBoss JIRA] (DROOLS-1071) NPE's stacktracke for an MvelConstraint.evaluate() should give a line number from the source DRL file

Geoffrey De Smet (JIRA) issues at jboss.org
Fri Feb 26 11:45:01 EST 2016


     [ https://issues.jboss.org/browse/DROOLS-1071?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Geoffrey De Smet moved PLANNER-541 to DROOLS-1071:
--------------------------------------------------

               Project: Drools  (was: OptaPlanner)
                   Key: DROOLS-1071  (was: PLANNER-541)
            Issue Type: Enhancement  (was: Bug)
              Workflow: GIT Pull Request workflow   (was: classic default workflow)
           Component/s: core engine
                            (was: optaplanner-core)
    Steps to Reproduce:   (was: DRL:

{code:java}
package com.rdthree.plenty.services.activities.planner;
    dialect "java"

import org.optaplanner.core.api.score.buildin.simple.SimpleScoreHolder;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;

import org.joda.time.Interval;
import org.joda.time.DateTime;
import org.apache.commons.lang.time.DateUtils;

import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.Solution;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import com.rdthree.plenty.config.GeneralPrefs;
import com.rdthree.plenty.services.activities.helpers.dtos.TaskPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.TaskResourceAllocationPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.SkillsAndRatesPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.EquipmentEquipmentTypesPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.ProductPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.LabourDayOffPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.OnHandForProduct;
import com.rdthree.plenty.services.activities.planner.TaskRequirementsMapper;
import com.rdthree.plenty.domain.users.LabourDayOff.ApprovalState;
import com.rdthree.plenty.services.activities.planner.ScheduleState;
 
global HardSoftScoreHolder scoreHolder;


dialect "java" 
dialect "mvel" 
// ############################################################################
// Soft constraints
// ############################################################################

// DOC
rule "setAllConflictingToFalseFirst"
	salience 100
	when
		$allocation : TaskResourceAllocationPlannerDto()
	then
        $allocation.setScheduleState(ScheduleState.SCHEDULING);
        $allocation.setLabourDayOffConflict(null);
        $allocation.setProductShortage(0);
end

rule "taskDateChangeRule"
    when
        TaskPlannerDto($taskId : id, $taskStart : interval.getStart().toDate())
        TaskRequirementsMapper( taskId == $taskId,  $taskReqStartMS : startDate.getTime(), startDate.getTime() != $taskStart.getTime())
    then
        scoreHolder.addSoftConstraintMatch(kcontext, Math.round(Math.abs($taskReqStartMS - $taskStart.getTime()) / 1000 / 60 / 60) * -100);
end

rule "taskPlanIndexChangeRule"
	when
		$task1 : TaskPlannerDto($task1Activity : activity, $task1Plan : activity.getPlan(), $task1Start : interval.getStart().toDate())
		TaskPlannerDto(!activity.equals($task1Activity), activity.getPlan().equals($task1Plan), $task1Activity.indexInPlan > activity.indexInPlan, interval.getStart().toDate() < $task1Start)
		TaskPlannerDto(!activity.equals($task1Activity), activity.getPlan().equals($task1Plan), $task1Activity.indexInPlan < activity.indexInPlan, interval.getStart().toDate() < $task1Start)
	then
		scoreHolder.addHardConstraintMatch(kcontext, -100000);
end

rule "taskLengthChangeRule"
    when
        TaskPlannerDto($taskId : id, $taskLength : interval.toPeriod().getDays())
        TaskRequirementsMapper( taskId == $taskId,  $taskReqLength : length, length!=$taskLength)
    then
        scoreHolder.addSoftConstraintMatch(kcontext, Math.abs($taskReqLength - $taskLength) * -1000);
end

rule "taskResourceChangeRule"
	when
		$allocation : TaskResourceAllocationPlannerDto( $taskId : taskId  )
		$mapper : TaskRequirementsMapper( taskId == $taskId )
		TaskRequirement( resourceClass.equals($allocation.getResourceClass()), resourceTypeOrSkill.getId() == $allocation.getResourceTypeId(), originalResource.getId() != $allocation.getResource().getId()) from $mapper.getRequirements()
	then
        scoreHolder.addSoftConstraintMatch(kcontext, -10);
end

// This rule checks if the allocated resource has already been allocated to the same task
rule "duplicateResourceAllocation"
	when
		TaskPlannerDto($taskId : id)
		TaskResourceAllocationPlannerDto($alloc1Id : id, taskId == $taskId, $alloc1Resource : resource)
		TaskResourceAllocationPlannerDto(id != $alloc1Id, taskId == $taskId, resource.getId() == $alloc1Resource.getId())
	then
		scoreHolder.addHardConstraintMatch(kcontext, -100000);
end

// This rule creates a constraint based on overlap of two tasks which use the 
// same labourer at the same time. The constraint is multipled by the size of the overlap in days
rule "TaskLabourerTimeOverlap"
    when
        $task1 : TaskPlannerDto($task1Interval : interval)
        $task1ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task1.id, resource instanceof SkillsAndRatesPlannerDto, $task1UserId : resource.getUserId())
        
        $task2 : TaskPlannerDto($task1.id != id, $task1Interval.overlaps(interval))
        $task2ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task2.id, resource instanceof SkillsAndRatesPlannerDto, resource.getUserId().equals($task1UserId))
    then
        scoreHolder.addHardConstraintMatch(kcontext, $task1Interval.overlap($task2.getInterval()).toPeriod(org.joda.time.PeriodType.days()).getDays() * -1);
        $task1ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
        $task2ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
        $task1.setState(ScheduleState.CONFLICT);
        $task2.setState(ScheduleState.CONFLICT);
end

// This rule creates a constraint based on overlap of a task and it's labour days off
// The constraint is multipled by the size of the overlap in days
rule "TaskLabourerDayOffOverlap"
    when
        $task1 : TaskPlannerDto($taskInterval : interval)
        $task1ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task1.id, resource instanceof SkillsAndRatesPlannerDto,  $task1UserId : resource.getUserId())
        $labourDayOff : LabourDayOffPlannerDto(userId == $task1UserId, $taskInterval.contains(new DateTime(date).plusMinutes(15)), state.equals(ApprovalState.APPROVED))
    then
        scoreHolder.addHardConstraintMatch(kcontext, -1);
		$task1ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
		$task1ResourceAllocation.setLabourDayOffConflict($labourDayOff.getDate().toDate());
        $task1.setState(ScheduleState.CONFLICT);
end

// This rule creates a constraint based on overlap of two tasks which use the 
// same equipment at the same time. The constraint is multipled by the size of the overlap in days
rule "TaskEquipmentTimeOverlap"
    when
        $task1 : TaskPlannerDto($task1Interval : interval)
        $task1ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task1.id, resource instanceof EquipmentEquipmentTypesPlannerDto, $task1EquipmentId : resource.getEquipmentId())
		
		$task2 : TaskPlannerDto($task1.id != id, $task1Interval.overlaps(interval))
        $task2ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task2.id, resource instanceof EquipmentEquipmentTypesPlannerDto, resource.getEquipmentId() == $task1EquipmentId)
    then
        scoreHolder.addHardConstraintMatch(kcontext, $task1Interval.overlap($task2.getInterval()).toPeriod(org.joda.time.PeriodType.days()).getDays() * -1);
        $task1ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
        $task2ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
        $task1.setState(ScheduleState.CONFLICT);
        $task2.setState(ScheduleState.CONFLICT);
end

// This rule create a constraint based on product defficiency for a product at a taks's start date
rule "TaskProductShortage"
	when
		$task : TaskPlannerDto( $taskId : id, $taskNeedsProductBy : interval.getStart().plusDays(0).withTimeAtStartOfDay())
		$allocation : TaskResourceAllocationPlannerDto( taskId == $taskId, resource instanceof ProductPlannerDto)
		OnHandForProduct(date.compareTo($taskNeedsProductBy) == 0 , productId == $allocation.resource.getId(), $onHandAmount : amount, amount - $allocation.amount  <= 0)
	then
		scoreHolder.addHardConstraintMatch(kcontext, $allocation.getAmount() * -1);
		$allocation.setScheduleState(ScheduleState.CONFLICT);
		$allocation.setProductShortage($allocation.getAmount());
		$task.setState(ScheduleState.CONFLICT);
end

{code}

added domain classes as attachments

)
     Affects Version/s: 6.4.0.Beta2
                        6.3.0.Final
                            (was: 6.3.0.Final)
                            (was: 6.4.0.Beta2)


> NPE's stacktracke for an MvelConstraint.evaluate() should give a line number from the source DRL file
> -----------------------------------------------------------------------------------------------------
>
>                 Key: DROOLS-1071
>                 URL: https://issues.jboss.org/browse/DROOLS-1071
>             Project: Drools
>          Issue Type: Enhancement
>          Components: core engine
>    Affects Versions: 6.4.0.Beta2, 6.3.0.Final
>         Environment: JDK: Java 7
> OS: Mac OSX 10.10.2
> IDE: Spring Tool Suite 3.6.4
>            Reporter: Ido Flax
>            Assignee: Geoffrey De Smet
>         Attachments: AbstractPlannerDto.java, activity-scoring.drl, EquipmentEquipmentTypesPlannerDto.java, LabourDayOffPlannerDto.java, OnHandForProduct.java, ProductInventoryTransactionPlannerDto.java, ProductPlannerDto.java, SkillsAndRatesPlannerDto.java, TaskPlannerDto.java, TaskResourceAllocationPlannerDto.java, TaskResourcePlannerDto.java, UserPlannerDto.java
>
>
> The attached code generates an NPE when running optaplanner/drools, but that stacktrace doesn't tell me which DRL line is responsible for it.
> Stacktrace:
> {code:java}
> Caused by: java.lang.NullPointerException: null
> 	at ConditionEvaluatoreaa3997683d949e28ce6eaf6feca0ced.evaluate(Unknown Source)  <================ No source DRL line
> 	at org.drools.core.rule.constraint.MvelConstraint.evaluate(MvelConstraint.java:258)
> 	at org.drools.core.rule.constraint.MvelConstraint.isAllowedCachedLeft(MvelConstraint.java:226)
> 	at org.drools.core.common.DoubleBetaConstraints.isAllowedCachedLeft(DoubleBetaConstraints.java:111)
> 	at org.drools.core.phreak.PhreakJoinNode.doLeftInserts(PhreakJoinNode.java:112)
> 	at org.drools.core.phreak.PhreakJoinNode.doNode(PhreakJoinNode.java:75)
> 	at org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:547)
> 	at org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:533)
> 	at org.drools.core.phreak.RuleNetworkEvaluator.evalNode(RuleNetworkEvaluator.java:369)
> 	at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:329)
> 	at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:163)
> 	at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:120)
> 	at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:194)
> 	at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:73)
> 	at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1003)
> 	at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1346)
> 	at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1284)
> 	at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1303)
> 	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1293)
> 	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1274)
> 	at org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.calculateScore(DroolsScoreDirector.java:84)
> 	at org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.solvingStarted(BestSolutionRecaller.java:70)
> 	at org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:197)
> 	at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:175)
> {code}



--
This message was sent by Atlassian JIRA
(v6.4.11#64026)


More information about the jboss-jira mailing list