'Getting a 400 bad request response when submitting a form in Thymeleaf to my spring boot application
I am creating a Spring boot application with a thymeleaf front-end. I am trying to create an object of type "expense" (seen in the code snippet below) but, whenever I call the POST operation on the correct path, I am given a 400 bad request errors message on my app and a "An error happened during template parsing (template: "ServletContext resource [/WEB-INF/views/error.html]")" in the console.
The entity below represents the data type I am trying to create using the form. To create this object, only the variables expenses_id, expenses_name and expenses_date are required. I was able to create one of these objects with null values in the remaining fields.
@Entity(name = "expenses")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Expenses {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long expenses_id;
private String expenses_name;
private Integer expenses_amount;
private Date expenses_date;
@ManyToOne
@JoinTable(
name = "budget_expenses",
joinColumns = @JoinColumn(name = "expenses_id"),
inverseJoinColumns = @JoinColumn(name = "budgets_id"))
private Budgets budget;
//Gettes setters and constructor
}
The snippet below shows the template with my form
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Expense Creation</title>
</head>
<body>
<div class="container">
<div class="container">
<div th:insert="fragments/navbar.html"> </div>
<div class="jumbotron">
<div class="row">
<h3>Expense Creation</h3>
</div>
<form action="#" th:action="@{/budgets/{id}/add-expense(id = ${budgetId})}" th:object="${expense}" method="post">
<p>Name: <input type="text" th:field="*{expenses_name}" /></p>
<p>Amount: <input type="number" th:field="*{expenses_amount}" /></p>
<p>Date: <input type="text" th:field="*{expenses_date}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</div>
</body>
</html>
The snippet below contains the GET and POST operations. The GET manages to provide the correct view template with the form in question. The problem comes from the POST mapping. As soon as I click "submit" the errors happen. I have done quite a lot of debugging and I believe that the problem is with the @ModelAttribute mainly because it is the component which breaks the application anytime it is present, I just don't understand how to correct it. I have verified the paths and made sure that the GET and POST are being done to the correct mapping. I have verified the variables to make sure they have the correct names and correspondence. I am at a loss as to why this is happening, even more so due to the fact that I have a similar creation via form dynamic with another object just a few lines above this code.
@GetMapping("{id}/add-expense")
public String expensesForm(Model model, @PathVariable Long id){
model.addAttribute("expense", new Expenses());
model.addAttribute("budgetId", id);
return "expenseForm";
}
@PostMapping("{id}/add-expense")
public String expenseSubmitted(@ModelAttribute Expenses expense, @PathVariable Long id, Model model){
Budgets budget = budgetsRepository.getById(id);
if(budget != null){
budget.addExpense(expense);
expense.setBudget(budget);
expensesRepository.saveAndFlush(expense);
}
else{
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "not all variables there");
}
model.addAttribute("expense", expense);
return "expenseResult";
}
If someone would be able to find what I am missing, I'd much appreciate it.
EDIT: I saw this in the stack trace:
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/views/error.html]
Which is strange since I do not have a error.html. I tried to rename the homing page to "error.html" and it stopped giving me the 400 response even though the overall behaviour is still wrong.
Solution 1:[1]
there is an error in the name of the object in your HTML template:
th:object="${expense}"
where do you use the class object:
public class Expenses
change in you HTML expense
to expenses
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Andronicus |