gpt4 book ai didi

java - org.springframework.beans.NullValueInNestedPathException : auto-grow nested property path in Spring MVC 3. 2.8

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:35:34 25 4
gpt4 key购买 nike

我有一个基于 Spring Web 模型- View - Controller (MVC) 框架的项目。 Spring Web模型- View - Controller (MVC)框架的版本是3.2.8。

这门课

public class DeviceForm {

Device device;

List<String> selectedItems = Collections.emptyList();

public DeviceForm() {
super();
}

public Device getDevice() {
return device;
}

public void setDevice(Device device) {
this.device = device;
}

public List<String> getSelectedItems() {
return selectedItems;
}

public void setSelectedItems(List<String> selectedItems) {
this.selectedItems = selectedItems;
}


}

还有这个

public class Device implements java.io.Serializable {

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CRITERIA")
private BaseCriteria criteria;

public BaseCriteria getCriteria() {
return criteria;
}

public void setCriteria(BaseCriteria criteria) {
this.criteria = criteria;
}
}

还有这个

@Entity
@Table(name = "CRITERIA")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING)
@SequenceGenerator(name = "seqCriteria", sequenceName = "SEQ_CRITERIA", allocationSize = 1)
public abstract class BaseCriteria {

public BaseCriteria() {
super();
}

private Long id;
private String code;
private Date adoptionDate;
private Date expirationDate;

@Transient
public abstract String getGroupKey();

@Transient
public abstract Long getGroupId();

@Transient
public abstract String getRefColumnName();

@Id
@Column(name = "ID", unique = true, nullable = true)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqCriteria")
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@Column(name = "CODE")
public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

@Column(name = "ADOPTION_DATE")
@Temporal(TemporalType.TIMESTAMP)
public Date getAdoptionDate() {
return adoptionDate;
}

public void setAdoptionDate(Date adoptionDate) {
this.adoptionDate = adoptionDate;
}

@Column(name = "EXPIRATION_DATE")
@Temporal(TemporalType.TIMESTAMP)
public Date getExpirationDate() {
return expirationDate;
}

@Transient
public boolean isExpired() {
return getExpirationDate().before(new Date());
}

public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}


@Override
public String toString() {
return "BaseCriteria [id=" + id + ", code=" + code + ", adoptionDate="
+ adoptionDate + ", expirationDate=" + expirationDate + "]";
}


}

和 JSP

<form:form  commandName="deviceForm"
name="deviceForm"
id="deviceFormId"
method="post"
action="${contextPath}/newdesign/manage/device/${deviceForm.device.id}"
htmlEscape="yes">

<div class="col-sm-6 text-right">
<button class="btn btn-primary" type="submit">Save device</button>
</div>
</div>

<c:forEach items="${deviceForm.device.productGroup.criteria}" var="criteria">
<div class="row">
<div class="col-md-3">
<form:radiobutton path="device.criteria.id" value="${criteria.id}"/>
<label for="basic-url">Criteria:</label>
<input value="${criteria.code}" disabled="disabled" class="form-control"/>
</div>
<div class="col-md-3">
<label for="basic-url">Adoption date:</label>
<input value="<fmt:formatDate type="date" value="${criteria.adoptionDate}" />" disabled="disabled" class="form-control"/>
</div>
<div class="col-md-3">
<label for="basic-url">Expiration Date:</label>
<input value="<fmt:formatDate type="date" value="${criteria.expirationDate}" />" disabled="disabled" class="form-control"/>
</div>
</div>
</c:forEach>
</form:form>

Controller :

/**
* @throws Exception
*
*/
@RequestMapping(value = { "/newdesign/manage/device/{appId}",
"/newdesign/manage/device/{appId}/"}, method = {RequestMethod.GET})
public String viewDevicesWithStatus(
@ModelAttribute("deviceForm") DeviceForm deviceForm,
@PathVariable Long appId,
HttpServletRequest request,
Model model ) throws Exception {

Device device = manageLicenseService.getDeviceById(appId, true);

if (device.getCriteria()==null) {
device.setCriteria(device.getProductGroup().getCriteria().get(0));
}

deviceForm.setDevice(device);
fillModel (model, request, device);

return "cbViewDeviceInfo";
}

/**
* @throws Exception
*
*/
@RequestMapping(value = { "/newdesign/manage/device/{appId}",
"/newdesign/manage/device/{appId}/"}, method = {RequestMethod.POST})
public String saveDevicesWithStatus(
@ModelAttribute("deviceForm") DeviceForm deviceForm,
@PathVariable Long appId,
HttpServletRequest request,
Model model ) throws Exception {

Device device = manageLicenseService.getDeviceById(deviceForm.getDevice().getId());

if (device.getCriteria()==null) {
device.setCriteria(device.getProductGroup().getCriteria().get(0));
}

//TODO: audit
device.updateDevice(deviceForm.getDevice());
manageLicenseService.saveDevice(device);

if (device.getCriteria()==null) {
device.setCriteria(device.getProductGroup().getCriteria().get(0));
}

deviceForm.setDevice(device);
fillModel (model, request, device);


return "cbViewDeviceInfo";
}

但是当我提交表单时出现以下错误,在 GET 方法上我得到了相同的页面而没有错误

org.springframework.beans.NullValueInNestedPathException: Invalid property 'device.criteria' of bean class [com.tdk.iot.controller.newdesign.manage.DeviceForm]: Could not instantiate property type [com.tdk.iot.domain.criteria.BaseCriteria] to auto-grow nested property path: java.lang.InstantiationException

最佳答案

你得到错误是因为在你的表单中有这个:

<form:radiobutton path="device.criteria.id" value="${criteria.id}"/>

在你的 POST 处理程序中你有这个:

public String saveDevicesWithStatus(@ModelAttribute("deviceForm") DeviceForm deviceForm){

}

这意味着 MVC 框架将尝试自动设置属性

deviceForm.device.criteria.id

现在,因为在任何范围内都没有现有的 DeviceForm,所以它将创建一个新的,当然 device.getCriteria() 返回 null,因此异常(exception)。

您可能认为您在 GET 处理程序中创建并填充的 DeviceForm 将被使用,但是 Spring MVC 是无状态的,因此您需要将其存储在请求之间的 session 范围内,以便重新使用或以其他方式修改您的逻辑。

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args

.... Given the above example where can theinstance come from? There are several options.....[in the absence of any other option] It may be instantiated using its default constructor

然而,更好的方法是将您的表单更改为如下所示:

<form:radiobutton path="device.criteria" value="${criteria.id}"/>

并注册一个转换器来转换提交的参数并绑定(bind)相应的实体实例。

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert

@Component
public class StringToCriteriaConverter implements Converter<String, BaseCriteria> {

@Autowired
private CriteriaService service;

//source is the ID passed by the page
public BaseCriteria convert(String source) {
// lookup and return item with corresponding ID from the database
}
}

关于java - org.springframework.beans.NullValueInNestedPathException : auto-grow nested property path in Spring MVC 3. 2.8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41570626/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com