How to pass ModelAttrubute parameters using MockMvc? - java

I have this html spring form:
<form:form action="addVacancy" modelAttribute="myVacancy">
<form:label path="name">name</form:label>
<form:input path="name" ></form:input>
<form:errors path="name" cssClass="error" />
<br>
<form:label path="description">description</form:label>
<form:input path="description" id="nameInput"></form:input>
<form:errors path="description" cssClass="error" />
<br>
<form:label path="date">date</form:label>
<input type="date" name="date" />
<form:errors path="date" cssClass="error" />
<br>
<input type="submit" value="add" />
</form:form>
I handle this form by this method:
#RequestMapping("/addVacancy")
public ModelAndView addVacancy(#ModelAttribute("myVacancy") #Valid Vacancy vacancy,BindingResult result, Model model,RedirectAttributes redirectAttributes){
if(result.hasErrors()){
model.addAttribute("message","validation error");
return new ModelAndView("vacancyDetailsAdd");
}
vacancyService.add(vacancy);
ModelAndView mv = new ModelAndView("redirect:goToVacancyDetails");
mv.addObject("idVacancy", vacancy.getId());
redirectAttributes.addAttribute("message", "added correctly at "+ new Date());
return mv;
}
How to make the same request, which is obtained after submitting the form. This must be done by means of MockMvc.
#Test
public void testMethod(){
MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/addVacancy");
//what must I write here?
ResultActions result = mockMvc.perform(request);
}
I very confused.

When a browser needs to submit a form, it typically serializes the form <input> fields as url-encoded parameters. Therefore, when you want to mock an HttpServletRequest, you need to add those same parameters to the request.
request.param("name", "some value")
.param("description", "description value")
.param("date", "some acceptable representation of date");
The DispatcherServlet will use these parameters to create a Vacancy instance to pass as an argument to your handler method.

You can pass in the required #ModelAttribute object with the .flashAttr() method like so:
request.flashAttr("myVacancy", new Vacancy()));

Related

Java spring - "required int parameter is not present"

I'm new in Spring. I am trying to create editUser.jsp for purpose of editing user in mysql database.
For that reason, I created controller and method for passing data from userList.jsp form to editUser.jsp.
Here is the code:
#RequestMapping(value = "/editUser", method = RequestMethod.POST)
private String editUser(#RequestParam int id, Model model) {
Users user = (Users) session.load(Users.class, id);
ModelAndView mv = new ModelAndView("user");
model.addAttribute("user", user);
if(user.getId()!=null){
Transaction transaction = session.beginTransaction();
session.update(user);
transaction.commit();
}
return "editUser";
}
And data are well passed to the editUser page. Now, when I try to edit and submit data I got error message:
Required int parameter 'id' is not present
<form:form action="editUser.htm" method="GET" commandName="editUser">
<div>Account Information</div>
<div>
<form:label path="uname">User name:</form:label><br/>
<form:input id="uname" type="text" path="uname"></form:input><br/>
<form:label path="pass">Password:</form:label><br/>
<form:input id="pass" type="text" path="pass"></form:input><br/>
</div>
<br/><br/>
<div>Contact Information</div>
<div>
<form:label path="gender">Choose gender:</form:label><br/>
<form:select id="gender" type="text" path="gender">
<form:option value="Female">Female</form:option>
<form:option selected="selected" value="Male">Male</form:option>
</form:select><br/>
<form:label path="age">Age:</form:label><br/>
<form:input id="age" type="text" path="age"></form:input><br/>
<form:label path="age">Address:</form:label><br/>
<form:input id="address" type="text" path="address"></form:input><br/>
</div>
<input type="submit" value="Edit User"/>
</form:form>enter code here
Do I need maybe create another method in the controller which should handle update data in the database or update handling could be done in existing method (currently, I'm totaly confused how jsp page "know" which method from Controller would be called)?
Database column id is set - auto increment.
Thanks in advance.
#RequestParam(value="id",required="false") int id

Input/Textarea - Required string parameter is not present

I'm having issues with the above code recognizing the 'defaultpagination' variable. It keeps throwing the 'Required String parameter 'defaultpagination' is not present' message on the user interface. This is part of an edit screen showing a configurable setting.
The controller method is below.
#RequestMapping(value = "/update", method = RequestMethod.POST)
public ModelAndView updateSetting(
#RequestParam("defaultpagination") String defaultPagination,
#RequestParam("id") long id) {
Setting setting = settingService.getOne(id);
setting.setDefaultPagination(Integer.parseInt(defaultPagination));
settingService.saveSetting(setting);
return new ModelAndView("redirect:/settings/setting-listing");
}
The thymleaf html can be seen below.
<form role="form" data-toggle="validator" name="createSetting" enctype="multipart/form-data" method="post" th:object="${setting}" action="/settings/update">
<div class="form-group">
<label for="defaultpagination">Default Pagination</label>
<input class="form-control" name="defaultpagination" type="number" th:field="${setting.defaultPagination}" placeholder="Enter default pagination" required="required" data-error="Pagination is required (maximum cannot exceed 100)" />
<div class="help-block with-errors"></div>
</div>
<input type="hidden" th:rows="1" class="form-control" id="id" name="id" th:value="${setting.id}"/>
<br />
<button type="submit" class="btn btn-default">Submit Button</button>
<br />
<br />
<br />
</form>
What's interesting is that I can change the 'input' tag to a textarea tag and everything would work as normal (the defaultpagination gets recognized). However, I want to use the input for validation. In this case the input needs to be a number. In similar cases, I will need a phone number and email. Has anyone faced this same problem regarding the input/textarea tag in thymeleaf?
one solution would be to change the String defaultPagination in the controller to Integer (if you expect only integer as defaultpagination)
ie
#RequestMapping(value = "/update", method = RequestMethod.POST)
public ModelAndView updateSetting(
#RequestParam("defaultpagination") Integer defaultPagination,
#RequestParam("id") long id) {
Another solution is to use the pattern attribute of the input tag (permit only numbers not decimal points)
<input class="form-control" name="defaultpagination" type="text"
pattern="\d+" th:field="${setting.defaultPagination}" placeholder="Enter default
pagination" required="required" data-error="Pagination is required (maximum cannot exceed 100)" />
Let me know if these worked for you

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.

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'userEditCommand' available as request attribute

#RequestMapping(value = "/user-edit-form", method = RequestMethod.POST)
public String userEditForm(#ModelAttribute("userEditCommand") UserEntity userEntity, BindingResult result, ModelAndView model, #RequestParam("userPhotoPath") MultipartFile file, HttpServletRequest request) throws IOException {
((Model) model).addAttribute("user", new UserEntity());
return "staff-user-profile";
//return new ModelAndView("staff-user-profile","user",userEntity);
}
staff-user-profile.jsp
<form:form class="form-horizontal" action="staff-edit-form" commandName="userEditCommand" enctype="multipart/form-data" modelAttribute="userEditCommand">
<form:label path="userFirstName" >First name:</form:label>
<form:input path="userFirstName" value="${user.userFirstName }"/>
<form:label path="userLastName" >Last name:</form:label>
<form:input path="userLastName" value="${user.userLastName }"/>
<form:label path="userAddress" >Address:</form:label>
<form:textarea path="userAddress" cols="5" rows="3" value="${user.userAddress }"></form:textarea>
<form:label path="userCity" >City:</form:label>
<form:input path="userCity" value="${user.userCity }" />
<form:label path="userCountryId" >Country:</form:label>
<form:select path="userCountryId" >
<form:options items="${countryList}" />
</form:select>

How to prepopulate an object before updating using spring mvc and hibernate?

What's the best practice to pre-populate an object before saving this object with hibernate?
What i've done:
My controller:
//The Form
#RequestMapping(value = "user/{id}/edit", method = RequestMethod.GET)
public String edit(#PathVariable("id") Long userId, ModelMap modelMap) {
modelMap.addAttribute("user", userService.find(userId));
return "user/userEdit";
}
//Updating database
#RequestMapping(value = "user/edit", method = RequestMethod.POST)
public String update(#ModelAttribute("user") #Valid User user, BindingResult result,
RedirectAttributes redirectAttrs) {
if (result.hasErrors()) {
return "user/userEdit";
}else{
userService.update(user);
redirectAttrs.addFlashAttribute("message", "Success");
return "redirect:user/userEdit";
}
}
It works if i make a form containing all fields (username, password and id) , but what should i do if i want the user to update only the password?
Since i have a #NotEmpty at username, i get an error that username is null, since its not in the form, but i dont want to put the username field, just the password.
My html form:
<c:url var="url" value="/user/edit" />
<form:form method="post" action="${url}" modelAttribute="user" class="form-horizontal">
<form:hidden path="id"/>
<form:hidden path="version"/>
<fieldset>
<div class="control-group">
<form:label cssClass="control-label" path="password"><spring:message code="user.label.password"/>: </form:label>
<div class="controls">
<form:input cssClass="input-xlarge" path="password" />
</div>
<form:errors path="password"/>
</div>
<div class="control-group">
<form:label cssClass="control-label" path="userRole"><spring:message code="user.label.role"/>: </form:label>
<div class="controls">
<form:select path="userRole">
<form:options items="${userRoleList}" itemValue="id" itemLabel="name"/>
</form:select>
</div>
<form:errors path="userRole"/>
</div>
<div class="control-group">
<form:label cssClass="control-label" path="costumer.id"><spring:message code="user.label.costumer"/>: </form:label>
<div class="controls">
<form:select path="costumer.id">
<form:options items="${costumerList}" itemValue="id" itemLabel="name"/>
</form:select>
</div>
<form:errors path="costumer.id"/>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save changes</button>
<a class="btn cancel link" href="<c:url value="/user" />">Cancel</a>
</div>
</fieldset>
</form:form>
I tried using #Sessionattributes, but it doesnt work well if i try to
edit two or more users using browser tabs.
I tried using property editors, but didnt work with #ModelAtrribute
User user.
I tried using convertors but didnt work.
Is the only way to make a User user = userService.find(id) first, and then set the updated values? Something like:
#RequestMapping(value = "user/edit", method = RequestMethod.POST)
public String update(#RequestParam("password") String password, BindingResult result, RedirectAttributes redirectAttrs) {
User user = userService.find(id);
if (password == null{
return "user/userEdit";
}else{
user.setPassword("password");
userService.update(user);
redirectAttrs.addFlashAttribute("message", "Success");
return "redirect:user/userEdit";
}
}
Which seens wrong, because there is no validation.
An alternate way, that I think is less messy and accident-prone, is to create a class that models the UI form, for example
public class EditUserForm {
// getters and setters for password and other fields...
}
and in the controller's update(EditUserForm,...) method, you simply map any fields populated by the user in the EditUserForm to the instance of User you wish to update.
In the code you posted it's obviously clear that you need some external helper classes to associate with your GUI side updating before you implement the move-control and persistence operations.
I've run into this problem too, if there's only a couple fields I use your second example and validate the fields one by one. Otherwise, you're going to have to do what the other posters have said and make a new class to match your form.
Try to use:
#PrePersist
#PreUpdate
public void prepare(){
//DO SOMETHING WITH YOUR ENTITY
//For example: if(name==null){ name="MYNAMEVALUE";}
}

Categories