java - Spring 形式 : BindException when submiting large list of objects

标签 java spring tomcat tomcat8 spring-form

我有这个表单,它在数据表中显示了几个对象列表。通过此表单,管理员用户可以定义特定用户对这些对象的权限。

例如,这是产品权限数据表jsp代码:

<sf:form action="${action}" class="form-horizontal" method="post" modelAttribute="permisosList" enctype="multipart/form-data" >
...
<table class="table table-striped table-bordered table-hover" id="tabla_permisos6">
    <thead>
        <tr>
            <th><%=Languages.getString("Producto")%></th>
            <th><%=Languages.getString("Permiso")%></th>
        </tr>
    </thead>
    <tbody>
        <c:forEach items="${permisosList.permisosProducto}" var="permiso" varStatus="counter">
            <tr>
                <sf:input path="permisosProducto[${counter.index}].producto.idProd" type="hidden"/>
                <td style="vertical-align:middle;"><c:out value="${permiso.producto.nombre}"/></td>
                <td align="center">
                    <sf:select class="form-control" path="permisosProducto[${counter.index}].permiso" type="number">
                        <sf:option value="0">
                            <c:out value="No visible" />
                        </sf:option>
                        <sf:option value="1">
                            <c:out value="Visible" />
                        </sf:option>
                        <sf:option value="2">
                            <c:out value="Descarga" />
                        </sf:option>
                    </sf:select>
                </td>
            </tr>
        </c:forEach>
    </tbody>
</table>
...

其中一些列表内部有成百上千个对象,因此提交表单时,我得到了 spring BindException:

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 4 errors

Field error in object 'permisosList' on field 'permisosProducto[137].producto.idProd': rejected value []; codes [typeMismatch.permisosList.permisosProducto[137].producto.idProd,typeMismatch.permisosList.permisosProducto.producto.idProd,typeMismatch.permisosProducto[137].producto.idProd,typeMismatch.permisosProducto.producto.idProd,typeMismatch.idProd,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [permisosList.permisosProducto[137].producto.idProd,permisosProducto[137].producto.idProd]; arguments []; default message [permisosProducto[137].producto.idProd]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'permisosProducto[137].producto.idProd'; nested exception is java.lang.NumberFormatException: For input string: ""]

Field error in object 'permisosList' on field 'permisosProducto[338].permiso': rejected value []; codes [typeMismatch.permisosList.permisosProducto[338].permiso,typeMismatch.permisosList.permisosProducto.permiso,typeMismatch.permisosProducto[338].permiso,typeMismatch.permisosProducto.permiso,typeMismatch.permiso,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [permisosList.permisosProducto[338].permiso,permisosProducto[338].permiso]; arguments []; default message [permisosProducto[338].permiso]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'permisosProducto[338].permiso'; nested exception is java.lang.NumberFormatException: For input string: ""]

Field error in object 'permisosList' on field 'permisosProducto[573].permiso': rejected value []; codes [typeMismatch.permisosList.permisosProducto[573].permiso,typeMismatch.permisosList.permisosProducto.permiso,typeMismatch.permisosProducto[573].permiso,typeMismatch.permisosProducto.permiso,typeMismatch.permiso,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [permisosList.permisosProducto[573].permiso,permisosProducto[573].permiso]; arguments []; default message [permisosProducto[573].permiso]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'permisosProducto[573].permiso'; nested exception is java.lang.NumberFormatException: For input string: ""]

Field error in object 'permisosList' on field 'permisosProducto[808].permiso': rejected value []; codes [typeMismatch.permisosList.permisosProducto[808].permiso,typeMismatch.permisosList.permisosProducto.permiso,typeMismatch.permisosProducto[808].permiso,typeMismatch.permisosProducto.permiso,typeMismatch.permiso,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [permisosList.permisosProducto[808].permiso,permisosProducto[808].permiso]; arguments []; default message [permisosProducto[808].permiso]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'permisosProducto[808].permiso'; nested exception is java.lang.NumberFormatException: For input string: ""]

我已经检查过那些索引处的信息是正确的,所以任何地方都没有空字段(那为什么一旦提交数据就会有空字段?)。我还注意到这些索引并不总是相同的。也许如果我重新启动 tomcat 或者我在几分钟后重试,错误中的索引是不同的。 并且只发生在包含至少 200 个以上对象的列表中。并且在到达 Controller 之前抛出异常。

这是我的 PermisoList 类:

public class PermisoList {
    List<PermisoProductoForm> permisosProducto;
    List<PermisoCarpetaForm> permisosCarpeta;
    List<PermisoTipoDocForm> permisosTipoDoc;
    List<PermisoAgenteClienteForm> permisosAgenteCliente;
    List<PermisoIdiomaForm> permisosIdioma;
    List<PermisoPaisForm> permisosPais;
    List<PermisoEmpresaForm> permisosEmpresa;
    List<PermisoUsuarioProductoForm> permisosUsuarioProducto;   
...
}

我的 PermisoProductoForm 类:

public class PermisoProductoForm {

    private Producto producto;
    private int permiso;
...
}

还有我的 Producto 类:

@Entity
@Table(name = "Producto")
public class Producto {

    @Id
    @GeneratedValue
    private int idProd;

    private String codigo;
    private String nombre;
    private String marca;
    private boolean activo;

    @ManyToOne
    @JoinColumn(name = "idFamilia")
    private Familia familia;

    @OneToMany(mappedBy = "producto", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Documento> documentacion;

    @ManyToOne
    @JoinColumn(name = "idEmpresa")
    private Empresa empresa;

    @OneToMany(mappedBy = "primaryKey.producto", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<PermisoUsuarioProducto> permisosProducto;

    @OneToMany(mappedBy = "productoRelacionado", fetch = FetchType.LAZY)
    private List<TemaForo> temasForo;
...
}

此外,我已经尝试了一些我发现的解决方案,比如将这段代码添加到 Controller 中:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setAutoGrowCollectionLimit(2048);
}

或者在jsp代码的form标签内添加enctype="multipart/form-data"

有谁知道为什么会这样或者知道如何解决这个问题?我现在 100% 卡住了。


编辑:我已经完成@angcap 回答的内容(将 int 更改为 Integer 类型并在 initBinder 方法中添加 CustomEditor),现在不再抛出此 BindException。所以到达 Controller 。

现在发生的情况是那些具有空字符串的索引现在具有“空”值(由于 CustomEditor)。正如我所说,我在提交表单之前检查了信息,我可以看到列表中的所有对象都正常,没有一个元素的字段为空。

那么,当列表非常大时,Spring 为什么要对数据执行此操作?而且它似乎对随机索引执行此操作...


编辑 2: 这是一个 TOMCAT 问题! 我已经在 Pivotal tc Server (v3.1) 上部署了 binder.setAutoGrowCollectionLimit( 2048); 解决方案,没有任何异常或空字符串或 null。功能齐全。

所以问题出在tomcat(v8.0)配置上。有人知道这件事吗?


编辑 3: 我接受 @angcap 的回答,因为它确实解决了我最初的问题。按照他所说的去做,就避免了 BindException。

最佳答案

您似乎为数字字段 idProdpermiso 发布了空字符串。检查发布的数据或尝试注册 CustomNumberEditor允许在 Controller 中使用 @initBinder 来使用 empyValues。

关于java - Spring 形式 : BindException when submiting large list of objects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38303884/

相关文章:

java - 使用反射替换 java.net.URL URLStreamHandlerFactory 是个好主意吗?

java - JUnit 测试 - 进行测试的最佳且最可靠的方法?

java - Flex 错误 flex.messaging.io.amf.ASObject 无法转换为

java - org.springframework.beans.factory.UnsatisfiedDependencyException : Error creating bean with name userController : Unsatisfied dependency

java - Spring Boot JAR 不适用于 Windows Server

tomcat - 启动Tomcat时出现异常

Javamail 作为 tomcat 中的 JNDI 资源

java - 在 Java 中用零填充列表

java - 如何解决jsp到servlet的空间问题?

java - 入门级自动配置Bean始终优先于自定义自动配置Bean