Spring Forms绑定异常 - IllegalStateException:无法将类型[java.lang.String]的值转换为所需类型

时间:2014-03-11 17:42:09

标签: java jsp spring-mvc jstl spring-form

我是Spring和Java的新手,并致力于使用JSP,JSTL,Hibernate / JPA和模型类来获取Spring MVC中的表单。我可以让页面显示正常,但是应该创建用户的帖子给了我一个错误。

Failed to convert property value of type java.lang.String to required type com.everesttech.recruiting.searchtool.entity.Role for property user.role; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.everesttech.recruiting.searchtool.entity.Role] for property role: no matching editors or conversion strategy found

此错误有意义,因为表单正在传递Role的ID,而User对象需要传递Role对象。但是我不知道如何解决这个问题,同时仍然允许我的JSP由我的实际Entity对象支持,因为我想使用Spring / Hibernate验证。有没有办法声明该表单:选择作为角色对象?任何建议或解决方案都非常感谢。谢谢你提前。

我提供了项目中相关的代码部分。我没有包含来自我的服务层和实体层的代码,因为我知道它们正在工作。但是,如果需要,我也可以包括这些。用户与Role有多对一的关系。

UserController中

/**
 * display the user add page
 * 
 * @return              returns the view name
 */
@RequestMapping(value="/user/add", method=RequestMethod.GET)
public ModelAndView showUserAdd(ServletRequest request, @ModelAttribute("userModel") UserModel userModel, ModelMap modelmap) {  

    ModelMap modelMap = new ModelMap();
    userModel.setUser(new User());
    userModel.setRoles(userService.getRoles());
    modelMap.addAttribute("userModel", userModel);

    return new ModelAndView("user/add", modelMap);
}

/**
 * handle post request to handle user creation, if successful displays user list page
 * 
 * @param user          User object from JSP
 * @param result        BindingResult from JSP
 * @return              returns view name
 */
@RequestMapping(value="/user/add", method=RequestMethod.POST)
public String userAdd(UserModel userModel, BindingResult result) {

    if (result.hasErrors()) {
        logger.warn("Error binding UserModel for /user/add, returning to previous page");
        List<ObjectError> errors = result.getAllErrors();
        for (ObjectError error : errors) {
            logger.warn(error.getCode() + " - " + error.getDefaultMessage());
        }
        return "user/add";
    }

    try {
        User user = userModel.getUser();
        userService.addUser(user);
    }
    catch (DuplicateKeyException e) {
        logger.warn("Duplicate record found in User table", e);
    }
    catch (Exception e) {
        logger.error("Error occurred while trying to create a new user", e);
    }

    return "/user";
}

这是我传递给JSP的模型,它包含一个User对象,它是Hibernate Entity,还有一个Roles列表,另一个是hibernate Entity。

import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.everesttech.recruiting.searchtool.entity.Role;
import com.everesttech.recruiting.searchtool.entity.User;

@Scope(value="request")
@Component("userModel")
public class UserModel {

    public User user;
    public List<Role> roles;

    public UserModel() {

    }

    public UserModel(User user, List<Role> roles) {
        this.user = user;
        this.roles = roles;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    @Override
    public String toString() {
        return "UserModel [user=" + user + ", roles=" + roles + "]";
    }
}

这是我的JSP。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-8 col-md-6">
            <h3>User - Add</h3>
            <br>

            <spring:hasBindErrors name="userModel">
                <div class="alert alert-danger">
                    <sf:errors path="userModel.user.firstName"></sf:errors>
                    <sf:errors path="userModel.user.lastName"></sf:errors>
                    <sf:errors path="userModel.user.email"></sf:errors>
                    <sf:errors path="userModel.user.userName"></sf:errors>
                    <sf:errors path="userModel.user.password"></sf:errors>
                    <sf:errors path="userModel.user.role"></sf:errors>
                </div>
            </spring:hasBindErrors>

            <c:url var="formAction" value="/user/add" />

            <sf:form commandName="userModel" modelAttribute="userModel" method="post" action="${formAction}"> 
                <div class="form-group">
                    <label for="first-name">First Name</label>
                    <sf:input path="user.firstName" id="first-name" class="form-control" placeholder="First Name" />
                </div>
                <div class="form-group">
                    <label for="last-name">Last Name</label>
                    <sf:input path="user.lastName" id="last-name" class="form-control" placeholder="Last Name" />
                </div>
                <div class="form-group">
                    <label for="email">Email</label>
                    <sf:input path="user.email" id="email" class="form-control" placeholder="Email" />
                </div>
                <div class="form-group">
                    <label for="user-name">Username</label>
                    <sf:input path="user.userName" id="user-name" class="form-control" placeholder="Username" />
                </div>
                <div class="form-group">
                    <label for="password">Password</label>
                    <sf:password path="user.password" id="password" class="form-control" placeholder="" />
                </div>
                <div class="form-group">
                    <label for="confirm-password">Confirm Password</label>
                    <input type="password" id="confirm-password" class="form-control" placeholder="" />
                </div>
                <div class="form-group">
                    <label for="role">Role</label>
                    <sf:select path="user.role" id="role" class="form-control" >
                        <c:forEach var="r" items="${userModel.roles}">
                            <sf:option value="${r.getId()}">${r.getFriendlyName()}</sf:option>
                        </c:forEach>
                    </sf:select>
                </div>
                <button type="submit" class="btn btn-default">Save</button>
                <button type="button" class="btn btn-default">Cancel</button>
            </sf:form>
        </div>
    </div>
</div>

1 个答案:

答案 0 :(得分:1)

对于任何有兴趣的人,我在Spring文档中找到了一个解决方案。我必须创建一个类来处理从String到Role的转换并注册它。这必须访问数据库以创建Role对象,但我没有看到另一种处理它的方法。

这是我的班级。

import javax.inject.Inject;

import org.springframework.core.convert.converter.Converter;

import com.everesttech.recruiting.searchtool.dao.RoleDao;
import com.everesttech.recruiting.searchtool.entity.Role;

final class StringToRole implements Converter<String, Role> {

@Inject
RoleDao roleDao;

@Override
public Role convert(String source) {
    return roleDao.find(Long.parseLong(source));
    }
}

我在mvc-context.xml文件中添加/编辑了以下内容。

<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

<bean id="conversionService"
  class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="com.examplecompany.exampleapp.example.converter.StringToRole"/>
        </list>
    </property>
</bean>

这有效,我现在能够提交表格而没有任何问题。但是现在,当User对象不满足验证要求时,我的hibernate验证没有出现在JSP上。例如,First Name有一个@NotBlank注释。我可以看到它被检测到并且我正在记录它。但是它们没有以形式出现在jsp上:错误标记。如果有人知道如何解决这个问题,请告诉我。