org.springframework.beans.NotReadablePropertyException:bean类的无效属性。 Thymeleaf + SpringBoot

时间:2018-05-03 09:20:33

标签: java spring-mvc spring-boot thymeleaf

错误详细信息

页面工作正常,但是当我将错误的时间段放入两个输入startStatusDateendStatusDate时。验证检查类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;
    }

}

1 个答案:

答案 0 :(得分:0)

我已找出问题的根本原因。让我回答自问的问题。

在我的情况下, [kg.nurtelecom.dictionaries.entity.carordering]中的属性“startStatusDate”确实不存在 org.springframework.beans.NotReadablePropertyException 。驱动程序。让我解释一下它为什么会发生。要点是下面提到的Controller方法的参数序列不正确。

@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对象中的目标对象获取,验证工作正常。