Issue
I have MVC project on Spring Boot that suppose to do CRUD operations. Basically it has two models, which represents Forum Theme and Article of this Theme. And I want to add new Themes or Articles. Now I stuck on submitting form data, managed with POST request. My controller:
@Controller
public class forumController {
@Autowired
private themeRepository themeRepository;
@Autowired
private articleRepository articleRepository;
@GetMapping("/forum")
public String blogMain(Model model) {
Iterable<ThemeModel> themes = themeRepository.findAll();
model.addAttribute("themes", themes);
return "blogMain";
}
@GetMapping("/guest")
public String guestMain(Model model) {
Iterable<ThemeModel> themes = themeRepository.findAll();
model.addAttribute("themes", themes);
return "blogMain";
}
@GetMapping("/guest/{id}")
public String readTheme(@PathVariable(value = "id") Long id, Model model) {
Optional<ThemeModel> theme = themeRepository.findById(id);
ArrayList<ThemeModel> result = new ArrayList<>();
theme.ifPresent(result::add);
model.addAttribute("theme", result);
return "readTheme";
}
@GetMapping("/user")
public String userMain(Model model) {
Iterable<ThemeModel> themes = themeRepository.findAll();
model.addAttribute("themes", themes);
return "userMain";
}
@GetMapping("/user/{id}")
public String userReadTheme(@PathVariable(value = "id") Long id, Model model) {
Optional<ThemeModel> theme = themeRepository.findById(id);
ArrayList<ThemeModel> result = new ArrayList<>();
theme.ifPresent(result::add);
model.addAttribute("theme", result);
return "userReadTheme";
}
@GetMapping("/user/addArticle/{id}")
public String userAddArticle(@PathVariable(value = "id") Long id, Model model) {
return "userAddArticle";
}
@PostMapping("/user/addArticle/{id}")
public String userAddArticlePost(@PathVariable(value = "id") Long id, @RequestParam String full_text, Model model) {
ArticleModel article = new ArticleModel(full_text);
articleRepository.save(article);
ThemeModel thisTheme = themeRepository.findById(id).orElseThrow();
thisTheme.getArticles().add(article);
themeRepository.save(thisTheme);
return "redirect:/user/{id}";
}
@GetMapping("/admin")
public String adminMain(Model model) {
Iterable<ThemeModel> themes = themeRepository.findAll();
model.addAttribute("themes", themes);
return "adminMain";
}
@GetMapping("/admin/addTheme")
public String addTheme(Model model) {
return "adminAddTheme";
}
@PostMapping("/admin/addTheme")
public String addPostTheme(@RequestParam("heading") String heading, @RequestParam("description") String description, Model model) {
ThemeModel theme = new ThemeModel(heading, description);
themeRepository.save(theme);
return "redirect:/admin";
}
}
Template to add theme:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<title>Title</title>
</head>
<body>
<h1 class="text-muted p-2 mt-1">Додати нову тему</h1>
<div class="container mt-5">
<th:taglib uri="http://www.springframework.org/tags/form" prefix="form" />
<form:form action="#" th:action="@{/admin/addTheme}" th:object="${theme}" method="post">
<input type="text" name="heading" placeholder="Введіть заголовок..." class="form-control mb-2"/>
<input type="text" name="description" placeholder="Введіть опис..." class="form-control mb-2"/>
<input type="submit" value="Опублікувати" class="btn btn-info mt-2"/>
</form:form>
<a href="/admin" class="btn btn-secondary mt-2">Скасувати</a>
</div>
</body>
</html>
Template to add Article:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<title>Title</title>
</head>
<body>
<h1 class="text-muted p-2 mt-1">Додати допис</h1>
<div class="container mt-5">
<th:taglib uri="http://www.springframework.org/tags/form" prefix="form" />
<form:form method="POST">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<textarea name="full_text" placeholder="Введіть текст" class="form-control"></textarea>
<button type="submit" class="btn btn-info mt-2">Опублікувати</button>
<a href="/user" class="btn btn-secondary mt-2">Скасувати</a>
</form:form>
</div>
</body>
</html>
Theme Model:
@Entity
@Table(name = "themes")
public class ThemeModel {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String heading, description;
public ThemeModel() {
}
public ThemeModel(String heading, String description) {
this.heading = heading;
this.description = description;
}
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "article_id", referencedColumnName = "id")
List<ArticleModel> articles = new ArrayList<>();
public Long getId() {
return id;
}
public String getHeading() {
return heading;
}
public String getDescription() {
return description;
}
public List<ArticleModel> getArticles() {
return articles;
}
public void setId(Long id) {
this.id = id;
}
public void setHeading(String heading) {
this.heading = heading;
}
public void setDescription(String description) {
this.description = description;
}
public void setArticles(List<ArticleModel> articles) {
this.articles = articles;
}
}
Article Model:
@Entity
@Table(name="articles")
public class ArticleModel {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String full_text;
public ArticleModel() {
}
public ArticleModel(String full_text) {
super();
this.full_text = full_text;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFull_text() {
return full_text;
}
public void setFull_text(String full_text) {
this.full_text = full_text;
}
}
Solution
Remove the use of th:taglib
and form:form
and use a normal HTML <form>
.
Answered By - Wim Deblauwe
Answer Checked By - Mary Flores (JavaFixing Volunteer)