I am trying to send a request from a Bootstrap Modal via a Spring Form whereby a user can change their password provided that their current password is input correctly. I am having a bit of trouble understanding the logistics of how this will be processed, currently I have a form:
<!-- Modal -->
<form:form modalAttribute="user" action="changepass" method="POST">
<div id="changePassModal" class="modal fade modal-password" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h3 class="modal-title"><b>Change Password </b></h3>
</div>
<table>
<tr>
<td>Current Password :</td>
<td><form:password path="currentpassword" />
</td>
<td><form:errors path="currentpassword" />
</td>
</tr>
<tr>
<td>Password :</td>
<td><form:password path="newpassword" />
</td>
<td><form:errors path="newpassword"/>
</td>
</tr>
<tr>
<td>Confirm Password :</td>
<td><form:password path="newpasswordconfirmation" />
</td>
<td><form:errors path="newpasswordconfirmation"/>
</td>
</tr>
</table>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<input type="submit" class="btn btn-primary" value="Save Changes" />
</div>
</div>
</div>
</div>
</form:form>
EDIT: Added Main Controller Class
package controller;
import java.security.Principal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import model.User;
@Controller
public class MainController {
/** Constructors **/
@ModelAttribute("user")
public User constructUser(){
return new User();
}
/** Mapping URI **/
@RequestMapping(value ={"/", "/login"}, method = RequestMethod.GET)
public String loginPage(Model model) {
return ("loginPage");
}
@RequestMapping(value = "/logoutSuccessful", method = RequestMethod.GET)
public String logoutSuccessfulPage(Model model) {
model.addAttribute("title", "Logout");
return "logoutSuccessfulPage";
}
@RequestMapping(value = "/home", method = RequestMethod.GET)
public String loginPage(Model model, Principal principal) {
model.addAttribute("title", "Home");
String userName = principal.getName();
model.addAttribute("message",
"Welcome Home " + userName);
return "homePage";
}
@RequestMapping(value = "/useradmin", method = RequestMethod.GET)
public String adminPage(Model model) {
model.addAttribute("title", "Admin");
model.addAttribute("message", "Admin Page - This is protected!");
return "userAdmin";
}
@RequestMapping(value = "/403", method = RequestMethod.GET)
public String accessDenied(Model model, Principal principal) {
model.addAttribute("title", "Access Denied!");
if (principal != null) {
model.addAttribute("message", "<br>Error 403"
+ "<br> You do not have permission to access this page!");
} else {
model.addAttribute("msg",
"You do not have permission to access this page!");
}
return "403Page";
}
/** Form Handling **/
@RequestMapping(value = "/changepass", method = RequestMethod.POST)
public String changePassword(@ModelAttribute ("user") User user, Principal principal) {
// for testing purpose:
String name = principal.getName();
System.out.println("entered changePass");
return "redirect:/home.jsp";
}
}
I end up with the error (when loading the screen):
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init> (BindStatus.java:144)
EDIT: Add User Class
package model;
public class User {
private String username;
private String currentpassword;
private String newpassword;
private String newpasswordconfirmation;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCurrentpassword() {
return currentpassword;
}
public void setCurrentpassword(String currentpassword) {
this.currentpassword = currentpassword;
}
public String getNewpassword() {
return newpassword;
}
public void setNewpassword(String newpassword) {
this.newpassword = newpassword;
}
public String getNewpasswordconfirmation() {
return newpasswordconfirmation;
}
public void setNewpasswordconfirmation(String newpasswordconfirmation) {
this.newpasswordconfirmation = newpasswordconfirmation;
}
}
mvc-dispatcher-servlet
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:component-scan base-package="controller" />
<context:annotation-config />
<mvc:default-servlet-handler/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/css/, /resources/js/, /resources/images/, /resources/fonts/" cache-period="31556926"/>
<mvc:annotation-driven />
</beans>
Do I need to map a user bean in the dispatcher? I have tried a number of different approaches to this including simpleforms (deprecated). I also believe that modelAttribute should be used instead of command.
Any advice is well received.
Add the model attribute "user" to the model in a GET request which will be called before form submission.
Example
Get request to load page and form
@RequestMapping(value ={"/", "/login"}, method = RequestMethod.GET)
public String loginPage(Model model) {
model.addAttribute("user", new User()); // Here it is added to the model
return ("loginPage");
}
Form submission
@RequestMapping(value = "/changepass", method = RequestMethod.POST)
public String changePassword(@ModelAttribute ("user") User user, Principal principal) {
// for testing purpose:
String name = principal.getName();
System.out.println("entered changePass");
return "redirect:/home.jsp";
}