错误详情
该页面工作正常,但是当我在两个输入startStatusDate
和endStatusDate
中输入了不正确的时间段时。验证检查类DriverHistoryValidator
中的错误时发生错误。
我在调试器中看到分配后生成的异常
errors.rejectValue("startStatusDate",
"co.driverHistoryStatusPeriod.notpermitted")
方法中
validate(Object o, Errors errors)
请看下面
我究竟做错了什么?
2018-05-03 11:03:54.364 ERROR 6234 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'startStatusDate' of bean class [kg.nurtelecom.dictionaries.entity.carordering.Driver]: Bean property 'startStatusDate' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?] with root cause
org.springframework.beans.NotReadablePropertyException: Invalid property 'startStatusDate' of bean class [kg.nurtelecom.dictionaries.entity.carordering.Driver]: Bean property 'startStatusDate' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
前端
在Thymeleaf中实现的前端:
<form id="statusSheduleForm" class="form-horizontal" th:action="@{/driver/saveStatusSchedule}"
th:method="POST"
th:object="${driverHistory}">
<div class="form-group col-md-7">
<div class="input-group date">
<label class="validation-message" for="statusdatetimepicker1"
th:if="${#fields.hasErrors('startStatusDate')}"
th:errors="*{startStatusDate}"></label>
<input type="text" placeholder="Время начала" th:field="*{startStatusDate}"
id="statusdatetimepicker1"/>
<input type="text" placeholder="Время окончания" th:field="*{endStatusDate}"
id="statusdatetimepicker2"/>
<select id="status-select" required="required" th:field="*{driverStatus}">
<option th:each="item:${statuses}"
th:value="${item.id}"
th:text="${item.name}"></option>
</select>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Сохранить</button>
<a th:href="@{/driver/index}" class="btn btn-default">Закрыть</a>
</div>
</form>
后端:
控制者
@RequestMapping(value = "/saveStatusSchedule", method = RequestMethod.POST)
public ModelAndView saveStatusSchedule(@ModelAttribute DriverHistory driverHistory, Driver driver,
BindingResult bindingResult) {
ModelAndView modelAndView = getModelsViews();
Driver sessionDriver = (Driver) modelAndView.getModel().get("driver");
if (sessionDriver != null) {
sessionDriver.setMenu1Act();
driverHistory.setDriver(sessionDriver);
driverHistoryValidator.validate(driverHistory, bindingResult);
if (bindingResult.hasErrors()) {
return getModelsViews();
}
if (driverHistory.getDriverShift() != null) {
sessionDriver.setMenu2Act();
}
driverHistory.setDriver(sessionDriver);
driverHistoryService.save(driverHistory);
return getModelsViews();
} else {
driver.setMenu0Act();
modelAndView.addObject("failMessage", "Водитель не создан");
modelAndView.addObject("driver", driver);
return modelAndView;
}
}
验证器:
@Component
public class DriverHistoryValidator implements Validator {
@Autowired
DriverHistoryService driverHistoryService;
@Override
public boolean supports(Class<?> aClass) {
return DriverHistory.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
DriverHistory driverHistory = (DriverHistory) o;
if (driverHistoryService.isExistDriverStatusInPeriodOf(driverHistory)) {
errors.rejectValue("startStatusDate", "co.driverHistoryStatusPeriod.notpermitted");
}
}
}
实体:
@Entity
@Table(name = "CO_DRIVER_HISTORY")
public class DriverHistory extends BaseEntity {
@DateTimeFormat(pattern = "dd.MM.yyyy HH:mm")
@Column(name = "startStatusDate")
private Date startStatusDate;
@DateTimeFormat(pattern = "dd.MM.yyyy HH:mm")
@Column(name = "endStatusDate")
private Date endStatusDate;
@DateTimeFormat(pattern = "dd.MM.yyyy HH:mm")
@Column(name = "startShiftDate")
private Date startShiftDate;
@DateTimeFormat(pattern = "dd.MM.yyyy HH:mm")
@Column(name = "endShiftDate")
private Date endShiftDate;
@ManyToOne
@JoinColumn(name = "DriverId")
private Driver driver;
@ManyToOne
@JoinColumn(name = "DriverStatusId")
private DriverStatus driverStatus;
@ManyToOne
@JoinColumn(name = "DriverShiftId")
private DriverShift driverShift;
public DriverHistory() {
}
public Date getStartStatusDate() {
return startStatusDate;
}
public void setStartStatusDate(Date startStatusDate) {
this.startStatusDate = startStatusDate;
}
public Date getEndStatusDate() {
return endStatusDate;
}
public void setEndStatusDate(Date endStatusDate) {
this.endStatusDate = endStatusDate;
}
public Date getStartShiftDate() {
return startShiftDate;
}
public void setStartShiftDate(Date startShiftDate) {
this.startShiftDate = startShiftDate;
}
public Date getEndShiftDate() {
return endShiftDate;
}
public void setEndShiftDate(Date endShiftDate) {
this.endShiftDate = endShiftDate;
}
public Driver getDriver() {
return driver;
}
public void setDriver(Driver driver) {
this.driver = driver;
}
public DriverStatus getDriverStatus() {
return driverStatus;
}
public void setDriverStatus(DriverStatus driverStatus) {
this.driverStatus = driverStatus;
}
public DriverShift getDriverShift() {
return driverShift;
}
public void setDriverShift(DriverShift driverShift) {
this.driverShift = driverShift;
}
}
最佳答案
我已经找出问题的根本原因。让我回答自问的问题。
在我的情况下,类[kg.nurtelecom.dictionaries.entity.carordering.Driver]中实际上不存在自属性“ startStatusDate”以来生成的org.springframework.beans.NotReadablePropertyException
。让我解释一下为什么会发生。重点是以下提到的控制器方法的参数顺序不正确。
@RequestMapping(value = "/saveStatusSchedule", method = RequestMethod.POST)
public ModelAndView saveStatusSchedule(@ModelAttribute
DriverHistory driverHistory,
Driver driver,
BindingResult bindingResult)
在参数中声明的
BindingResult
对象获取先前声明的参数作为目标对象。 See debug in screen shot。在我的验证器类DriverHistoryValidator
中,将错误值设置为不是目标对象的类的字段。在我简单地更改上述方法中的参数顺序之后,该问题已解决:@RequestMapping(value = "/saveStatusSchedule", method = RequestMethod.POST)
public ModelAndView saveStatusSchedule(DriverHistory driverHistory,
BindingResult bindingResult,
Driver driver)
对参数重新排序后,将获得类
DriverHistory
作为BindinResult
对象中的目标对象,并且验证可以正常进行。