Using #ModelAttribute and RedirectAttributes - java

I have a controller with the following methods:
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String register(Model model) {
model.addAttribute("user", new User());
return "register";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute("user") User user, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
UserValidator validator = new UserValidator();
validator.validate(user, bindingResult);
if (bindingResult.hasErrors()) {
redirectAttributes.addFlashAttribute(BindingResult.MODEL_KEY_PREFIX + "user", bindingResult);
redirectAttributes.addFlashAttribute("user", user);
return "redirect:/register";
}
...
}
My jsp:
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<form:form method="POST" modelAttribute="user" action="/registration">
<div>
<label>First Name</label>
<form:input path="firstName"/>
<form:errors path="firstName"/>
</div>
<div>
<label>Last Name</label>
<form:input path="lastName"/>
<form:errors path="lastName"/>
</div>
<div>
<label>E-mail</label>
<form:input path="email"/>
<form:errors path="email"/>
</div>
<div>
<label>Password</label>
<form:password path="password"/>
<form:errors path="password"/>
</div>
<input type="submit" value="Submit"/>
</form:form>
However, if there are errors they are not shown after the redirect because I create a new user every time the /register is called. Is there a way to fix this without storing the user in a session?
I can create another method just for this case so I can redirect to /register2 without losing the user:
#RequestMapping(value = "/register2", method = RequestMethod.GET)
public String register2() {
return "register";
}
It worked like I wanted, but it's a very bad approach.

How about checking first if a model named "user" exist before creating one on "/register" ?
if(!model.containsAttribute("user")) model.addAttribute("user", new User());
Also if I'm not wrong you can simply use #ModelAttribute on parameter and it will serve similar purpose
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String register(#ModelAttribute("user") User user) {

Related

Spring Thymeleaf classappend not appending the classes

I'm trying to classappend a few classes dependant on errors found in the validation process of a form. But for some reason, it's not appending the classes. My CSS is correct as it works without using the classappend error check and also my validation is correct as it will detect an error in the form but just won't append the css classes. The specific method used is updateRole() in the RoleController class. Below is all my code:
RoleController.java
#Controller
public class RoleController {
#Autowired
private RoleServiceImpl roleService;
#RequestMapping("/roles")
public String viewAllRoles(ModelMap model) {
List<Role> roles = roleService.findAll();
model.put("roles", roles);
if (!model.containsAttribute("role")) {
model.put("role", new Role());
}
return "roles";
}
#RequestMapping(value = "/roles", method = RequestMethod.POST)
public String addRole(#Valid Role role, BindingResult result, RedirectAttributes redirectAttributes) {
if (result.hasErrors()) {
// Add the error message as a flash attribute
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.role", result);
// Add the role object created so the user can see their inital input after redirect
redirectAttributes.addFlashAttribute("role", role);
return "redirect:/roles";
}
roleService.save(role);
redirectAttributes.addFlashAttribute("flash", new FlashMessage("Role successfully added", FlashMessage.Status.SUCCESS));
return "redirect:/roles";
}
#RequestMapping(value = "/roles/{roleId}")
public String viewRole(#PathVariable Long roleId, ModelMap model) {
Role role = roleService.findById(roleId);
model.put("role", role);
return "role";
}
#RequestMapping(value = "/roles/{roleId}", method = RequestMethod.POST)
public String updateRole(#Valid Role role, BindingResult result, RedirectAttributes redirectAttributes) {
if (result.hasErrors()) {
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.role", result);
redirectAttributes.addFlashAttribute("role", role);
return String.format("redirect:/roles/%s/edit", role.getId());
}
roleService.save(role);
redirectAttributes.addFlashAttribute("flash", new FlashMessage("Role successfully updated", FlashMessage.Status.SUCCESS));
return "redirect:/roles";
}
#RequestMapping(value = "/roles/{roleId}/edit")
public String editRole(#PathVariable Long roleId, ModelMap model) {
Role role = roleService.findById(roleId);
model.put("action", String.format("/roles/%s", roleId));
model.put("role", role);
return "role_edit";
}
}
role_edit.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="base :: head('role_edit')"></head>
<body>
<header th:replace="base :: header"></header>
<nav>
<ul>
<li><a th:href="#{projects}">Projects</a></li>
<li><a th:href="#{collaborators}">Collaborators</a></li>
<li class="selected"><a th:href="#{roles}">Roles</a></li>
</ul>
</nav>
<section>
<div class="container wrapper">
<form th:action="#{${action}}" method="post" th:object="${role}">
<input type="hidden" th:field="*{id}">
<div class="edit-input" th:classappend="${#fields.hasErrors('name')}? 'edit-error test' : ''">
<label> Role Name:</label>
<input type="text" th:field="*{name}">
</div>
<div th:class="${#fields.hasErrors('name')}? 'error' : ''">
<div class="testtwo error-message" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div>
</div>
<div class="actions">
<button class="button" type="submit" value="Submit">Save</button>
<a th:href="#{|/roles/*{id}|}" class="button button-secondary">Cancel</a>
</div>
</form>
</div>
</section>
</body>
</html>
If anyone could help it would be great, as I'm really stuck on this one.

Hibernate spring mvc formulaire

Hello I'm tryin to developpe a page that can delete users but when I click on submit I have an error Etat HTTP 400 - La requête envoyée par le client était syntaxiquement incorrecte.
Jsp file
</div>
<form method="POST" action="Users">
User ID
<input type="text" name="idUser" /><br><br>
<input type="submit" name="Supprimer" value="Supprimer"/>
</form>
Controller
#RequestMapping(value = "/Users")
public String goUsers(Model model)
{
model.addAttribute("AllUsers", UserS.getAllUsers());
return "Users";
}
#RequestMapping(value = "/Users", method = RequestMethod.POST)
public String goUsers(#ModelAttribute User user,BindingResult result,#RequestParam int id, Map<String, Object> model)
{
UserS.deleteUser(id);
return "Users";
}
thank you
Your controller wrong. You expect oen User and one param with name id but you send one param with name idUser.
Eliminate ModelAttribute and force de name of RequestParam:
#RequestMapping(value = "/Users", method = RequestMethod.POST)
public String goUsers(BindingResult result,#RequestParam(name="idUser") int id, Map<String, Object> model)
{
UserS.deleteUser(id);
return "Users";
}
1.first you need to add modelattribute to your form like this :
Notice how i am using spring forms. You can use them by adding
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
before DOCTYPE html>
Then you need to add hidden path to attribute "id" so when you controller gets the request you will know which user you will need to delete or edit.
This is example form :
`<form:form method="POST" modelAttribute="User" action="Users">
<form:hidden path="id"/>
<div class="form-group">
<label for="usernameId">Username</label>
<form:input path="username" id="usernameId" class="form-control" />
<form:errors path="username" style="color:red;"></form:errors>
</div>
<div class="form-group">
<label for="fullNameId">Full Name</label>
<form:input path="firstLastName" id="firstLastName" class="form-control"/>
<form:errors path="firstLastName" style="color:red;"></form:errors>
</div>
<div class="form-group">
<label for="passwordId">Password</label>
<form:password path="password" id="passwordId" class="form-control"/>
<form:errors path="password" style="color:red;"></form:errors>
</div>
<div class="form-group">
<label for="emailId">Email</label>
<form:input path="email" id="emailId" class="form-control"/>
<form:errors path="email" style="color:red;"></form:errors>
</div>
<input type="submit" class="btn btn-default" value="Register"/>
</form:form>`
finally you will add to your controller class.
#ModelAttribute("User")
public User getUser(){
return new User();
}
Then you will need to adjust your controller like this :
#RequestMapping(value="/Users", method=RequestMethod.POST)
public String deleteUser(User user){
getRegisterService().deleteUser(user.getId());
return "home";
}
Note : You will have to create class = User : with id attribute(and all others you need). You will also need to create a method for deleting user in your service and repository layer.
P.S. User user in your deleteUser method is actually the same user you created with #modelAttribute annotation.
If you have any additional questions feel free to ask!
I have given you almost exact form i use for register/editing or deleting Users. When you submit form, everything will be saved into object User with annotation #modelAttribute. Hidden id field is crucial here. When you have id, which is primary key you can just create method in repository (something like this)
public void deleteUser(UserJPA userJPA){
getEntityManager().remove(UserJPA);
}
Hope you find this post helpful.

form validation error message doesn't show spring mvc thymeleaf

I have add user form doesn't display the error message with thymeleaf. I try to read other solutions and apply other solutions in this forum but still doesn't work.
**userform.html**
<form id="adduser" role="form" th:action="#{/adduser}" method="post" th:object="${user}">
<div class="form-group">
<label>First Name</label>
<input class="form-control" th:field="*{first_name}"/>
<p th:if="${#fields.hasErrors('first_name')}" th:errors="${user.first_name}">First name is mandatory</p>
</div>
<button type="submit" name="action" value="adduser" class="btn btn-default" onclick="myFunction()">Submit</button>
</form>
My spring MVC controller
UserformController.java
// Returns the view with model attached
#RequestMapping(value = "/userform", method = RequestMethod.GET)
public ModelAndView showuser(HttpServletRequest request, HttpServletResponse response) {
LOGGER.info("in get adduser");
ModelAndView mav = new ModelAndView();
mav.setViewName("userform");
mav.addObject("user", new User());
return mav;
}
//Save
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
public ModelAndView adduser(#Valid #ModelAttribute("userForm") Userform user, BindingResult result, #RequestParam(value="action", required=true) String action) {
ModelAndView mav = new ModelAndView();
if (result.hasErrors()) {
mav.setViewName("redirect:userform");
mav.addObject("user", user);
return mav;
}
else {
utilService.insert(user);
mav.setViewName("redirect:userlist");
return mav;
}
}
Did you define any constraints in the User class? Please show the User class.
The errors would be based on the constraints in the properties of the User class, so there should be something like this
public class User {
#NotNull
private String first_name;
}

Neither BindingResult nor plain target object for bean name when running application

index.jsp
<f:form action="emp_change.htm" method="POST" commandName="index">
<div id="login_box">
<div id="form_val">
<div class="label">Username:</div>
<div class="control"><f:input path="emailId" /></div>
<div style="clear:both;height:0px;"></div>
<div class="label">Password:</div>
<div class="control"><f:input path="password" type="password" /></div>
<div style="clear:both;height:0px;"></div>
<div id="msgbox"></div>
<div id="login_foot">
<input type="submit" name="action" id="login" value="Login" class="send_button" />
</div>
</div>
</div>
</f:form>
AdminInfoControl.java
#Controller
public class AdminInfoControl {
private AdminInfoService service;
#RequestMapping(value = "/emp_change", method = RequestMethod.POST)
public String doActions(#ModelAttribute JtAdminInfo emp, BindingResult result, #RequestParam String action, Map<String, Object> map) {
service = new AdminInfoService();
JtAdminInfo empResult = new JtAdminInfo();
switch (action.toLowerCase()) {
case "login":
JtAdminInfo search = service.getFindAdmin(emp.getEmailId());
empResult = search != null ? search : new JtAdminInfo();
break;
}
map.put("index", empResult);
map.put("empList", service.getAll());
return "index";
}
}
I'm getting following error :
Neither BindingResult nor plain target object for bean name 'emp_change' available as request attribute
Anyone please help me to correct this. Please let me know, if information is not sufficient.
Just answered on almost the same question.. You are obtaining emp_change as a model attribute in doActions method but you didn't set it as a model attribute previously. So, set your emp_change as a model attribute in some method that e.g. shows your index.jsp page. Something like this:
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView showIndex() {
ModelAndView mav = new ModelAndView("index");
mav.addObject("emp_change", new JtAdminInfo ());
return mav;
}
I have added following method in my controller and works fine.
#RequestMapping("/index")
public String setupForm(Map<String, Object> map) {
map.put("index", new JtAdminInfo());
return "index";
}

java.lang.IllegalStateException: Neither BindingResult nor plain target object available as request attribute

When I am trying to submit (Spring) form query:
I don't get the message.
Controller
#RequestMapping(value = "beerbean", method = RequestMethod.GET)
public String showForm(#ModelAttribute("beerbean") BeerBean beerbean){
return "addbeerform";
}
#RequestMapping(value = "beerbean", method = RequestMethod.POST)
public String newBeer(Model model, #Valid #ModelAttribute BeerBean beerbean,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
return "addbeerform";
}
model.addAttribute("beani", beerbean);
return "showBeer";
}
addbeerform.jsp
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<form:form commandName="beerbean" action="${pageContext.request.contextPath}/app
/beerbean" method="POST">
<form:input path="name" /><form:errors path="name" /><br/>
<form:input path="id" /><form:errors path="id" /><br/>
<input type="submit">
</form:form>
When there isn't errors in fields it works and goes to "showBeer", but when there is it just crashes. I have also BeerBean class which implements Serializable etc., but don't think the solution is there (variables there are written like parameters in form, input path="name" goes to private String name etc).
I suggest to explicitly specify name of model attribute:
public String newBeer(
Model model,
#Valid #ModelAttribute("beerbean") BeerBean beerbean,
BindingResult bindingResult
) {

Categories