既不是BindingResult也不是bean名称的普通目标对象&userCreateForm'可用作请求属性

时间:2014-10-13 11:24:45

标签: jsp spring-mvc jsp-tags

我为用户创建了一些表单:

                <form:form action="${pageContext.request.contextPath}/user/create" method="post" modelAttribute="userCreateForm" autocomplete="off">
                    <table class="b-table table table-striped">
                        <tbody>

                            <tr>
                                <td><spring:message code="UI.Labels.User.FirstName"/></td>
                                <td>
                                    <form:input type="text" path="firstName" cssClass="form-control"/>
                                </td>
                            </tr>
                            <tr>
                                <td><spring:message code="UI.Labels.User.LastName"/></td>
                                <td>
                                    <form:input type="text" path="lastName" cssClass="form-control"/>
                                </td>
                            </tr>
                            <tr>
                                <td><spring:message code="UI.Labels.User.Role"/></td>
                                <td>
                                    <form:select path="userRole" cssClass="form-control">
                                        <form:options items="${roles}"/>
                                    </form:select>
                                </td>
                            </tr>

                            <tr>
                                <td><spring:message code="UI.Labels.User.Email"/></td>
                                <td>
                                    <form:input type="text" path="email" cssClass="form-control" autocomplete="off"/><span><form:errors path="email" cssClass="error"/></span> 
                                </td>
                            </tr>

                            <tr>
                                <td><spring:message code="UI.Labels.User.Password"/></td>
                                <td>
                                    <form:input type="password" path="password" cssClass="form-control" autocomplete="off"/><span></span>
                                </td>
                            </tr>

                            <tr>
                                <td><spring:message code="UI.Labels.User.Pictire"/></td>
                                <td>
                                    <input type="file" name="file" cssClass="form-control"/><span></span>
                                </td>
                            </tr>
                        </tbody>
                    </table>

                    <button class="btn btn-primary" type="submit" name="submit">
                        <spring:message code="UI.Labels.User.Submit"/>
                    </button>

                </form:form>

控制器:

@RequestMapping("/create")
public String createPage(Model model, Principal principal, Locale locale) {
    final User loggedUser = getLoggedUser();

    User userCreateForm = new User();
    model.addAttribute("userCreateForm", userCreateForm);
    //model.addAttribute("roles", Utils.localizedRoles(loggedUser.getUserRole(), messageSource, locale));
    model.addAttribute("roles", systemRoleService.findAll());
    return "user/create";
}

@RequestMapping(value = "/create", method = RequestMethod.POST)
public String create(
                     @ModelAttribute User userForm,
        BindingResult bindingResult,
        Model model,
        Locale locale,
        RedirectAttributes redirectAttributes) {
    if(bindingResult.hasErrors()) {
        return "user/create";
    }
    try {
        userForm.setPassword(Utils.bcrypt(userForm.getPassword()));
        userForm.setLogin(userForm.getEmail());

        userService.create(userForm);
        redirectAttributes.addFlashAttribute("success", messageSource.getMessage("UI.Messages.User.CreatedSuccess", null, locale));
    } catch (ResourceException ue) {
        final User loggedUser = getLoggedUser();
        final List<String> failures = new ArrayList<>();
        for(String m : ue.getMessages()) failures.add( messageSource.getMessage(m, null, locale) );
        model.addAttribute("failures", failures);
        model.addAttribute("userCreateForm", userForm);
        model.addAttribute("roles", Utils.localizedRoles(loggedUser.getUserRole(), messageSource, locale));
        return "user/create";
    }
    return "redirect:/";
}

如果我没有选择任何角色 - 它工作正常,但保存没有角色的用户。 当我在.jsp中选择userRole并按“保存”时 - 我有一个错误:

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'userCreateForm' available as request attribute

请帮我解决这个问题。 你能告诉我出了什么问题吗?

如果我选择了一个角色,那么在@ModelAttribute中我得到的是SystemRole对象而不是User ....为什么?

现在我收到了一个新错误:

Field error in object 'userCreateForm' on field 'userRole': rejected value [6]; codes [typeMismatch.userCreateForm.userRole,typeMismatch.userRole,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userCreateForm.userRole,userRole]; arguments []; default message [userRole]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'userRole'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [ru.test.jpa.SystemRole] for property 'userRole[0]': no matching editors or conversion strategy found]

在User对象中,提交的'userRole' - 是List。 如何从jsp中获取所选角色的列表?


我添加了转换器

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import ru.test.jpa.SystemRole;

@Component("userRoleConverter")
public class UserRoleConverter implements Converter<String, SystemRole> {

    @Autowired
    private ResourceService<SystemRole> systemRoleService;


    @Override
    public SystemRole convert(String id)  {
        return systemRoleService.findOne(Long.valueOf(id));
    }
}

并将其注册在sprint-context.xml

<beans:bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <beans:property name="converters">
            <beans:ref bean="userRoleConverter"/>
    </beans:property>
</beans:bean>

我仍然得到同样的错误。 有什么问题?

非常感谢。

1 个答案:

答案 0 :(得分:0)

错误消息中最相关的部分是:Cannot convert value of type [java.lang.String] to required type [ru.test.jpa.SystemRole] for property 'userRole[0]'

您没有显示User类,但由于错误,我认为userRoleSystemRole的集合或数组。您可以使用包装类作为表单对象,该表单对象具有接受字符串集合的setter并生成角色,如:

class UserWrapper {
    class User user = new User();

    // delegates for setters and getters omitted for breivety
    public void setStrUserRole(List<String> strRole) {
        role = new List<SystemRole>();
        for (String str: strRole) {
            // build role r form its String representation
            role.add(r);
        }
    }
}

或者您可以创建Converter<String, SystemRole>并将其注册到Spring使用的DefaultFormattingConversionService

如果使用XML配置,则可以通过以下方式注册新转换器:

<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean"
      id="conversionService"/>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
      p:targetObject-ref="conversionService" p:targetMethod="addConverter">
    <property name="arguments">
        <list>
            <value type="java.lang.Class">java.lang.String</value>
            <value type="java.lang.Class">ru.test.jpa.SystemRole</value>
            <ref bean="userRoleConverter"/>
        </list>
    </property>
</bean>

因为您只想添加一个新的转换器,而不是替换整个默认的Spring转换器。