Passing an object from view to controller - spring-mvc

I want to add new message to database from my .jsp inputs via controller. I tried to just create new object of message in controller and put it in database and it works fine. But when I try to do it using inputs i receive error like this:
SEVERE [http-nio-8080-exec-2]org.springframework.web.servlet.tags.form.InputTag.doStartTag Neither BindingResult nor plain target object for bean name 'message' available as request attribute
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'message' available as request attribute
My code:
#Controller
public class DemoController {
#Autowired
UserService userService;
#Autowired
MessageService messageService;
#PostMapping("/messages/sendNewMessage")
public String sendNewMessage(#ModelAttribute("message") MessagesEntity tempMessage) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
tempMessage.setFromUsername(userService.getUser(auth.getName()));
messageService.sendNewMessage(tempMessage);
return "redirect:/messages";
}
}
JSP here
<form:form action="sendNewMessage" modelAttribute="message" method="POST">
<table>
<tbody>
<tr>
<td><label>Username:</label></td>
<td><form:input path="toUsername" /></td>
</tr>
<tr>
<td><label>Subject:</label></td>
<td><form:input path="subject" /></td>
</tr>
<tr>
<td><label>Content:</label></td>
<td><form:input path="content" /></td>
</tr>
<tr>
<td><label></label></td>
<td><input type="submit" value="Send" class="save" /></td>
</tr>
</tbody>
</table>
</form:form>

you are using action url as sendNewMessage in jsp view but in the controller, it is /messages/sendNewMessage.

You need to put MessagesEntity object in ModelAttribute.
Either define the ModelAttribute while loading the form page like below.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String messageForm(Model model) {
model.addAttribute("message", new MessagesEntity());
return "messageFormPageName";
}
or Put below method in the controller which will be common for complete controller so ModelAttribute will be available always.
#ModelAttribute("message")
public MessagesEntity createModel() {
return new MessagesEntity();
}

Related

Neither BindingResult nor plain target object for bean name xxx available as request attribute

"Neither BindingResult nor plain target object for bean name 'loginCommand' available as request attribute"
I keep getting this Binding result error and nothing I've tried seems to be making it stop. I've seen other posts for this question, but none of them seem to fix whatever issue I'm having.
This is the first controller of my new project and I had some issues getting the xml squared away. I think that's all fixed, but if nothing looks off I supposed the problem could be there. The weird thing is that all this code is almost straight copied from another project I have and it works just fine.
Also I'm running on glassfish if that matters at all. Thanks in advance!
edit: The webpage is /morencore/login.jsp. I tried going to login.html assuming that would bring it up, but it only seems to work when I go to login.jsp. I believe I tried changing my controller to map to the jsp instead, but that did not work.
here is my login.jsp page:
<form:form method="post" modelAttribute="loginCommand">
<form:errors cssClass="error" element="p" />
<table border="0">
<tr>
<td align="right">Username:</td>
<td><form:input path="userName" /> <form:errors path="userName" cssClass="error" /></td>
</tr>
<tr>
<td align="right">Password:</td>
<td><form:password path="password" /> <form:errors path="password" cssClass="error" /></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" id="submit" name="submit" value="Log In" disabled="disabled"></td>
</tr>
</table>
</form:form>
and here is my controller:
#Controller
#ControllerAdvice
#RequestMapping("/login.html")
public class LoginController {
protected final Logger logger = LogManager.getLogger(getClass());
#Autowired
protected LoginValidator loginValidator;
#RequestMapping(method= RequestMethod.GET)
protected String initializeForm(#ModelAttribute("loginCommand")LoginCommand loginCommand,
BindingResult result,
ModelMap model)
{
logger.info("INITIALIZING LOGIN FORM");
model.addAttribute("loginCommand", new LoginCommand());
return "login";
}
#InitBinder("loginCommand")
protected void initBinder(ServletRequestDataBinder binder) throws Exception
{
binder.addValidators(loginValidator);
}
#RequestMapping(method=RequestMethod.POST)
protected String onSubmit(#ModelAttribute("loginCommand")LoginCommand loginCommand,
BindingResult result,
HttpServletRequest request) throws Exception
{
logger.info("validating login input");
loginValidator.validate(loginCommand, result);
if (result.hasErrors())
{
result.reject("login.failure");
return "login";
}
UserDao userDao = new UserDao();
User user = userDao.by_name(loginCommand.getUserName());
if (user == null
|| !user.getName().equals(loginCommand.getUserName())
|| !user.getPassword().equals(loginCommand.getPassword()))
{
result.reject("login.failure");
return "login";
}
return "redirect:main.html";
}
}
Here is my LoginCommand class:
#XmlRootElement
public class LoginCommand
{
private String userName;
private String password;
/** blah blah blah getters and setters*/
}
Here is the full stack trace as requested:
Neither BindingResult nor plain target object for bean name 'loginCommand' available as request attribute
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'loginCommand' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:142)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:188)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:154)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:141)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:132)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:116)
at org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:422)
at org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:142)
at org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:84)
at org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80)
at org.apache.jsp.login_jsp._jspx_meth_form_input_0(login_jsp.java:233)
at org.apache.jsp.login_jsp._jspService(login_jsp.java:126)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1580)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:338)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.glassfish.tyrus.servlet.TyrusServletFilter.doFilter(TyrusServletFilter.java:305)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:250)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:652)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:591)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:463)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:168)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:242)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
Among other things, it seems like your mappings need to be modified. Here is what I would try. There are a lot of adjustments so no guarantees on whether it will work completely, but it should get you in the right direction.
#Controller
public class LoginController {
protected final Logger logger = LogManager.getLogger(getClass()); //look at SLF4J instead. Then you're not tied to a specific logger and you use a facade.
#Autowired //may want to use constructor wiring instead on these
private LoginValidator loginValidator;
#Autowired
private UserDao userDao; //this should be wired and not simply instantiated - Spring won't know about it otherwise
#Autowired
private LoginValidator loginValidator;
#GetMapping("/login")
public String initializeForm(Model model) {
logger.info("INITIALIZING LOGIN FORM");
model.addAttribute("loginCommand", new LoginCommand());
return "login";
}
#PostMapping("/loginPost")
public String onSubmit(#ModelAttribute("loginCommand") LoginCommand loginCommand,
BindingResult result) throws Exception {
logger.info("validating login input");
loginValidator.validate(loginCommand, result);
if (result.hasErrors()) {
result.reject("login.failure");
return "login";
}
User user = userDao.by_name(loginCommand.getUserName());
if (user == null
|| !user.getName().equals(loginCommand.getUserName())
|| !user.getPassword().equals(loginCommand.getPassword())) { //you should really refactor this and move it outside of your controller. Just keep routing code in your controller, not logic
result.reject("login.failure");
return "login";
}
return "main"; //you should return just "main" or redirect:/main depending on what you're trying to do - you want the JSP to be processed. Leaving off the extension allows you to change frameworks without changing the server-side code and allows the page to be compiled. You could switch to Thymeleaf, for example, and not touch any of this code.
}
}
Add an action to your form:
<form:errors cssClass="error" element="p" />
<table border="0">
<tr>
<td align="right">Username:</td>
<td><form:input path="userName" /> <form:errors path="userName" cssClass="error" /></td>
</tr>
<tr>
<td align="right">Password:</td>
<td><form:password path="password" /> <form:errors path="password" cssClass="error" /></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" id="submit" name="submit" value="Log In"></td>
</tr>
</table>
For the next developer reading your code, I'd rename LoginCommand to something closer to what it actually is - like UserDetailsAdapter or something along those lines. I am assuming that LoginCommand will implement UserDetails from Spring Security if you're using that.
You may also want to consider updating your UserDao to have the method called findOneByUsername instead of by_name. The naming convention can help you later when you use Spring Repositories.
Lastly, look at Project Lombok for your beans. It'll save you lots of headaches.

spring Form binding using path not attribute not working

I have a form ,when I am using spring form tags with the path attribute,I get the following error
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'selectedPerson' available as request attribute
However when I use the regular HTML input with the name attribute I don't see any issues.
What am I doing wrong.
Here is the controller code
#RequestMapping(value="/savePersonChanges.htm",method=RequestMethod.POST)
public ModelAndView savePersonChanges(HttpSession session,#Valid #ModelAttribute(value="selectedPerson")PersonBean editedPersonBean,BindingResult bindingResult){
ModelAndView mav=new ModelAndView();
mav.setViewName(LANDING_PAGE;
mav.addObject(TAB_SELECTOR,"EditPerson");
if(session!=null){
Rpt_date=(java.util.Date)session.getAttribute("editDate");
}
if(bindingResult.hasErrors()){
mav.addObject("errorDescription",errorDescription );
}
else{
/* Call service that updates database with table changes */
try{
PersonService.updatePerson(Rpt_date, editedPersonBean
}
catch(Exception e){
log.logError("Exception while updating Person", e.toString());
}
}
return mav;
}
The form is as follows:
<form:form modelAttribute="selectedPerson" id="editPersonForm">
<table id="selectPerson">
<tbody>
<tr>
<td>
<select id="personId" name="personId" onchange="getPersonDetails(this)">
<c:choose>
<c:when test="${empty selectedPerson}">
<option value="0" selected ="selected">Select A Person</option>
<c:forEach var="personIdItem" items="${editPersonProperties.personproperties}">
<option value="${personIdItem.personId}"><spring:escapeBody>${personIdItem.personName}</spring:escapeBody></option>
</c:forEach>
</c:when>
<c:otherwise>
<c:forEach var="personIdItem" items="${editPersonProperties.personproperties}">
<c:if test="${personIdItem.personId eq selectedPerson.personId}">
<option value="${personIdItem.personId}" selected ="selected">${personIdItem.personName}</option>
</c:if>
<c:if test="${personIdItem.personId ne selectedPerson}">
<option value="${personIdItem.personId}"><spring:escapeBody>${personIdItem.personName}</spring:escapeBody></option>
</c:if>
</c:forEach>
</c:otherwise>
</c:choose>
</select>
</td>
</tr>
</tbody>
</table>
<!-- Person Details -->
<table id="editPersonTable">
<tr>
<td>First Name</td>
<td> <form:input type ="text" path="fname" value="${selectedPerson.fname}"></form:input></td>
<td>Last Name</td>
<td> <form:input type ="text" path="lname" value="${selectedPerson.lname}"/></td>
</tr>
</table>
<div class="editcancelstyle">
<input id="savebtn" type="button" onclick="savePerson()" value="Save" />
<input id="cancelbtn" type="button" onclick="cancelPersonEdits ()"value="Cancel" />
</div>
</form:form>
I understand that the path attribute will bind the field to the form. However, I keep getting the bind error. If I replace using plain HTML, the controller sees the edited values for the fname and lname for the SelectedPerson bean.
Here is your problem, when you do :
<form:... modelAttribute="selectedPerson" ...>, the selectedPerson is the key of model object mapped from the holder of both Model & View class ( ex : ModelAndView), suppose you bind a model in your controller with new ModelAndView ("yourForm", "selectedPerson", new Person()),
#RequestMapping(value = "/form")
public ModelAndView userInput() {
ModelAndView mv = new ModelAndView("personForm", "selectedPerson", new Person());
return mv;
}
now the Person is mapped with selectedPerson so when this form returned as the response from controller, your form has already been bound to the Person model, so that you use path to refer to this Person's attributes (ex. path="name" , means it refers to Person's name attribute)
In your form, on modelAttribute="selectedPerson", the selectedPerson is not binded to any models, since "selectedPerson" is never assigned to any object because you didn't do any binding first before processing ( submitting ) the form.
this is why you got
> java.lang.IllegalStateException: Neither BindingResult nor plain
> target object for bean name 'selectedPerson' available as request
> attribute.
Note that to get this binding works, add also the following on the top of your form
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
you can then populate the fields of the form (assuming you put action="result.html"):
#RequestMapping(value = "/result")
public ModelAndView processUser( #ModelAttribute("selectedPerson") Person person, BindingResult result) {
if (result.hasErrors()) {
return new ModelAndView("errorPage","message","Something goes wrong");
}
/*System.out.println(person.getName());*/
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("personResult");
modelAndView.addObject("person", person);
return modelAndView;
}

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

Getting java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'loginForm' available as request attribute. My login.jsp is as below.
<form:form method="POST" action="/loginPage" commandName = "loginForm">
<tr>
<td><form:label path="name">Username</form:label></td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td><form:label path="age">Password</form:label></td>
<td><form:input path="age" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit"/>
</td>
</tr>
and my controller is
#RequestMapping(value="/loginPage",method = RequestMethod.POST)
public String processForm(#ModelAttribute("loginForm") LoginForm loginForm, BindingResult result,
Map model)
can anyone suggest how can i resolve this exception.
You need to add "loginForm" key to ModelMap before you start using it..
Example:
//This code needs to be invoked first
#RequestMapping(value="/onPageLoadOfLogin",method = RequestMethod.GET)
public String onLoadOfLoginPage(ModelMap m){
m.put("loginForm",new LoginForm());
}
model.put("loginForm",new LoginForm());
This means that, your command name should be exactly the same as the modelAttribute name... so if your commandName in your jsp file is "loginForm" then you model should add the attribute with the name "loginForm".
Please add model map attribute before rendering to login page.
<form:form method="POST" action="/loginPage" modelAttribute = "loginForm">
try adding modelAttribute in
also u need to first bind the form with the controller. To do this you can first perform a GET to perform the binding.
#RequestMapping(value="/loginPage",method = RequestMethod.GET)
public String processForm(#ModelAttribute("loginForm") LoginForm loginForm, BindingResult result,
Map model)
after this do POST. And submit button will do the binding of its own in POST method calling. Your form will be like
<form:form modelAttribute = "loginForm">

Spring 3.0 : How redirect to same page

In Spring MVC, I have a search form. If user submit search form, result should show in same page.
It is redirecting to same page But I'm not getting attributes in JSP from controller.
qSearch.jsp
<form:form name="quickSearchForm" id="searchFormId" method="POST" action="./searchQuick.html" modelAttribute="searchForm" onsubmit="return validateForm()">
<table>
<tr>
<th>Change/Defect ID</th><td><form:input type="text" name="identifier" path="identifier"/></td>
</tr>
</table>
<div class="icons">
<span><button style="left:0px" type="reset" name="clear" style="border-radius: 25px;">CLEAR</button></span>
<span><button style="right:0px" type="submit" name="submit" style="border-radius: 25px;" >SEARCH</button></span>
</div>
</form:form>
<hr>
<div>
<c:if test="${empty SEARCH_RESULTS_KEY}">
<table style="border-collapse: collapse;" border="1" class="showResults">
<tr>
<td colspan="7">No Results found</td>
</tr>
</table>
</c:if>
<c:if test="${! empty SEARCH_RESULTS_KEY}">
<table style="border-collapse: collapse;" border="1" class="showResults">
<tr>
<td colspan="7">Result found</td>
</tr>
</table>
</c:if>
Controller
#RequestMapping(value="/qSearch", method = RequestMethod.GET)
public String getQuickSearchmodel(Model model) {
System.out.println("Welcome to search tool\n");
ArchivalIssue archivalIssue=new ArchivalIssue();
model.addAttribute("searchForm", archivalIssue);
return "quickSearchPage";
}
#RequestMapping(value = "/searchQuick", method = RequestMethod.POST)
public ModelAndView getAllArchivalIssues(HttpServletRequest request){
String identifier = request.getParameter("identifier");
List<ArchivalIssue> archivalIssue = archivalIssueService.getAllArchivalIssue(identifier);
ModelAndView mav = new ModelAndView("redirect:/qSearch"); //Add model to display results
mav.addObject("SEARCH_RESULTS_KEY", archivalIssue); //Add result object to model
return mav;
}
please someone help me, how to get result in JSP. I'm always getting no result found.
I think you should not redirect in this case. Because redirect will create new GET request to server. The quickSearchPage and getAllArchivalIssues should return same view
#RequestMapping(value = "/searchQuick", method = RequestMethod.POST)
public ModelAndView getAllArchivalIssues(HttpServletRequest request){
String identifier = request.getParameter("identifier");
List<ArchivalIssue> archivalIssue = archivalIssueService.getAllArchivalIssue(identifier);
//return quickSearchPage, so that the client can render the list archivalIssue
ModelAndView mav = new ModelAndView("quickSearchPage");
mav.addObject("SEARCH_RESULTS_KEY", archivalIssue); //Add result object to model
return mav;
}
When the return value contains redirect: prefix, The rest of the view name will be treated as the redirect URL. And the browser will send a new request to this redirect URL. So the handler method mapped to this URL will be executed.
just return the same page as response with model attributes.
Are you using JSTL is there any changes required
${empty param.SEARCH_RESULTS_KEY}

Spring MVC update without redundant code?

I'm working on a Spring MVC controller and views to implement CRUD operations for a simple object named Partner. The update operation troubles me. It seems like I need to write several lines of code manually that I expected Spring MVC would take care of automatically. Is there a best practice that I'm missing here?
Here's my view:
<%# include file="include.jsp"%>
<form:form commandName="partner">
<input type="hidden" name="_method" value="PUT" />
<table>
<tr>
<td>Id:</td>
<td><form:input path="id" disabled="true" /></td>
</tr>
<tr>
<td>Name:</td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td>Logo:</td>
<td><form:input path="logo" /></td>
</tr>
<tr>
<td>On-screen text:</td>
<td><form:textarea path="onScreenText" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Save Changes" /></td>
</tr>
</table>
</form:form>
And here's my controller method for the update operation:
#RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(#ModelAttribute Partner partner, #PathVariable int partnerId) {
EntityManager entityManager = DatabaseHelper.getEntityManager();
try {
Partner partnerToUpdate = entityManager.find(Partner.class, partnerId);
entityManager.getTransaction().begin();
partnerToUpdate.setId(partnerId);
partnerToUpdate.setName(partner.getName());
partnerToUpdate.setLogo(partner.getLogo());
partnerToUpdate.setOnScreenText(partner.getOnScreenText());
entityManager.persist(partnerToUpdate);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
return new ModelAndView("redirect:/partner");
}
The lines of code that trouble me are:
Partner partnerToUpdate = entityManager.find(Partner.class, partnerId);
partnerToUpdate.setId(partnerId);
partnerToUpdate.setName(partner.getName());
partnerToUpdate.setLogo(partner.getLogo());
partnerToUpdate.setOnScreenText(partner.getOnScreenText());
Do I really need to look up the existing Partner in the database and explicitly update each field of that object? I already have a Partner object with all the right values. Is there no way to store that object directly to the database?
I've already looked at Spring MVC CRUD controller best pactice, but that didn't quite answer my question.
As one possible suggestion, you could lookup the existing Partner object as part of model creation so that this model instance backs the form and Spring binds the fields directly to it. One way to achieve this would be to create an explicit method in the controller responsible for creating the model.
For example:
#ModelAttribute("partner")
public Partner createModel(#PathVariable int partnerId) {
Partner partner = entityManager.find(Partner.class, partnerId);
return partner;
}
And then you could remove the copying from the updatePartner method - because Spring will already have bound the form fields directly to the loaded Partner object.
#RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(#ModelAttribute("partner") Partner partner) {
EntityManager entityManager = DatabaseHelper.getEntityManager();
try {
entityManager.getTransaction().begin();
entityManager.persist(partner);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
return new ModelAndView("redirect:/partner");
}
One caveat - because the createModel method would get called for every request to the controller (not just updatePartner), the partnerId path variable would need to be present in all requests.
There's a post here which goes over a solution to that issue.
You can use merge to update the desired values, something like:
#RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(#ModelAttribute Partner partner, #PathVariable int partnerId) {
EntityManager entityManager = DatabaseHelper.getEntityManager();
try {
entityManager.getTransaction().begin();
partner.setId(partnerId);
entityManager.merge(partner);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
return new ModelAndView("redirect:/partner");
}
Also, I recommend You to use the DAO Pattern and Spring Transaction Support with #Transactional and #Repository

Resources