modelAttribute and path in a form when using a wrapper of a list of entities and c:foreach loop

huangapple go评论81阅读模式
英文:

modelAttribute and path in a form when using a wrapper of a list of entities and c:foreach loop

问题

我计划创建一个带有多个表单的视图,这些表单是由模型对象列表创建的。正如在这里的答案中所描述的 https://stackoverflow.com/a/32666512/5673289,我创建了一个列表的包装对象:

src/main/java/tk/trzczy/gallery/wrapperObject/GalleryForm.java

package tk.trzczy.gallery.wrapperObject;

import tk.trzczy.gallery.domain.Image;

import java.util.List;

public class GalleryForm {
    private List<Image> gallery;

    public GalleryForm(List<Image> gallery) {
        this.gallery = gallery;
    }

    public List<Image> getGallery() {
        return gallery;
    }

    public void setGallery(List<Image> gallery) {
        this.gallery = gallery;
    }
}

并且以以下方式改进了控制器:

src/main/java/tk/trzczy/gallery/controllers/ImageController.java

package tk.trzczy.gallery.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import tk.trzczy.gallery.domain.Image;
import tk.trzczy.gallery.services.ImageService;
import tk.trzczy.gallery.services.ImageCategoryService;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.Date;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import tk.trzczy.gallery.wrapperObject.GalleryForm;

@Controller
public class ImageController {

    private static final Logger log = LogManager.getLogger(LoginController.class);

    @Autowired
    private ImageService imageService;

    //(...)
    @RequestMapping("/gallery/edit")
    public String getImagesToEdit(Model model) {
        model.addAttribute("images", new GalleryForm(imageService.getAllImages()));
        return "editGallery";
    }
    //(...)
}

并且尝试在 JSP 文件中使用正确的 modelAttributepath 值,但未成功:

src/main/webapp/WEB-INF/views/editGalleryPage.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="g" uri="/WEB-INF/date-format-tag.tld" %>

<link rel="stylesheet" href="<spring:url value="/resource/css/editGallery.css" />"/>

<div class="panel-body">
    <div class="row">
        <c:forEach items="${images.gallery}" var="image" varStatus="vs">
            <form:form modelAttribute="images" action="/images/edit/${image.id}" id="image" class="image"
                       method="post">
                <form:input path="images.gallery[${vs.index}].url" id="image-${image.id}" style="width: 525px;"
                            class=" form:input-large"
                            name='url' value="${image.url}"/>
                <input type="submit">
                <p><form:errors path="url" cssClass="alert alert-danger"/></p>
            </form:form>
        </c:forEach>
    </div>
</div>

错误是:

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'images' of bean class [tk.trzczy.gallery.wrapperObject.GalleryForm]: Bean property 'images' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

这是一个 pom.xml 文件:

<!-- (项目依赖) -->

如何修复这个问题?

英文:

I plan to create a view with multiple forms tha are created of a list of model objects. As it is desribed in an answer here https://stackoverflow.com/a/32666512/5673289 I created a wrapper object for the list:

src/main/java/tk/trzczy/gallery/wrapperObject/GalleryForm.java

package tk.trzczy.gallery.wrapperObject;

import tk.trzczy.gallery.domain.Image;

import java.util.List;

public class GalleryForm {
    private List&lt;Image&gt; gallery;

    public GalleryForm(List&lt;Image&gt; gallery) {
        this.gallery = gallery;
    }

    public List&lt;Image&gt; getGallery() {
        return gallery;
    }

    public void setGallery(List&lt;Image&gt; gallery) {
        this.gallery = gallery;
    }
}

and improved a controller in this way:

src/main/java/tk/trzczy/gallery/controllers/ImageController.java

package tk.trzczy.gallery.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import tk.trzczy.gallery.domain.Image;
import tk.trzczy.gallery.services.ImageService;
import tk.trzczy.gallery.services.ImageCategoryService;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.Date;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import tk.trzczy.gallery.wrapperObject.GalleryForm;

@Controller
public class ImageController {

    private static final Logger log = LogManager.getLogger(LoginController.class);

    @Autowired
    private ImageService imageService;

//(...)
    @RequestMapping(&quot;/gallery/edit&quot;)
    public String getImagesToEdit(Model model) {
        model.addAttribute(&quot;images&quot;, new GalleryForm(imageService.getAllImages()));
        return &quot;editGallery&quot;;
    }
//(...)
}

And tried to use proper modelAttribute and path values in jsp file, but did not succeed:

src/main/webapp/WEB-INF/views/editGalleryPage.jsp

&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;
&lt;%@ taglib prefix=&quot;form&quot; uri=&quot;http://www.springframework.org/tags/form&quot; %&gt;
&lt;%@ taglib prefix=&quot;spring&quot; uri=&quot;http://www.springframework.org/tags&quot; %&gt;
&lt;%@ taglib prefix=&quot;g&quot; uri=&quot;/WEB-INF/date-format-tag.tld&quot; %&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;spring:url value=&quot;/resource/css/editGallery.css&quot; /&gt;&quot;/&gt;

&lt;div class=&quot;panel-body&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
        &lt;c:forEach items=&quot;${images.gallery}&quot; var=&quot;image&quot; varStatus=&quot;vs&quot;&gt;
        &lt;form:form modelAttribute=&quot;images&quot; action=&quot;/images/edit/${image.id}&quot; id=&quot;image&quot; class=&quot;image&quot;
                   method=&quot;post&quot;&gt;
            &lt;form:input path=&quot;images.gallery[${vs.index}].url&quot; id=&quot;image-${image.id}&quot; style=&quot;width: 525px;&quot;
                        class=&quot; form:input-large&quot;
                        name=&#39;url&#39; value=&quot;${image.url}&quot;/&gt;
            &lt;input type=&quot;submit&quot;&gt;
            &lt;p&gt;&lt;form:errors path=&quot;url&quot; cssClass=&quot;alert alert-danger&quot;/&gt;&lt;/p&gt;
        &lt;/form:form&gt;
    &lt;/div&gt;
&lt;/div&gt;

The error was

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property &#39;images&#39; of bean class [tk.trzczy.gallery.wrapperObject.GalleryForm]: Bean property &#39;images&#39; is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

Here it is a pom.xml file:

&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;groupId&gt;tk.trzczy&lt;/groupId&gt;
&lt;artifactId&gt;spring-webmvc&lt;/artifactId&gt;
&lt;version&gt;0.0.1&lt;/version&gt;
&lt;packaging&gt;war&lt;/packaging&gt;
&lt;properties&gt;
&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
&lt;aspect.version&gt;1.9.2&lt;/aspect.version&gt;
&lt;jackson.version&gt;2.9.8&lt;/jackson.version&gt;
&lt;hibernate.version&gt;5.4.2.Final&lt;/hibernate.version&gt;
&lt;hibernate.validator.version&gt;5.2.1.Final&lt;/hibernate.validator.version&gt;
&lt;c3p0.version&gt;0.9.5.2&lt;/c3p0.version&gt;
&lt;/properties&gt;
&lt;dependencies&gt;
&lt;!-- servlets and jps --&gt;
&lt;dependency&gt;
&lt;groupId&gt;javax.servlet&lt;/groupId&gt;
&lt;artifactId&gt;jstl&lt;/artifactId&gt;
&lt;version&gt;1.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;javax.servlet&lt;/groupId&gt;
&lt;artifactId&gt;javax.servlet-api&lt;/artifactId&gt;
&lt;version&gt;4.0.1&lt;/version&gt;
&lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.tiles&lt;/groupId&gt;
&lt;artifactId&gt;tiles-extras&lt;/artifactId&gt;
&lt;version&gt;3.0.8&lt;/version&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;jcl-over-slf4j&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;exclusion&gt;
&lt;groupId&gt;jboss&lt;/groupId&gt;
&lt;artifactId&gt;javassist&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;commons-fileupload&lt;/groupId&gt;
&lt;artifactId&gt;commons-fileupload&lt;/artifactId&gt;
&lt;version&gt;1.3.3&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.commons&lt;/groupId&gt;
&lt;artifactId&gt;commons-io&lt;/artifactId&gt;
&lt;version&gt;1.3.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;!--hibernate--&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
&lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
&lt;version&gt;${hibernate.version}&lt;/version&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;org.javassist&lt;/groupId&gt;
&lt;artifactId&gt;javassist&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
&lt;artifactId&gt;hibernate-entitymanager&lt;/artifactId&gt;
&lt;version&gt;${hibernate.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- Hibernate-C3P0 Integration --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
&lt;artifactId&gt;hibernate-c3p0&lt;/artifactId&gt;
&lt;version&gt;${hibernate.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- c3p0 --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.mchange&lt;/groupId&gt;
&lt;artifactId&gt;c3p0&lt;/artifactId&gt;
&lt;version&gt;${c3p0.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
&lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
&lt;version&gt;${hibernate.validator.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;mysql&lt;/groupId&gt;
&lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
&lt;version&gt;5.1.34&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- for rest services --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt;
&lt;artifactId&gt;jackson-databind&lt;/artifactId&gt;
&lt;version&gt;${jackson.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;javax.servlet.jsp&lt;/groupId&gt;
&lt;artifactId&gt;javax.servlet.jsp-api&lt;/artifactId&gt;
&lt;version&gt;2.3.3&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- For Aop --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.aspectj&lt;/groupId&gt;
&lt;artifactId&gt;aspectjrt&lt;/artifactId&gt;
&lt;version&gt;${aspect.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.aspectj&lt;/groupId&gt;
&lt;artifactId&gt;aspectjweaver&lt;/artifactId&gt;
&lt;version&gt;${aspect.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- To Send Email --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.sun.mail&lt;/groupId&gt;
&lt;artifactId&gt;javax.mail&lt;/artifactId&gt;
&lt;version&gt;1.5.4&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-core&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-webmvc&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-tx&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-orm&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-web&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-config&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;!--logging--&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j-core&lt;/artifactId&gt;
&lt;version&gt;2.8.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j-api&lt;/artifactId&gt;
&lt;version&gt;2.8.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j-web&lt;/artifactId&gt;
&lt;version&gt;2.13.3&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;slf4j-simple&lt;/artifactId&gt;
&lt;version&gt;1.7.30&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- PostgreSQL --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.postgresql&lt;/groupId&gt;
&lt;artifactId&gt;postgresql&lt;/artifactId&gt;
&lt;version&gt;42.2.16&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context-support&lt;/artifactId&gt;
&lt;version&gt;5.1.3.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
&lt;artifactId&gt;spring-security-taglibs&lt;/artifactId&gt;
&lt;version&gt;5.1.2.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;5.2.7.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-war-plugin --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
&lt;version&gt;3.2.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-surefire-plugin --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
&lt;version&gt;2.22.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-web&lt;/artifactId&gt;
&lt;version&gt;5.2.0.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-rest-core --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.data&lt;/groupId&gt;
&lt;artifactId&gt;spring-data-rest-core&lt;/artifactId&gt;
&lt;version&gt;3.3.4.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
&lt;!-- To define the plugin version in your parent POM --&gt;
&lt;pluginManagement&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
&lt;version&gt;2.22.1&lt;/version&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/pluginManagement&gt;
&lt;plugins&gt;
&lt;!-- To use the plugin goals in your POM or parent POM --&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
&lt;configuration&gt;
&lt;source&gt;1.8&lt;/source&gt;
&lt;target&gt;1.8&lt;/target&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;/project&gt;

How to fix it?

答案1

得分: 1

这应该可以工作

<div class="panel-body">
<div class="row">
<c:forEach items="${images.gallery}" var="image" varStatus="vs">
<form:form modelAttribute="images" action="/images/edit/${image.id}" id="image" class="image" method="post">
<form:input path="gallery[${vs.index}].url" id="image-${image.id}" style="width: 525px;"
class="form:input-large"
name='url' value="${image.url}"/>
<input type="submit">
<p><form:errors path="gallery[${vs.index}].url" cssClass="alert alert-danger"/></p>
</form:form>
</c:forEach>
</div>
</div>

问题在于form:input指定的路径以images.开头,但由于modelAttributeimages,它需要以gallery开头。

英文:

this should work

&lt;div class=&quot;panel-body&quot;&gt;
&lt;div class=&quot;row&quot;&gt;
&lt;c:forEach items=&quot;${images.gallery}&quot; var=&quot;image&quot; varStatus=&quot;vs&quot;&gt;
&lt;form:form modelAttribute=&quot;images&quot; action=&quot;/images/edit/${image.id}&quot; id=&quot;image&quot; class=&quot;image&quot; method=&quot;post&quot;&gt;
&lt;form:input path=&quot;gallery[${vs.index}].url&quot; id=&quot;image-${image.id}&quot; style=&quot;width: 525px;&quot;
class=&quot; form:input-large&quot;
name=&#39;url&#39; value=&quot;${image.url}&quot;/&gt;
&lt;input type=&quot;submit&quot;&gt;
&lt;p&gt;&lt;form:errors path=&quot;gallery[${vs.index}].url&quot; cssClass=&quot;alert alert-danger&quot;/&gt;&lt;/p&gt;
&lt;/form:form&gt;
&lt;/c:forEach&gt;
&lt;/div&gt;
&lt;/div&gt;

the problem was the path specified for form:input which started with images. but since the modeAttribute is images it needed to start with gallery.

huangapple
  • 本文由 发表于 2020年10月16日 06:18:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/64380419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定