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
Related
I familiarize myself with Thymeleaf.
I am trying to get data from a POST-mapping in the controller.
But I got null variables when I call employee.getName().
I looked a lot online but can't find a solution.
My controller class
#GetMapping
public String getEmployees(Model model) {
model.addAttribute("newEmployee", new Employee());
return "employees";
}
#PostMapping
public String addEmployee(#ModelAttribute("newEmployee") Employee employee) {
System.out.println(employee); // return object
System.out.println(employee.getFirstName()); // return null
return "employees";
}
HTML form with Thymeleaf
<div class="modal-body">
<form th:action="#{/employees}" th:object="${newEmployee}" method="post">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-form-label">First Name <span class="text-danger">*</span></label>
<input th:field="*{firstName}" class="form-control" type="text">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-form-label">Last Name</label>
<input th:field="*{lastName}" class="form-control" type="text">
</div>
</div>
See tutorials:
Wim Deblauwe: Form handling with Thymeleaf
Baeldung: Binding a List in Thymeleaf
#GetMapping("/all")
public String showAll(Model model) {
model.addAttribute("employees", employeeService.findAll());
return "employees/all";
}
#GetMapping("/add")
public String createForm(Model model) {
model.addAttribute("newEmployee", new Employee()); // the form-data object as blank employee to be filled
return "employees/form"; // the page containing the form
}
#PostMapping
public String addEmployee(#ModelAttribute("newEmployee") Employee employee) {
System.out.println(employee); // return object
System.out.println(employee.getFirstName()); // return null if either not set in HTML-form or not mapped from HTML-form to POST correctly
// save new employee or add to a repository
employeeService.save(newEmployee);
model.addAttribute("employees", employeeService.findAll());
return "redirect:/employees/all"; // use a redirect
}
Client-Server interaction:
First in your browser you should navigate to the endpoint adding the form-data-object, i.e. GET /employees/add.
Then the form-page should load and you will have a blank object newEmployee to bind all the input-fields to for submitting.
After submitting the form via the submit-click, a POST /employees is sent. The server/controller should receive the form-data as model-attribute in employee parameter and can save it.
The controller-method redirects back to the list-endpoint (same as navigating in browser to) GET /employees/all
<h1>Create employee</h1>
<form th:object="${newEmployee}"
th:action="#{/employees}"
method="post">
<input type="text" name="firstName" id="firstName" th:field="*{firstName}" />
<input type="text" name="lastName" id="lastName" th:field="*{lastName}" />
<button type="submit">Submit new employee</button>
</form>
The th:object attribute refers to the key under which we put our Employee instance in the model (newEmployee in this example). The th:action has the URL for the #PostMapping method. Finally, the method attribute is set to "post" since we want to use the HTTP POST method.
Using th:field=*{…}, we can setup a two-way binding between the HTML input and the field in our form data object.
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.
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()));
I have a jsp page which uses spring tag lib. I have elements on he page that is bind to properties of an object. I also have button values that are not bind to the POJO i am trying to get these values on the server. Under is the code
JSP
<body>
<form:form id="monitoringList" name="monitoringList" commandName="monitoring">
<h3>Monitoring For Criminals Victims/Wittiness</h3>
<h3>Crime Record - ${crimeRecNo}</h3>
<div id="victims">
<h3>Victims</h3>
<hr>
<input type="hidden" id="records" value="${records}"/>
<div id="citizen_row">
<label class="name"></label>
<form:input class="citizen" type="hidden" name="socialSecurityNumber" path="socialSecurityNumber"/>
<table border="1">
<tr>
<td><form:input type="hidden" path="crimeRecNo" name = "crimeRecNo"/>
<canvas id="photoCvs${citizen.socialSecurityNumber}" class="canvas" height="200" width="200"></canvas></td>
<td><label>Start Date : </label><form:input name= "monitoringStDate" path="monitoringStDate" id="monitoringStDate"/></td>
<td><label>End Date : </label><form:input name="monitoringEndDate" path="monitoringEndDate" id="monitoringEndDate"/></td>
<td>
<label>Monitoring Type : </label>
<form:select path="monitoringTypeId" name="monitoringTypeId" id="monitoringTypeId" title="Monitoring Type">
<form:options items="${monitoringType.monitoringTypeList}" itemValue="monitoringTypeId" itemLabel="monitoringTypeDesc" />
</form:select>
</td>
</tr>
</table>
<div><button id="action" onclick="submitPage('${pageContext.request.contextPath}/monitoringList.htm','POST');" type="button">Create Monitoring Records</button></div>
</div>
<!-- MySql first record starts at 0. So we need to send in the value 0 to get the first record. Create Record Navigation based on record count -->
<div id= "recordNavigation">
<c:forEach begin="0" end="${records - 1}" var="i">
<input type="submit" class="navigationbtns" id="page" onclick="submitPage('${pageContext.request.contextPath}/monitoringList.htm','POST');" value="${i}"/>
</c:forEach>
</div>
</div>
</form:form>
</body>
This is the controller and i am using request.getParameter to get the value of the button however the value id null when i click on the button which post me to the server
Controller
#RequestMapping(value = "monitoringList.htm", method = RequestMethod.POST)
public ModelAndView handleNextMonitoringPage(#ModelAttribute("crimeRecNo")Integer crimeRecNo, Model model,#ModelAttribute Monitoring monitoring, BindingResult result,ModelMap m,HttpServletRequest request,SessionStatus status, HttpSession session) throws Exception {
String p_page = request.getParameter("page");
logger.info("Page request was ::" + p_page);
//int page = 0;
myMonitoringTypeList.put("monitoringTypeList",this.monitoringTypeManager.getListOfMonitoringType());
model.addAttribute("monitoringType",myMonitoringTypeList);
Monitoring aMonitoringRecord = new Monitoring();
aMonitoringRecord = this.monitoringManager.getAMonitoringRecByCrimeRecNo(crimeRecNo, page);
int recordCount = this.monitoringManager.MonitoringRecords_RecordCount(crimeRecNo);
model.addAttribute("records",recordCount);
model.addAttribute("crimeRecNo", crimeRecNo);
model.addAttribute("monitoring", aMonitoringRecord);
return new ModelAndView(new RedirectView("monitoringList.htm"),"page",page);
}
you are missing the name attribute under which the value is being submitted
<button name="page" ....>
and
<input type="submit" name="page" ..../>
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";}
}