[Resolvido] Erro ao passar um objeto de form html para o Controller Spring

Boa tarde e Feliz Natal a todos!

Estou com o seguinte problema tenho um cadastro de usuários que é uma pagina JSP, quando tento gravar um usuario no banco ocorre o seguinte erro:

Grave: Servlet.service() for servlet [Spring_MVC_Dispatcher_Servlet] in context with path [/SGE] threw exception [Request processing failed; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'usuario' on field 'perfil': rejected value [br.com.sge.modelo.Perfil@19de339]; codes [typeMismatch.usuario.perfil,typeMismatch.perfil,typeMismatch.br.com.sge.modelo.Perfil,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [usuario.perfil,perfil]; arguments []; default message [perfil]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'br.com.sge.modelo.Perfil' for property 'perfil'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [br.com.sge.modelo.Perfil] for property 'perfil': no matching editors or conversion strategy found]] with root cause org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'usuario' on field 'perfil': rejected value [br.com.sge.modelo.Perfil@19de339]; codes [typeMismatch.usuario.perfil,typeMismatch.perfil,typeMismatch.br.com.sge.modelo.Perfil,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [usuario.perfil,perfil]; arguments []; default message [perfil]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'br.com.sge.modelo.Perfil' for property 'perfil'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [br.com.sge.modelo.Perfil] for property 'perfil': no matching editors or conversion strategy found] at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:647) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:603) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:950) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:859) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:883) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:792) at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722)

Meu objeto Usuário tem um atributo Perfil e preciso passa-lo para a criação de um Usuário valido segue abaixo o meu form

<form action="cadastrarUsuario" method="post"> <div class="label"><label for="nome_usuario">Nome:</label></div><input class="input_texto" type="text" name="nome_usuario" id="nome_usuario"/><br/> <div class="label"><label for="email_usuario">Email:</label></div><input class="input_texto" type="text" name="email_usuario" id="email_usuario"/><br/> <div class="label"><label for="login_usuario">Login:</label></div><input class="input_texto" type="text" name="login_usuario" id="login_usuario"/><br/> <div class="label"><label for="senha_usuario">Senha:</label></div><input class="input_texto" type="password" name="senha_usuario" id="senha_usuario"/><br/> <div class="label"><label for="perfil">Perfil:</label></div> <select id="perfil" name="perfil"> <option value="">Selecione...</option> <c:forEach items="${lista_perfil}" var="perfil"> <option value="${perfil}">${perfil.tipo_perfil}</option> </c:forEach> </select> <div class="botoes"><input type="submit" value="Cadastrar" /><input type="reset" value="Limpar" /></div> </form>

alguém pode me ajudar ?

[Failed to convert property value of type 'java.lang.String' to required type 'br.com.sge.modelo.Perfil' for property 'perfil';

Pelo que entendi vc tem uma classe Usuario que tem um objeto interno do tipo Perfil.

E quando você tenta salvar um Usuario na JSP, você está passando para Usuario não um objeto Perfil, mas sim um objeto String.

Você precisa criar um converter, para transformar seu campo String referente a Perfil na interface, em um objeto do tipo Perfil. Porque o controller está esperando um Perfil e não uma String. Ou então, se não souber criar o conversor, você pode criar um campo do tipo String na entidade, e usar esse campo como perfil na jsp, e quando chegar no controller, dai pega o perfil_string, e insere no objeto Perfil.

http://static.springsource.org/spring/docs/2.5.x/reference/validation.html#beans-beans-conversion-customeditor-registration

[quote]E quando você tenta salvar um Usuario na JSP, você está passando para Usuario não um objeto Perfil, mas sim um objeto String.

Você precisa criar um converter, para transformar seu campo String referente a Perfil na interface, em um objeto do tipo Perfil. Porque o controller está esperando um Perfil e não uma String. Ou então, se não souber criar o conversor, você pode criar um campo do tipo String na entidade, e usar esse campo como perfil na jsp, e quando chegar no controller, dai pega o perfil_string, e insere no objeto Perfil.

http://static.springsource.org/spring/docs/2.5.x/r...sion-customeditor-registration[/quote]

Romarcio eu li a documentação desse link mas sou iniciante com Spring e Java Web não consegui entender muita coisa :oops:
fiz esse esquema do campo String mas vai chegar o ponto em que terei uma classe que vai ter vários objetos interno de vários tipos diferentes e fai ficar meio complicado converter tudo isso no Controller e setar o atributo na classe.

vc teria algum exemplo de como fazer um Converter ?
em uma situação parecida com a minha se não for pedir muito kkkkkkkk

desde já agradeço

Sim, vou te passar o seguinte exemplo:

  • Na classe User eu tenho um objeto Perfil. Na classe Perfil eu tenho por exemplo, um campo Long id e um campo String desc.
public class User {
    ...
    private Perfil perfil;
  • Na JSP tenho o combo que mostra uma lista de perfis:
                &lt;form:select path="perfil"&gt;User profile:
                    &lt;form:option value="0" label="--- Select ---"/&gt;
                    &lt;form:options items="${perfilList}" itemValue="id" itemLabel="desc"/&gt;
                &lt;/form:select&gt;
  • Quando você seleciona um item no combo, você vai enviar para o UserController o valor que está em itemValue=“id”, ou seja, o id do perfil selecionado. Veja então que você não está enviando um objeto perfil e sim apenas o id do perfil. Porém, o controller espera um objeto perfil para inserir no objeto user. Então temos que converter esse id em um objeto perfil.
  • Para converter vamos criar uma classe chamada PerfilPropertyEditor. Para isso eu preciso fazer uma consulta no banco e recuperar o perfil com o id selecionado:
public class ProfilePropertyEditor extends PropertyEditorSupport {
    private IProfileDao&lt;Profile&gt; dao;

    public PerfilPropertyEditor(IPerfilDao&lt;Perfil&gt; dao) {
        this.dao = dao;
    }

    @Override
    public void setAsText(String text) {
        //transforma a String com o id em um long
        Long id = new Long(text);
        //recupera no db o perfil do id referido
        Perfil perfil = dao.find(id);
        //add o objeto perfil encontrado no objeto user no controller através do método setValue da super-classe.
        super.setValue(profile);
    }
}
  • Na classe UserController inserimos um método chamado initBinder:
@Controller
public class UserController {
    @Autowired
    private IPerfilDao&lt;Perfil&gt; perfilDao;

    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(Perfil.class, new PerfilPropertyEditor(perfilDao));
    }
...
}
  • Desse modo o Spring fará a conversão para você. Quando receber do formulário JSP um perfil, ele acessa automaticamente o método initBinder, acessando sua classe de conversão, e tornando para o objeto User um objeto Perfil.

Caso sua JSP não envie o Id perfil e sim a descrição do Perfil, você muda a consulta para localizar por descrição e não por id como eu exemplifiquei.

obrigado deu certo :smiley:

Jóia, legal que funcionou.