Spring MVC pass same object between controller

In Spring MVC how do I pass an object between two controller methods? I have an update form and an updateController. In the controller I have 2 methods, one for fetching the data and displaying it in a view. The second method of the controller is invoked when the user clicks update button with modified changes. What I am observing is that the object which I get in second method of the controller is not the same object which I passed to the view in the first controller method call. Its a new object altogether with all form fields mapped to it. How do I make sure that the same object is passed to the second controller method which was provided to the view by the first controller method?

@RequestMapping(value = "/showEmpDetail.html", method = RequestMethod.GET)
public String showEmpDetails(
        @RequestParam(value = "page", required = false) Integer page,
        HttpServletRequest request, @RequestParam("empId") Long empId,
        ModelMap model) {
    // Get employee using empId from DB
    model.addAttribute("emp",emp);
    return "showEmpDetail";
    }

The above controller method gets the emp values from Db and displays it correctly in the view. Now the user changes some details and clicks submit button. The following controller method is called.

@RequestMapping(value = "/editEmpFormSubmission.html", method = RequestMethod.POST)
public String editEmpFormSubmission(
        @RequestParam(value = "page", required = false) Integer page,
        @ModelAttribute("emp") Employee emp, BindingResult result,
        ModelMap model, HttpServletRequest request) {
     // update changes in DB
    }

In the above controller method when I check the emp object its not the same object which I passed in previous controller call. The fields which are not form backed but had values were changed to null. How can I make sure the same object is passed by view. I do not want to add the object as sessionAttribute since a user might modify many employees in a session.

Answers


You have 3 options

  1. Use @SessionAttributes to store the object in the session in between requests.
  2. Use a @ModelAttribute annotated method to retrieve the object before each request
  3. Write your own code and store it in the session (similair to 1 but more work on your part).
Option 1
  1. Add the @SessionAttributes annotation to your controller class
  2. Add the SessionStatus as a parameter to your update method and the setComplete() method when you are finished with the object

@SessionAttributes("emp")
public class EmployeeController {
@RequestMapping(value = "/editEmpFormSubmission.html", method = RequestMethod.POST)
public String editEmpFormSubmission(
    @RequestParam(value = "page", required = false) Integer page,
    @ModelAttribute("emp") Employee emp, BindingResult result,
    ModelMap model, HttpServletRequest request
    SessionStatus status) {
 // update changes in DB
 status.setComplete();
}    
} 
Option 2
  1. Add the method which retrieves the object from the database and annotate it with @ModelAttribute
  2. Cleanup your showEmpDetails method as it should only return a view name

public class EmployeeController {

    @ModelAttribute("emp")
    public Employee getEmployee(@RequestParam("empdId") Long id) {
        // Get employee using empId from DB
        return  emp;
    }

    @RequestMapping(value = "/showEmpDetail.html", method = RequestMethod.GET)
    public String showEmpDetails() {) {
        return "showEmpDetail";
    }
}
Option 3
  1. In your methods add the HttpSession as an argument
  2. In your showDetails method next to adding it to the model add it to the session
  3. In your editEmpFormSubmission use the one from the session and copy all non-null fields to the object from the session and store that in the database.

I wouldn't go for option, I strongly would suggest option 1 especially including the setComplete() on the SessionStatus object for cleanup. You could also combine 1 and 2 (have a @ModelAttribute annotated method and still use @SessionAttributes.).


How can I make sure the same object is passed by view. I do not want to add the object as sessionAttribute since a user might modify many employees in a session

You could make a field in the object that is filled with a random number at the time of initial render and then store that object in the session. In the view you can map that field with a hidden input and now when user sends a request to edit action you can get that hidden field and fetch the original object from session by the number in the hidden field. That would resolve the multiple edits in different tabs conflict.


Need Your Help

Appium get xpath from element?

ios ruby xpath appium

I have code which retrieves a static text element for me fine but what I want to do is then get the xpath of that element as a string. I'm using ruby. At this point I have an array of elements I have

Always open camera in landscape mode in Android

android android-intent

In my android app, after clicking on button I want camera to open in landscape mode. Even if I rotate my mobile into portrait mode, camera should always be in landscape mode or in portrait mode