2
respostas

ERRO 400 APOS ENVIAR FORM

Boa tarde senhores, estou tentando fazer o cadastramento de algumas perguntas digitadas pelo usuário, essas perguntas devem ficar vinculadas a um questionário que ja foi cadastrado anteriormente.

Durante o curso foi mostrado com listar e mostrar no model essa lista, tentei listar os meus questionários e manda-los para form para que o usuário possa escolher qual questionário a pergunta sera vinculada.

Mas quando tento submeter o form de pegunta recebo um erro 400.

Minha intensão com esse form é vincular a pegunta digitada ao questionário escolhido no form

segue abaixo as minhas classes:

package br.com.clienteoculto.models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Pergunta {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column
    private String pergunta;
    @ManyToOne
    @JoinColumn(name="questionario_id")
    private Questionario questionario;

    public int getId() {
        return id;
    }

    public String getPergunta() {
        return pergunta;
    }

    public Questionario getQuestionario() {
        return questionario;
    }

    public void setQuestionario(Questionario questionario) {
        this.questionario = questionario;
    }

    public void setPergunta(String pergunta) {
        this.pergunta = pergunta;
    }


}
package br.com.clienteoculto.models;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.OneToMany;

@Entity
public class Questionario {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String nomeQuestionario;
    @Lob
    private String descricaoQuestionario;

    @OneToMany(mappedBy="questionario")
    private List<Pergunta> perguntas = new ArrayList<Pergunta>();

    public List<Pergunta> getPergunta() {
        return perguntas;
    }

    public void setPergunta(List<Pergunta> pergunta) {
        this.perguntas = pergunta;
    }

    public String getNomeQuestionario() {
        return nomeQuestionario;
    }

    public void setNomeQuestionario(String nomeQuestionario) {
        this.nomeQuestionario = nomeQuestionario;
    }

    public String getDescricaoQuestionario() {
        return descricaoQuestionario;
    }

    public void setDescricaoQuestionario(String descricaoQuestionario) {
        this.descricaoQuestionario = descricaoQuestionario;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void addPergunta (Pergunta pergunta){
        this.perguntas.add(pergunta);
        pergunta.setQuestionario(this);
    }

}
package br.com.clienteoculto.controllers;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.clienteoculto.daos.PerguntaDAO;
import br.com.clienteoculto.daos.QuestionarioDAO;
import br.com.clienteoculto.models.Pergunta;
import br.com.clienteoculto.models.Questionario;

@Controller
@RequestMapping("/perguntas")
public class PerguntasController {

    @Autowired
    private QuestionarioDAO questionarioDAO;
    private PerguntaDAO perguntaDAO;

    @RequestMapping("/form")
    public ModelAndView form(){
        ModelAndView modelAndView = new ModelAndView("perguntas/form");
        modelAndView.addObject("questionarios", questionarioDAO.list());
        return modelAndView;
    }

    @Transactional
    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView save(Pergunta pergunta, RedirectAttributes redirectAttributes){
        ModelAndView modelAndView = new ModelAndView("perguntas/ok");
        Questionario questionario = new Questionario();
        questionario.addPergunta(pergunta);
        perguntaDAO.save(pergunta);
        redirectAttributes.addFlashAttribute("Sucesso", "pergunta cadastrada com sucesso");
        return modelAndView;
    }
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ 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"%>
<!DOCTYPE html>
<html>
<head>
<meta charset=UTF-8>
<title>Cliente Oculto</title>
</head>
<body>
    <h1>Cadastro de Perguntas</h1>
    <c:url value="/perguntas" var="url" />
    <form action="${url }" method="post">
        <div>
            <c:forEach items="${questionarios }" var="quest" varStatus="status">
                <input type="radio" name="questionario"
                    value="${quest.id}" />${quest.nomeQuestionario}
        </c:forEach>

        </div>
        <div>
            <label for="pergunta">Pergunta</label> <input type="text"
                name="pergunta" id="pergunta">
        </div>
        <div>
            <input type="submit" value="Cadastrar">
        </div>
    </form>
</body>
</html>
package br.com.clienteoculto.daos;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import br.com.clienteoculto.models.Questionario;

@Repository
public class QuestionarioDAO {

    @PersistenceContext
    private EntityManager manager;

    public List<Questionario> list() {
        return manager.createQuery("select q from Questionario q", Questionario.class).getResultList();
    }

    public void save(Questionario questionario) {
        manager.persist(questionario);
    }

}
2 respostas

Fala Wilker, tudo bem ?

O Http Status 400 Bad Request sinaliza que o servidor tentou processar a requisição mas ela continha dados inválidos.

Provavelmente isso ocorreu porque na action você espera receber um objeto de Pergunta, só que no formulário você envia um duas coisas: um id com name questionario, e uma String com name pergunta. Nesse caso o Spring vai tentar inserir o que veio do input com name pergunta (uma String) na variável pergunta que espera um objeto bem mais complexo.

Lembre-se que quando pedimos um objeto do modelo (um Java Bean qualquer) na action podemos passar por exemplo vários campos pra representar cada um dos atributos desse objeto. Quando recebe a requisição, neste caso, o Spring procura os setters pra cada atributo baseado no name dos inputs pra preencher o objeto.

Tente fazer essa correção em uma das pontas, no form ou no controller.

Espero ter ajudado. Abraço!

opa Rafael tudo certo e contigo?

pelo o que entendi na minha classe PerguntaController no metodo save() eu deveria receber também um questionário para assim o spring conseguir fazer o bindig com os meus atributos na minha classe Pergunta, é isso ?

se for isso eu tentei fazer mas ainda recebi o mesmo erro 400

segue o meu PerguntaController


@Controller
@RequestMapping("/perguntas")
public class PerguntasController {

    @Autowired
    private QuestionarioDAO questionarioDAO;
    private PerguntaDAO perguntaDAO;

    @RequestMapping("/form")
    public ModelAndView form(){
        ModelAndView modelAndView = new ModelAndView("perguntas/form");
        modelAndView.addObject("questionarios", questionarioDAO.list());
        return modelAndView;
    }

    @Transactional
    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView save(Questionario questionario,Pergunta pergunta, RedirectAttributes redirectAttributes){
        ModelAndView modelAndView = new ModelAndView("perguntas/ok");
        questionario.addPergunta(pergunta);
        perguntaDAO.save(pergunta);
        redirectAttributes.addFlashAttribute("Sucesso", "pergunta cadastrada com sucesso");
        return modelAndView;
    }
}

tenho uma outra questão com você disse o spring vai tentar pegar o meu input com o name pergunta e fazer o binding para o meu atributo pergunta que é uma string. Como seria o comportamento do spring quando ele tentar pegar o valor do input com o name questão e tentar fazer o binding com o meu atributo questionário que é do tipo questionário?

te alguma literatura que possa ler pra me entender um pouco mais sobre isso ?