Error no console: Neither BindingResult nor plain target object for bean name 'material' available as request attribute
ERROR 6528 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/formMateriais.html]")] with root cause
An error happened during template parsing (template: "class path resource [templates/formMateriais.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/formMateriais.html]")
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "formMateriais" - line 19, col 26)
import java.util.List;
import java.util.Optional;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import ifrn.pi.controle.materiais.models.Materiais;
import ifrn.pi.controle.materiais.respositories.MateriaisRespository;
@Controller
@RequestMapping("/materiais")
public class MateriaisController {
@Autowired
private MateriaisRespository mr;
@GetMapping("/form")
public String form(Materiais material) {
return "formMateriais";
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public String Salvar(@Valid Materiais material, BindingResult resultado, RedirectAttributes attributes) {
if (resultado.hasErrors()) {
return form(material);
}
System.out.println(material);
mr.save(material);
attributes.addFlashAttribute("mensagem", "Seu material foi emprestado com sucesso!");
return "redirect:/materiais";
}
@GetMapping
public ModelAndView listar() {
List<Materiais> materiais = mr.findAll();
ModelAndView mv = new ModelAndView("materiais/lista");
mv.addObject("materiais", materiais);
return mv;
}
@GetMapping("/{id}/selecionar")
public ModelAndView selecionar(@PathVariable Long id) {
ModelAndView md = new ModelAndView();
Optional<Materiais> opt = mr.findById(id);
if (opt.isEmpty()) {
md.setViewName("redirect:/materiais");
return md;
}
Materiais material = opt.get();
md.setViewName("materiais/formMateriais");
md.addObject("material", material);
return md;
}
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
@GetMapping("/{id}/remover")
public String apagar(@PathVariable Long id, RedirectAttributes attributes) {
Optional<Materiais> opt = mr.findById(id);
if (opt.isEmpty()) {
Materiais material = opt.get();
mr.delete(material);
attributes.addFlashAttribute("mensagem", "Seu material de empréstimo foi removido com sucesso!");
}
return "redirect:/materiais";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Controle de Materiais</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
</head>
<body>
<div th:replace="~{menu :: menu}"></div>
<h1>Adicionar Materiais</h1>
<div class="container">
<form action="/materiais" method="post" th:object="${material}">
<div>
<input type="hidden" th:field="*{id}" readonly="readonly">
</div>
<div>
<label>Material:</label> <input type="text" th:field="*{material}">
<p th:errors="*{material}"></p>
</div>
<div>
<label>Quantidade:</label> <input type="text"
th:field="*{quantidade}">
<p th:errors="*{quantidade}"></p>
</div>
<div>
<label>Data:</label> <input type="date" th:field="*{data}">
<p th:errors="*{data}"></p>
</div>
<div>
<label>Horário de empréstimo:</label> <input type="time"
th:field="*{horario}">
<p th:errors="*{horario}"></p>
</div>
<div>
<label>Horário de devolução:</label> <input type="time"
th:field="*{horariodevolucao}">
<p th:errors="*{horariodevolucao}"></p>
</div>
<div>
<button class="waves-effect waves-light btn" type="submit">Salvar</button>
<button class="waves-effect waves-light btn" type="reset">Limpar</button>
</div>
</form>
</div>
</body>
</html>
pelo erro do console que voce enviou postou o erro esta na linha linha 19, coluna 26
da pagina formMateriais.html, se essa pagina é do codigo html que vc postou o erro é
para estar na linha
<input type="hidden" th:field="*{id}" readonly="readonly">
desativa essa linha e ve se o erro some ou muda de local? não sei como vc chama esse id sem bean, mais ve
se descobre o erro nessa linha, eu investigaria se de alguma forma a classe MateriaisController nao esta enviando ou definindo o campo ID corretamente,
para formMateriais.html ou se th:field=“*{id}” esta definido corretamente em formMateriais.html para se comunicar com MateriaisController.
nao consigo ajudar mais porque nunca trabalhei com thymeleaf, muito mesmo se comunicando com classe que usa spring dessa forma.
o erro aparece direto quando voce carrega a pagina formMateriais.html, ou só quando vc clica em salvar?
quando eu carrego a página
acredito que nesse objeto material
que usa a classe Materiais. dentro da classe Materiais que vc não postou essa classe tem que ter os atributos id
quantidade
data
horario
horariodevolucao ou seja todos os atributos que vc esta chamando no formulario
. Se esse @getMapping estiver configurado corretamente é para sair o erro dessa linha faz. um teste. Se certifica que na classe Materiais tem definido o atributo id que esta dando erro Posta Essa Classe Materiais sua
@GetMapping("/form")
public String form(Materiais material) {
return "formMateriais";
}
<form action="/materiais" method="post" th:object="${material}">
@GetMapping("/form")
public String form(Materiais material) {
return "formMateriais";
}
Nesta parte acimo de codigo, digo que voce tem que substituir com algo como isso onde a Classe Materiais recebe uma instancia e é Setada dentro de model . Model é a classe utilizada para transmitir dados do controller para a view e, portanto, os dados adicionados nela podem ser utilizados pelo Thymeleaf, assim o campo id que esta dando erro será reconhecido pois ele é da Classe Materias e essa classe sera enviada para a view “formMateriais” atravé de model.addAttribute e os camapos id quantidade serao reconhecidos
apartir do objeto th:object=“${material}” que as contem na pagina/view “formMateriais”
.
@GetMapping("/form")
public String form(final Model model) {
model.addAttribute("material", new Materiais());
return "formMateriais";
}
de uma olhada neste link Spring MVC: Comunicação view/controller via POST de onde tirei exemplo e é explicado esse ultimo codigo que vai te dar uma luz