BindingResult error from submitting a form with two request parameters - java

Below is code from a controller that I'm aiming to make sure it's receiving two input parameters (name and code) from a front-end interface.
It's a page that takes two parameters within a submit form, "name" and "code".
#RequestMapping(method = RequestMethod.POST)
public String transfer(#RequestParam(name = "name") String name,
#RequestParam(name = "code") String code,
Errors errors, RedirectAttributes redirectAttributes) {
if (errors.hasErrors()) {
return "htmlPageOne";
}
try {
User userToBeTransferred = usersRepository.findByName(name);
userToBeTransferred.setTransferred(true);
Region regionOfTransference = regionsRepository.findByCode(code);
regionOfTransference.setPopulationNumber(regionOfTransference.getPopulationNumber() + 1);
userToBeTransferred.setRegion(regionOfTransference);
usersRepository.save(userToBeTransferred);
regionsRepository.save(regionOfTransference);
return "redirect:/section/users/new";
} catch (IllegalArgumentException e) {
return "htmlPageOne";
}
}
The front-page form :
<form class="form-horizontal" method="POST" action="/section/users/new" th:object="${user}">
<input type="hidden" th:field="*{id}"/>
<div class="form-group row">
<label for="name" class="col-form-label">User name</label>
<input type="text" class="form-control" id="name" th:field="*{name}" name="name"/></div>
<div class="form-group row">
<label for="code" class="col-form-label">Code</label>
<input type="text" class="form-control" id="code" th:field="*{region.code}" name="code"/></div>
<button type="submit" class="btn btn-primary col-sm-6 ">Save</button>
</form>
For some reason, I'm getting the following error after I click to submit the form :
There was an unexpected error (type=Internal Server Error, status=500).
An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the #RequestBody or the #RequestPart arguments to which they apply: public java.lang.String
I'm not sure if I'm using the requestparams correctly, so maybe it's got something to do with this? I don't know, I've been stuck on this for a few hours now, so would appreciate if someone could help me.

Related

Thymeleaf concatenates values of input fields where the attribute names of the objects are identical [duplicate]

I'm asking for help because thymeleaf does somthing weird:
Here is my form:
<form action="#" th:action="#{/add-new-board}" method="post">
<p>Board name: <input type="text" th:name="board" th:field="${board.name}" /></p>
<p th:if="${#fields.hasErrors('board.name')}" th:errors="${board.name}">Name Error</p>
<p>Section #1 name: <input type="text" th:name="section" th:field="${section.name}" /></p>
<p th:if="${#fields.hasErrors('section.name')}" th:errors="${section.name}">Name Error</p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
Here is my controller:
#GetMapping(path = "/add-new-board")
public String addNewBoardForm(Model model) {
model.addAttribute("board", new Board());
model.addAttribute("section", new Section());
return "fragments/forms/add-new-board";
}
#PostMapping(path = "/add-new-board")
public String addNewBoardSubmit(#Valid #ModelAttribute Board board,
#Valid #ModelAttribute Membership membership,
#Valid #ModelAttribute Section section,
#AuthenticationPrincipal UserDetailsImpl principal,
BindingResult result,
RedirectAttributes attributes) {
if (result.hasErrors()) {
attributes.addFlashAttribute("create_board_fail", "Check if you have all fields");
return "fragments/forms/add-new-board";
} else {
board.setCreated_at(LocalDateTime.now());
Slugify slug = new Slugify();
board.setSlug(slug.parse(board.getName()));
boardRepository.save(board);
User user = userRepository.findByEmail(principal.getEmail()).get();
membership.setMember_type(MemberType.MANAGER);
membership.setBoardId(board);
membership.setUserId(user);
membershipRepository.save(membership);
section.setBoard(board);
section.setColor(ColorType.BLUE_BASIC);
section.setOrdering(1);
sectionRepository.save(section);
attributes.addFlashAttribute("create_board_success", "You successfully added a new board!");
return "redirect:/";
}
So, my goal is to insert text from 1st input to "board" table to a column "name", and insert text from 2nd input to "section" table to a column "name". So this column titles are similar. Now when I run code, fill inputs and submit it, I'm getting to my database:
database tables img
Where "AAA" is what I wrote in 1st input, and "BBB" in 2nd
This is happening because you are using th:field incorrectly. th:field is designed to be used with a single th:object but right now you are using 2 different objects board and section. When the HTML is rendered, both inputs probably have the same name="name" and when that is submitted, the values are concatenated together and you get the behavior you are seeing.
You should instead add Board and Section to a single object, and use that as your form. For example, if you created a BoardForm object:
public class BoardForm {
private Board board = new Board();
private Section section = new Section();
// Getters and setters...
}
added that to your model instead
model.addAttribute("form", new BoardForm());
then your html would look like this
<form action="#" th:action="#{/add-new-board}" th:object="${form} method="post">
<p>Board name: <input type="text" th:name="board" th:field="*{board.name}" /></p>
<p>Section #1 name: <input type="text" th:name="section" th:field="*{section.name}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>

Update operation is not performing -Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]

I'm trying to develop an application in spring boot + thymeleaf, and I'm able to retrieve the logged in user details in the profile tab from the MySQL database, but when I try to change one or two field details (update) and hit the update button it is showing me an error message - Fri Sep 04 20:39:47 IST 2020
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
see my controller code (I'm using #RestController annotated on top of the class)-
#RequestMapping(value = "/profile", method = RequestMethod.PUT)
public ModelAndView updateProfile(#ModelAttribute Customer customer, HttpSession session) {
ModelAndView model = new ModelAndView();
Customer exist = cRepo.findByCustEmail(customer.getCustEmail());
if(exist != null) {
if(exist.getCustEmail().equals(session.getAttribute("emailsession"))) {
cRepo.save(customer);
model.addObject("msg", "User Details has been successfully updated!!");
model.setViewName("profile");
}
}else {
model.addObject("exist", "Please enter correct email address!");
String email = (String) session.getAttribute("emailsession");
Customer cust = cRepo.findByCustEmail(email);
model.addObject("customer", cust);
model.setViewName("profile");
}
return model;
}
Thymleaf code (html) -
<div align="center" class="alert alert-success" th:if="${msg}" th:utext="${msg}"></div>
<div align="center" class="alert alert-danger" th:if="${exist}" th:utext="${exist}"></div>
<!-- Modal HTML -->
<div id="myModal">
<div class="modal-dialog modal-login">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Profile Details</h4>
</div>
<div class="modal-body">
<form name="myForm" th:action="#{/profile}" th:object="${customer}" method="post">
<div class="form-group">
<i class="fa fa-id-card"></i>
<input name="id" type="text" class="form-control" placeholder="Enter Id" th:field="${customer.custId}" disabled="true" required="required" />
</div>
<div class="form-group">
<i class="fa fa-user"></i>
<input name="name" type="text" class="form-control" placeholder="Enter Name" th:field="${customer.custName}" required="required" />
</div>
<div class="form-group">
<i class="fa fa-envelope"></i>
<input name="email" type="email" class="form-control" placeholder="Enter Email" th:field="${customer.custEmail}" required="required" />
</div>
<div class="form-group">
<i class="fa fa-lock"></i>
<input name="password" type="text" class="form-control" placeholder="Enter Password" th:field="${customer.custPassword}" required="required" />
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary btn-block btn-lg" value="Update" />
</div>
</form>
</div>
</div>
</div>
</div>
I want when user login and visit he/she should be able to check his/her profile(which I'm able to do working code) and when the user wants to update few fields(1-2 based on choice) and hit update he/she should be able to update the details (not create new user or record) because when I use #Controller on top of class then this code work and create new user instead update.
Your controller is annotated with #RequestMapping(value = "/profile", method = RequestMethod.PUT) which makes it a PUT endpoint. However, your request is clearly a POST. If we look at your html form it contains method="post". HTML forms only support GET and POST as valid methods so you need to update your endpoint to be a POST endpoint.
tldr;
RequestMapping(value = "/profile", method = RequestMethod.PUT)
to
RequestMapping(value = "/profile", method = RequestMethod.POST)
You request mapping in is POST but Controller has set to accept request as PUT.
<form name="myForm" th:action="#{/profile}" th:object="${customer}" **method="post"**>
#RequestMapping(value = "/profile", method = **RequestMethod.PUT**)
Just keep these in similar way both should be same.
Please check what I find and resolve this.
#RequestMapping(value = "/profile" ,method = RequestMethod.POST)
public ModelAndView updateProfile(#ModelAttribute Customer customer, HttpSession session) {
ModelAndView model = new ModelAndView();
Customer exist = cRepo.findByCustEmail(customer.getCustEmail());
if(exist != null) {
if(exist.getCustEmail().equals(session.getAttribute("emailsession"))) {
**exist.setCustId(exist.getCustId());
exist.setCustName(customer.getCustName());
exist.setCustEmail(customer.getCustEmail());
exist.setCustPassword(customer.getCustPassword());**
cRepo.save(exist);
model.addObject("msg", "User Details has been successfully updated!!");
model.addObject("customer", exist);
model.setViewName("profile");
}
}else {
model.addObject("exist", "Please enter correct email address!");
String email = (String) session.getAttribute("emailsession");
Customer cust = cRepo.findByCustEmail(email);
model.addObject("customer", cust);
model.setViewName("profile");
}
return model;
}

Thymeleaf retrieving text from input with similar field name adding it to another separated by comma

I'm asking for help because thymeleaf does somthing weird:
Here is my form:
<form action="#" th:action="#{/add-new-board}" method="post">
<p>Board name: <input type="text" th:name="board" th:field="${board.name}" /></p>
<p th:if="${#fields.hasErrors('board.name')}" th:errors="${board.name}">Name Error</p>
<p>Section #1 name: <input type="text" th:name="section" th:field="${section.name}" /></p>
<p th:if="${#fields.hasErrors('section.name')}" th:errors="${section.name}">Name Error</p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
Here is my controller:
#GetMapping(path = "/add-new-board")
public String addNewBoardForm(Model model) {
model.addAttribute("board", new Board());
model.addAttribute("section", new Section());
return "fragments/forms/add-new-board";
}
#PostMapping(path = "/add-new-board")
public String addNewBoardSubmit(#Valid #ModelAttribute Board board,
#Valid #ModelAttribute Membership membership,
#Valid #ModelAttribute Section section,
#AuthenticationPrincipal UserDetailsImpl principal,
BindingResult result,
RedirectAttributes attributes) {
if (result.hasErrors()) {
attributes.addFlashAttribute("create_board_fail", "Check if you have all fields");
return "fragments/forms/add-new-board";
} else {
board.setCreated_at(LocalDateTime.now());
Slugify slug = new Slugify();
board.setSlug(slug.parse(board.getName()));
boardRepository.save(board);
User user = userRepository.findByEmail(principal.getEmail()).get();
membership.setMember_type(MemberType.MANAGER);
membership.setBoardId(board);
membership.setUserId(user);
membershipRepository.save(membership);
section.setBoard(board);
section.setColor(ColorType.BLUE_BASIC);
section.setOrdering(1);
sectionRepository.save(section);
attributes.addFlashAttribute("create_board_success", "You successfully added a new board!");
return "redirect:/";
}
So, my goal is to insert text from 1st input to "board" table to a column "name", and insert text from 2nd input to "section" table to a column "name". So this column titles are similar. Now when I run code, fill inputs and submit it, I'm getting to my database:
database tables img
Where "AAA" is what I wrote in 1st input, and "BBB" in 2nd
This is happening because you are using th:field incorrectly. th:field is designed to be used with a single th:object but right now you are using 2 different objects board and section. When the HTML is rendered, both inputs probably have the same name="name" and when that is submitted, the values are concatenated together and you get the behavior you are seeing.
You should instead add Board and Section to a single object, and use that as your form. For example, if you created a BoardForm object:
public class BoardForm {
private Board board = new Board();
private Section section = new Section();
// Getters and setters...
}
added that to your model instead
model.addAttribute("form", new BoardForm());
then your html would look like this
<form action="#" th:action="#{/add-new-board}" th:object="${form} method="post">
<p>Board name: <input type="text" th:name="board" th:field="*{board.name}" /></p>
<p>Section #1 name: <input type="text" th:name="section" th:field="*{section.name}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>

Redirection issues under subdomains

I have been doing a basic application, which may contain all the issues I have had recently.
I tried to map the endpoints specified in the code under "/example/", "/example/add" and "/example/add2", but unfortunately I got 404 when I tried to submit the form.
My code works if I don't use subdomains, jut map everthing under "/".
Here's my relevant code:
//#RequestMapping("/example") --> also tried to put it here
public class AttractionController {
private AttractionService attractionService;
#Autowired
public AttractionController(AttractionService attractionService) {
this.attractionService = attractionService;
}
#RequestMapping("/example")
#GetMapping("/")
String main(Model model) {
model.addAttribute("attractions", attractionService.findAll());
return "main";
}
#PostMapping("/add")
String add(#ModelAttribute Attraction attraction) {
attractionService.save(attraction);
return "redirect:/";
}
#PostMapping("/add2")
String add2(#RequestParam String name, #RequestParam Double latitude,
#RequestParam String city, Model model) {
attractionService.save(new Attraction(name, latitude, city));
return "redirect:/";
//also tried to use return "redirect:/example"
}
HTML:
<form th:method="POST" th:action="#{add}">
<input type="text" name="name">
<input type="text" name="latitude">
<input type="text" name="city">
<input type="submit">
</form>
<form th:method="POST" th:action="#{add2}">
<input type="text" name="name">
<input type="text" name="latitude">
<input type="text" name="city">
<input type="submit">
</form>
How could I solve this issue?

How to retrieve form elements at controller in java

I am trying to submit a form to controller in using java spring, in following code i am retrieving file element by following way successfully but not getting how to retrieve other elements(shortname and full name)value.
please help me out.
<body>
<div style="text-align: center; margin-top: 60px;">
<form action="upload" enctype="multipart/form-data">
<input type="hidden" id="shortName" name="michael">
<input type="hidden" id="fullName" name="michael jackson">
Select file:
<input type="file" name="dataFile" id="fileAttachment"/><br/><br/>
<div style="text-align: center; margin-top: 100px;">
<input style="cursor: pointer;" onmouseover="" onclick="uploadAttachment()" class="dialogbox" type="submit" value="Upload Report" />
</div>
</form>
</div>
</body>
Controller side code :
#RequestMapping(value = "upload", method=RequestMethod.POST)
public void upload(HttpServletRequest request, HttpServletResponse response,
#RequestPart("dataFile") MultipartFile file
){
System.out.println(file.getSize());
}
first change the input elements and create the name attribute for both shortName and fullName like so :
<input type="hidden" id="shortNameId" name="shortName" value="michael">
<input type="hidden" id="fullNameId" name="fullName" value="michael jackson">
however you can remove the default value attribute and just enter the value yourself when the page render so value="michael" & value="michael jackson" are optional !
Then you can retrieve those input elements like this :
#RequestMapping(value = "upload", method=RequestMethod.POST)
public void upload(HttpServletRequest request, HttpServletResponse response, #RequestParam("shortName")String shortName, #RequestParam("fullName")String fullName
#RequestPart("dataFile") MultipartFile file
){ .... }
Good Luck !
In your controller, try something like this,
#RequestMapping(value = "/your/url/{formParamenter}", method = RequestMethod.GET)
public String yourfunction(#PathVariable("formParameter") Type formParameter{}
The Type is the type of data, (String/int/float..etc).
In your case just change RequestPart to #PathVariable

Categories

Resources