当前位置: 首页 > 知识库问答 >
问题:

当简单JSON对象传递给控制器时,Optaplanner solutionClass entityCollectionProperty不应返回null错误

李永寿
2023-03-14

我正在从事optaplanner spring boot starter云平衡项目,并试图根据员工的技能水平为其分配班次。然而,当我将一个JSON对象传递给我的花名册控制器时,我会收到一个错误消息:

Java语言lang.IllegalArgumentException:solutionClass(class com.redhat.optaplannersbs.domain.花名册)的entityCollectionProperty(class com.redhat.optaplannersbs.domain.花名册上的bean属性移位列表)不应返回null。

我不明白问题是什么,因为我基本上在做与云平衡问题相同的事情,而且运行和解决得很好。

以下是我的employee类代码:

public class Employee {
    private int eid;

    private String name;

    private int skillLevel;

    public Employee(){

    }

    public int getEid() {
        return eid;
    }

    public void setEid(int eid) {
        this.eid = eid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // constraint getters and setters
    public int getSkillLevel() {
        return skillLevel;
    }

    public void setSkillLevel(int skillLevel) {
        this.skillLevel = skillLevel;
    }


}

以下是我的shift类代码:

 @PlanningEntity
public class Shift {
    private int sid;

    private LocalTime startTime;

    private LocalTime endTime;

    private int requiredSkillLevel;

    @PlanningVariable(valueRangeProviderRefs = "employee")
    private Employee employee;

    public Shift(){

    }

    public Shift(Long deptId, Long spotId, LocalTime startTime,
                 LocalTime endTime, Long employeeId){
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public int getSid() {
        return sid;
    }

    public void setSid(int sid) {
        this.sid = sid;
    }

    public LocalTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalTime startTime) {
        this.startTime = startTime;
    }

    public LocalTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalTime endTime) {
        this.endTime = endTime;
    }


    // planning variable getter and setter

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public int getRequiredSkillLevel() {
        return requiredSkillLevel;
    }

    public void setRequiredSkillLevel(int requiredSkillLevel) {
        this.requiredSkillLevel = requiredSkillLevel;
    }
}

这是我的花名册课程:

 @PlanningSolution
public class Roster {

    private List<Employee> employeeList;

    private List<Shift> shiftList;

    private HardSoftScore score;

    public Roster(List<Employee> employeeList, List<Shift> shiftList) {
        this.employeeList = employeeList;
        this.shiftList = shiftList;
    }

    @ProblemFactCollectionProperty
    @ValueRangeProvider(id="employee")
    public List<Employee> getEmployeeList() {
        return employeeList;
    }

    public void setEmployeeList(List<Employee> employeeList) {
        this.employeeList = employeeList;
    }

    @PlanningEntityCollectionProperty
    public List<Shift> getShiftList() {
        return shiftList;
    }

    public void setShiftList(List<Shift> shiftList) {
        this.shiftList = shiftList;
    }

    @PlanningScore
    public HardSoftScore getScore() {
        return score;
    }

    public void setScore(HardSoftScore score) {
        this.score = score;
    }
}

这是我的约束提供程序:

    public class ConstraintProvider implements org.optaplanner.core.api.score.stream.ConstraintProvider {
    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[]{
                requiredSkillLevelOfEmployeesForShifts(constraintFactory)
        };
    }

    private Constraint requiredSkillLevelOfEmployeesForShifts(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Shift.class)
                .groupBy(Shift::getEmployee, sum(Shift::getRequiredSkillLevel))
                .filter((employee, requiredSkillLevel) -> requiredSkillLevel > employee.getSkillLevel())
                .penalize("requiredSkillLevelForShifts",
                HardSoftScore.ONE_HARD,
                (employee, requiredSkillLevel) -> requiredSkillLevel - employee.getSkillLevel());
    }
}

这是我的控制器:

@RestController
@RequestMapping("/roster")
public class RosterController {

    @Autowired
    private SolverManager<Roster, UUID> solverManager;

    @PostMapping("/solve")
    public Roster solve(@RequestBody Roster problem) {
        UUID problemId = UUID.randomUUID();
        // Submit the problem to start solving
        SolverJob<Roster, UUID> solverJob = solverManager.solve(problemId, problem);
        Roster solution;
        try {
            // Wait until the solving ends
            solution = solverJob.getFinalBestSolution();
        } catch (InterruptedException | ExecutionException e) {
            throw new IllegalStateException("Solving failed.", e);
        }
        return solution;
    }

}

我通过post请求传递的JSON数据如下:

 {
   "shifts":[
      {
         "sid":0,
         "startTime":"09:00",
         "endTime":"18:00",
         "requiredSkillLevel": 12
      },
      {
         "sid":1,
         "startTime":"12:00",
         "endTime":"20:00",
         "requiredSkillLevel": 10
      },
      {
         "sid":2,
         "startTime":"18:00",
         "endTime":"00:00",
         "requiredSkillLevel": 10
      },
      {
         "sid": 3,
         "startTime":"09:00",
         "endTime":"18:00",
         "requiredSkillLevel": 12
      },
      {
         "sid":4,
         "startTime":"12:00",
         "endTime":"20:00",
         "requiredSkillLevel": 10
      },
      {
         "sid":5,
         "startTime":"18:00",
         "endTime":"00:00",
         "requiredSkillLevel":10
      },
      {
         "sid":6,
         "startTime":"09:00",
         "endTime":"18:00",
         "requiredSkillLevel": 12
      },
      {
         "sid":7,
         "startTime":"12:00",
         "endTime":"20:00",
         "requiredSkillLevel": 10
      },
      {
         "sid":8,
         "startTime":"18:00",
         "endTime":"00:00",
         "requiredSkillLevel":10
      },
      {
         "sid":9,
         "startTime":"09:00",
         "endTime":"18:00",
         "requiredSkillLevel": 12
      },
      {
         "sid":10,
         "startTime":"12:00",
         "endTime":"20:00",
         "requiredSkillLevel": 10
      },
      {
         "sid":11,
         "startTime":"18:00",
         "endTime":"00:00",
         "requiredSkillLevel":10
      },
      {
         "sid":12,
         "startTime":"09:00",
         "endTime":"18:00",
         "requiredSkillLevel": 12
      },
      {
         "sid":13,
         "startTime":"12:00",
         "endTime":"20:00",
         "requiredSkillLevel": 10
      },
      {
         "sid":14,
         "startTime":"18:00",
         "endTime":"00:00",
         "requiredSkillLevel":10
      }
   ],
   "employees":[
      {
         "eid":0,
         "name":"john",
         "skillLevel": 10
      },
      {
         "eid":1,
         "name":"elaine",
         "skillLevel": 2
      },
      {
         "eid":2,
         "name":"kieran",
         "skillLevel": 11
      },
      {
         "eid":3,
         "name":"maeve",
         "skillLevel": 10
      },
      {
         "eid":4,
         "name":"steve",
         "skillLevel": 9
      },
      {
         "eid":5,
         "name":"steve",
         "skillLevel": 9
      },
      {
         "eid":6,
         "name":"steve",
         "skillLevel": 15
      },
      {
         "eid":7,
         "name":"amy",
         "skillLevel": 11
      }
   ]
}

我不应该得到这个错误因为我正在做一个更简单的版本的云平衡应用程序如果有人能找出我哪里出错了这将是一个很大的帮助

共有1个答案

郭俊拔
2023-03-14

在调用solverManager之前,在RosterController中设置一个断点。求解(…) 。您将看到您的花名册实例有一个移位列表字段,该字段为null。

问题在于json解组输入数据,因为输入json中的命名不匹配。请注意,默认情况下,Spring Boot中的Jackson忽略不存在的属性,而不是失败禁食(我从未理解的设计决策)。有一个属性可以更改这种行为IIRC。

 类似资料:
  • 问题内容: 我正在使用.Net 4,MVC 3和jQuery v1.5做一些工作 我有一个JSON对象,它可以根据调用它的页面而改变。我想将对象传递给控制器​​。 我了解如果我创建一个自定义模型,例如 并在我的控制器中使用它,例如 并使用jQuery的.ajax方法传递对象,如下所示: 这工作正常,我的JSON对象已映射到我的C#对象。我想做的是通过一个可能更改的JSON对象。当它更改时,我不需要

  • 问题内容: 我有以下任意JSON对象(字段名称可能会更改)。 -- 我知道我可以像定义具有相同字段名的JSON对象那样定义类,但是我希望控制器接受具有不同字段名的任意JSON对象。 问题答案: 如果您想将自定义JSON对象传递给MVC操作,则可以使用此解决方案,它的工作原理很吸引人。 该解决方案的真正好处是,您不需要为每个参数组合定义一个新类,并且除此之外,您可以轻松地将对象转换为其原始类型。 更

  • 问题内容: 我正在尝试从字符串(从Web获取)中读取JSON,但返回。 具体来说,给我 考虑包含以下JSON字符串: 编辑:最终代码工作 特别感谢Sufian和Ved! 问题答案: “ id”和“ name”位于JSON对象内部,键为“ rikeard”。因此,您需要进行如下更改:

  • 问题内容: 我正在将一个对象传递给我的控制器,如下所示: 我的控制器将其视为它正在寻找的对象: 我的问题是我只想再传递一个字符串。我知道我可以制作特定于视图的模型,但我想知道是否可以执行以下操作: 我没有运气就尝试了以下方法: 但是复杂对象只是作为null来的。有没有办法我也可以传递对象和字符串? 问题答案: 尝试将字符串项添加到已有的JSON中。不要对其进行字符串化,否则它将发送一个大字符串,您

  • 但是,当我返回列表时,就像这段代码: 对于完全相同的API的列表返回类型的响应是正确的响应: [{“SellingPrice”:23000,“ID”:1,“Version”:1,“CreatedOn”:“25Feb 2019,05:53”,“LastUpdatedOn”:“25Feb 2019,05:53”}]

  • 我正在开发将复杂数据从window.open()传递到MVC Controller action方法参数的javascript功能。我能够通过构建查询字符串并从控制器中的[FromQuery]检索它们来实现它。 但我的问题是,我想将数据作为模型对象传递。在窗户里可以吗。打开() 下面是我的javascript代码 如您所见,我可以在URL中传递数据,但它似乎是公开的。那么,有没有办法传入var u