Cant change column value by pressing button (Spring Boot, Thymeleaf) - spring

I get an Request method 'POST' not supported error every time I press the button
EventController.java fragment
#PostMapping(value = "/ledger/{id}/get-place")
public String modifyLedger(#PathVariable(value = "id") long id, #RequestParam Long place, Model model) {
Event event = eventRepository.findById(id).orElseThrow();
event.setPlace(place - 1);
eventRepository.save(event);
return "ledgerInfo";
}
That function suppose to substract 1 from Long place variable every time when i press the button but every time i got an HttpRequestMethodNotSupportedException error
LedgerInfo.html
<div class = "container mt-5">
<h1>Ledger Info</h1>
<div th:each="elem:${event}" class="alert alert-info mt-2">
<h2 th:text="${elem.title}"/>
Line count:<p th:text="${elem.line}"/>
Place remain:<p th:text="${elem.place}"/>
Place status:<p th:text="${elem.status}"/>
<form method="post">
<button type="submit" class="btn btn-success">Get Place</button>
</form>
</div>
</div>
Have no idea how to fix this. Any clues?

You did not specified the action for your form.
Use th:action="#{/your Url}" in the form tag.

Related

Spring Boot cannot render global error on multipart form submit

Currently I am trying to upload a CSV file containing records and this part is working fine.
However on submission of this form, if a data is not valid or missing, or if there is an import failure, I want to return a simple error message without refreshing the page.
Is it possible to return an error message on the same popup form, or is there any alternative way to do this?
Please find the code snippet below.
Form/Page:
<form id="uploadrecordform" method="POST" th:action="#{/import-record-file}" enctype="multipart/form-data">
<div class="form">
<h2>upload</h2>
<div class="form-element">
<label for="file">Upload record file</label>
<input type="file" name="file" class="form-control-file" id="file" accept=".csv" required>
</div>
<div class="form-element">
<button type="submit">
<p th:text="#{submit_text}"></p>
</button>
</div>
<div role="alert" th:if="${globalError}">
<strong>Error:</strong>
<span th:text="${globalError}"></span>
</div>
</div>
</form>
Note: on the page, there is an "add record" button and while clicking on the button, it opens the new form as a popup.
API sample code:
#RequestMapping(value = "/import-record-file", method = RequestMethod.POST)
#ResponseBody
public String importUserRecordCsvFile( #Valid #RequestParam("file") MultipartFile file, BindingResult result) {
final String username = principal.getName();
// validate file
if (file.isEmpty()) {
System.out.println("message Please select a CSV file to upload.");
ObjectError error = new ObjectError("globalError", "this is test error");
result.addError(error);
if (result.hasErrors()) {
return "errors/import-record-file";
}
}
return "empty";
}
I believe you are trying to make the controller validate the form and return the form back to the same pop up if there is an error.
You can do so using ajax. Let say your form is in a pop up and the pop up has the id popup.
<div id="popup">
<form>
<!-- form details -->
</form>
</div>
You can submit your form via ajax and have the result displayed in the pop up itself without refreshing the whole page.
The ajax function will do something as below,
$.ajax({
type: "POST",
data: formData,
url: url,
success: function (data) {
$('#popup').html(data); // data is always a simple html view
}
});
The endpoint handling the form submit (in your case, the endpoint /import-record-file) will function as follows, in case of error, the whole form is displayed back in the popup and in case of success, a simple html success message can be returned which will be displayed in the same popup.
So basically we are just overriding the content of the popup using ajax.

Spring Web application tymeleaf : POST request directed to wrong address

I have post mapping for URL: "/bank/addnew" My controller looks like:
Upon submission the form is submitted to "http://127.0.0.1:8082/banks/%20/banks" However, I need it to go to "http://127.0.0.1:8082/banks/addnew". Thanks for the Help!
#Controller
public class BankController {
#Autowired private BankService bankService;
#GetMapping("/banks")
public String bankList() {
return "bank/bank_list";
}
#PostMapping(value="/banks/addnew")
public String addNew(Bank bank) {
bankService.save(bank);
return "redirect: /banks";
}
}
And my template:
<form method="POST" action="#" th:action="#{/banks/addnew}" >
<div class="form-group">
<label for="recipient-name" class="col-form-label">Bank Name:</label>
<input type="text" class="form-control" id="recipient-name" name="name">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
The Post Method was actually working okay. I checked it by printing the Model object inside the target controller. However, it was being submitted to the database a NULL value because I didn't initialize getters and setters for my Model. Finally, there was a space in the return string, thus I removed it.
The controller Should have a return statement with no space.
return "redirect:/banks";

Spring 2 + Thymeleaf + Validation = Whitelabel Error Page 500

I'm trying to validate my form input, but after its submit it does not load my controller method, instead it shows a Whitelabel Error Page with Internal Server Errorand status 500 but with the correct validation errors.
I know it must be a matching issue with the expected parameters of my method, but so far from what I've gathered the rule is simply BindingResult then Model which I did but it still does not trigger my controller method...
Any thoughts are appreciated.
Controller-Method, that is not triggered unfortunately:
#Controller
#Validated
public class UserController {
#PostMapping("/users/add")
def String usersAdd(#Valid #ModelAttribute("user") User user, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
return "userAdd"
} else {
userRepository.save(user)
return "usersList"
}
}
Template-Form:
<form action="#" th:action="#{/users/add}" th:object="${user}" method="post">
<div class="form-row">
<div class="form-group col-md-12">
<input type="text" class="form-control" th:field="*{name}">
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<button type="submit" class="btn btn-success">Add</button>
</div>
</div>
</form>
Model-Class:
#Document(collection = "users")
public class User {
#Id
String id
#Size(min=3, max=100)
String name
}
Update:
Went debugging and found this part, so it seems it's invoking with the correct parameters. I am new to Spring, so I'm having difficulties thinking about other "newbie"-problems.
in InvocableHandlerMethod.java the method DoInvoke is called on my usersAdd with Station, BeanPropertyBindingResult, BindingAwareModelMap.
When Invoking the method it causes a ConstraintViolationException which will abort invocation, is this expected?
I figured it out after a looong debug session. The #Valid before my User user causes a ConstraintViolationException, which will, expectedly, abort the invocation of my usersAdd because, as expected, the parameter is not valid.
And the reason for this behaviour was the #Validated at the controller class, which I picked up from some tutorial, but when removed everything works and validates as expected.
I guess I was checking a REST-Tutorial and tried to use their approach... not the best idea ;)

How to POST an object to controller

I'm having a difficulty passing my 'product' object to the controller. How can I do it? I'm not getting errors. The problem is that the 'product' object is null on my controller.
html:
<section th:each="menu : ${allMenus}">
<button
<h1 th:text="${menu.name}"></h1>
</button>
<div>
<div th:each="product : ${menu.productList}">
<a data-toggle="modal" th:href="'#' + ${product.name} + 'Modal'">
h5 th:text="${product.name}"></h5>
<small th:text="${product.price} + '$'"></small>
<p th:text="${product.description}"></p>
</a>
<div th:replace="/productModal :: productModal(product=${product})"></div>
</div>
</section>
Modal:
<div th:fragment="productModal(product)">
<div role="document">
<form method="post" th:action="#{/addItemToCart}">
<div th:each="topping : ${product.toppings}">
<input type="checkbox" th:id="${topping} + ${product.id}" name="checkedToppings" th:value="${topping}" />
<label th:for="${topping} + ${product.id}" th:text="${topping}"></label>
</div>
<div>
<button type="submit">Add to Shopping Cart</button>
</div>
</form>
</div>
</div>
controller:
#RequestMapping(value="/addItemToCart", method=RequestMethod.POST)
public String addItemToCart(#ModelAttribute("product") Product product, #RequestParam("checkedToppings") List<String> toppings)
{
//product is null;
//checkedToppings are retrieved correctly
return "redirect:/menu";
}
Short answer:
you don't post objects to controllers using HTML.
Details:
You will never be able to post a "product" object to your controller from an HTML page.
Instead,
you should send identifying information about the desired "product" to the controller,
perhaps a product-id or some other product-unique-identity-blammy.
Response to options in comments:
Hackers love hidden fields and JavaScript;
I recommend against using those for this situation.
I believe that you only have one option: identifying info.
This does not need to be a "real" product number.
You can generate a UUID and store a map in the choose one: (Servlet Session, Database, Application Session, somewhere else on the server) that maps from the UUID to the desired product.

Error on submiting form MVC3 .Net

Hi there I have an error when I submit the following form:
<div id="tabs">
<ul>
<li>Project Details</li>
<li>Project Attachments</li>
<li><a href="#Url.Action("Members", "ProjectNetwork", new { IsTab = true })">Project
Network</a></li>
<li>Bulleting Board</li>
<li>Bids Received</li>
</ul>
</div>
<div id="LowerButton">
#Html.Hidden("MainStatus", #Model.Status)
#using (#Html.BeginForm("Dashboard", "Dashboard"))
{
<button type="button" id="MakeComment">
Make a Comment
</button>
<input type="submit" id="GoDashBoard" value="Return to Project List" />
}
</div>
When I press the button "GoDashBoard", The method "Dashboard" in the controller "Dashboard" is not reached. Instead the following error appears:
It tells me that a model property is beign sent to the server. However, there are no model properties inside the dashboard form.. unless I'm sending many forms at the same time. But I dont think thats possible right? Do you guys have any idea of why is trying to set a model property when I'm not actually sending any?
Update:
this is the input of the dashboard action:
public ActionResult Dashboard(int page = 1)
{
var user = (User)Session["User"];
if (user != null)
{...
}}
the input is a default integer. However, I saw the trace of the calls and its submiting another form which is not related to the one im using:
That form is inside of one of the ajax tabs. I dont understand how one form submits another form and they are not nested. Anyone knows a good workaround? because im thinking of receiving both forms in both actions and make some validations.
I solved it by removing the form "Dashboard" and instead adding an invisible link. The button would reference the invisible link:
#*#using (#Html.BeginForm("Dashboard", "Dashboard"))
{ *#
<button type="button" id="MakeComment">
Make a Comment
</button>
<button name="button" type="button" onclick="document.location.href=$('#GoDashBoard').attr('href')">Return to Project List</button>
<a id="GoDashBoard" href="#Url.Action("Dashboard", "Dashboard")" style="display:none;"></a>
#*<input type="submit" id="GoDashBoard" value="Return to Project List" />*#
#* }*#

Resources