I am making a Spring MVC project and i want to register new user.In my first page user sumbit his details like full name,address,mobilenumber etc when user enter the details i will send a OTP on his mobile and Store OTP in CacheLoader.Then i redirect the otp page and also use flashAttribute to use in OTPController GET method.I want when user enter OTP the full data comes to POST method and i will validate OTP then i save the full data in DB.
UserDetailsController.java
#RequestMapping(method = RequestMethod.POST)
public String addUser(#Valid #ModelAttribute("addUser") UserPojo userPojo, BindingResult bindingResult,
Model modelMap, final RedirectAttributes redirectAttributes) {
otpService.clearOTP(userPojo.getPhoneNumber());
boolean validate = adminUserService.uniqueUserName(userPojo.getUserName());
if (validate == false) {
int otp = otpService.generateOTP(userPojo.getPhoneNumber());
String response = smsService.sendOtp(otp, userPojo.getPhoneNumber());
if(response.equals("OK")) {
redirectAttributes.addFlashAttribute("addUser", userPojo);
logger.debug(addUserPojo.toString());
return "redirect:/userotp";
}
logger.debug("response is-OTP Failed");
redirectAttributes.addFlashAttribute("error", "Problem is Send OTP");
return "redirect:/admin/adduser";
}
redirectAttributes.addFlashAttribute("error", "UserName Must Be Unique");
return "redirect:/admin/adduser";
}
OtpController.java
#RequestMapping(value = "/userotp", method = RequestMethod.GET)
public String showAddUser(#ModelAttribute("addUser") UserPojo userPojo,
final BindingResult mapping1BindingResult, final Model model, ModelMap map,
final RedirectAttributes redirectAttributes) {
logger.debug("Enter in the Method" + this.getClass().getSimpleName());
logger.debug("Data is" + addUserPojo.toString());
return "userotp";
}
#RequestMapping(value = "/userotp", method = RequestMethod.POST)
public String validateUser(
final BindingResult mapping1BindingResult, Model model, final RedirectAttributes redirectAttributes,
HttpServletRequest request) {
logger.debug("Enter in the Method" + this.getClass().getSimpleName());
return "userotp";
}
userotp.html
<form:form method="post">
<div class="" role="document" style="padding: 0px 30%;">
<div class=" box">
<h5 class="">User Moblie No. Verify</h5>
<div class="">
<label>Moblie Number For Otp</label> <form:input type="number"
class="form-control" name="otp" placeholder="Enter OTP"/>
<br> <br>
<div class="float-right">
<button type="reset" class="btn btn-secondary">Reset</button>
<button type="submit" class="btn btn-primary">Verify</button>
</div>
</div>
</div>
</div>
</form:form>
I want to get data UserDetails in OtpController POST method.Can anyone help me.
I think you should use #SessionAttributes. To use #SessionAttributes we can store modelAttribute in Session and when there is no use of modelAttribute. We can remove it.
We can remove it like this:
#RequestMapping(value = "/userotp", method = RequestMethod.POST)
public String validate(#ModelAttribute User user, WebRequest request, SessionStatus status) {
// your business logic
status.setComplete();
request.removeAttribute("user", WebRequest.SCOPE_SESSION);
return "userotp";
}
Related
I have ReservationController that have 2 methods:
#GetMapping
public String getReservationPage(final Model model,
final #PathVariable String hotelId,
final #PathVariable String roomId) {
final RoomApi roomApi = roomClient.findById(roomId).getBody();
model.addAttribute("roomApi", roomApi);
model.addAttribute("hotelId", hotelId);
model.addAttribute("roomId", roomId);
model.addAttribute("reservationForm", new ReservationApi().toBuilder()
.room(roomApi)
.build());
return "reservation";
}
#PostMapping
public String createReservation(final #PathVariable String roomId,
final #PathVariable String hotelId,
final #ModelAttribute("reservationForm") ReservationApi reservationApi) {
final Reservation reservation = reservationMapper.toDomain(reservationApi);
reservationService.save(reservation);
return "redirect:/";
}
And I have one problem, that relate to the roomApi. So how can I transfer roomApi from the getReservationPage to the crateReservation in reservationForm. I also have thymeleaf page with some form, but when I click submit button, roomApi is null in reservation. I think thats because of thymeleaf form does not contain any information about roomApi in reservation, but Im addinig it with builder.
<form th:object="${reservationForm}"
method="post"
th:action="#{/hotels/{hotelId}/rooms/{roomId}/reservations(hotelId=${hotelId}, roomId=${roomId})}">
<div class="form-group">
<label for="additionalInformation">Additional Information</label>
<input type="text" th:field="*{additionalInformation}" th:name="additionalInformation" class="form-control form-control-sm" id="additionalInformation">
</div>>
<button type="submit">Reserve</button>
</form>
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;
}
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";
}
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) {
Login form:
<f:form class="form-horizontal" method="post" action="/login"
commandName="logindata">
<fieldset>
<legend class="text-info">Login</legend>
<div class="control-group">
<f:label path="uname" class="control-label" for="uname">Username</f:label>
<div class="controls">
<f:input type="text" path="uname" name="uname" id="uname"
placeholder="Username" />
</div>
</div>
<div class="control-group">
<f:label path="pwd" class="control-label" for="pwd">Password</f:label>
<div class="controls">
<f:input type="password" path="pwd" name="pwd" id="pwd"
placeholder="Password" />
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn" id="login">
Login <i class="icon-chevron-right"></i>
</button>
</div>
</div>
<div id="errormsg" class="alert alert-error">${message}</div>
</fieldset>
</f:form>
the loginData class:
package com.demo.forms;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
public class loginData {
#Length(min=4)
private String uname;
#NotEmpty
private String pwd;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
Controller methods for showing and submitting the form: (Shows homepage which contains signup form and login form)
#RequestMapping(value = "/", method=RequestMethod.GET)
public String showHome(Model model)
{
loginservice.logout();
model.addAttribute("logindata", new loginData());
model.addAttribute("signupdata", new signupData());
return "home";
}
Method called upon submitting login form:
#RequestMapping(value = "login", method=RequestMethod.POST)
public String submitloginForm(#Valid loginData logindata, SessionStatus state, Model model, BindingResult result)
{
if((loginservice.loggedin()) || (result.hasErrors()))
{
return showHome(model);
}
else
{
String uname = logindata.getUname();
String pwd = logindata.getPwd();
if(loginservice.login(uname, pwd))
{
model.addAttribute("user",uname);
return "redirect:profile";
}
else
{
model.addAttribute("message","Invalid Username/Password");
return showHome(model);
}
}
}
The login works fine when the data entered is 'valid' (either correct or wrong). However, when it is invalid, for instance, when the password field is empty or the username is less than four characters long, following error is shown:
The request sent by the client was syntactically incorrect.
Any idea how this might be fixed?
You have to modify the order of your arguments. Put the BindingResult result parameter always directly after the parameter with the #Valid annotation.
#RequestMapping(value = "login", method=RequestMethod.POST)
public String submitloginForm(#Valid loginData logindata, BindingResult result,
SessionStatus state, Model model)
This was even mentioned in this weeks This Week in Spring - March 5th, 2013 blog entry
Someone asked me this the other day and I felt like it was worthy of a
mention: in your Spring MVC #Controller class handler methods, make
sure that the BindingResult argument is immediately after the model or
command argument, like this: #RequestMapping(...) public String
handleRequest( #ModelAttribute #Valid YourCustomPojo attempt,
BindingResult result). In this example, handleRequest will validate
the POJO (YourCustomPojo) - checking the POJO for JSR303-annotations
and attempting to apply the constraints because the POJO is annotated
with #Valid - and stash any errors in the BindingResult, which it
makes available if we ask for it.
Spring will
0) determin the handler method
1) create an instance of loginData
2) populate it
3) validate it, and store the validation result in BindingResult
4) invoke the method (with loginData and BindingResult values), no matter whenever the binding Result contains an error or not