Is it possible to manually set the command object in the @RequestMapping method prior to Spring binding?

I have a JSP that has a Spring form. The form command object is added to the controller before the JSP is displayed. Spring binds the form in the JSP to this command object and handles it correctly when a new instance is submitted.

However, I would like to store the command object via DWR (which also works correctly), and THEN pass the form to the controller. The moment the form is submitted to the controller, the command object is no longer a new object, but remains a persistent object that needs to be updated. Here, I want the form elements to automatically link to the command object and update via the binding, but they are not linked.

SIMPLE Example: I'll add a new one Task

to ModelMap

so that the Spring form will bind to this command object. However, instead of submitting a new one Task

, I'll save a new Task

one via DWR, which will return the ID and then continue editing the issue before submitting the form to the controller.

Controller class

@Controller
public class ProjectController {

    /**
     * This adds the "task" command object to the session attributes and loads
     * the initial form.
     */
    @RequestMapping(value="/project", method=RequestMethod.GET)
    public String setupForm(@RequestParam(value="id", required=true) String id,
                            HttpServletRequest request, ModelMap modelMap) {

        modelMap.addAttribute("project", projectRepo.get(id));
        modelMap.addAttribute("task", new Task());

        return "/project/task";
    }

    /**
     * This processes the form submit, and should update the Task.
     */
    @RequestMapping(value="/project/task/update", method=RequestMethod.POST)
    public String updateTask(@ModelAttribute(value="task") Task task,
                             @RequestParam(value="taskId") String taskId,
                             HttpServletRequest request, ModelMap modelMap) {

        // BEFORE binding the parameters to the command object (task), 
        // I want to assign the command object as the one already persisted.
        task = taskRepo.get(taskId);

        // NOW, I want the request parameters to be bound to the task command object.
        // HOW ?????????

        // Persist the changes.
        taskRepo.merge(task);

        // BACK to the setupForm method/form view
        return "/project?id=" + task.getProject().getId();
    }
}

      

Spring Form

<form:form commandName="task" method="post" action="/project/task/update" id="taskForm">
    <form:hidden path="id" id="task.id"/>
    <form:input path="name" id="task.name"/>
    <!-- DWR will save the task (save and continue), then will return the id. -->
    <!-- After saved, the user can still change the name, 
         then submit the form for processing by the controller -->
</form:form>

      

Can a bound Spring command bean be set to a persistent bean before any post-dispatch binding happens?

+1


a source to share


2 answers


There is actually a better way to do this using annotations.

Create a ModelAttribute method that returns the command object you want from the repository.

@ModelAttribute("task")
public Task task(@RequestParam(value = "id", required = true) String id) {
    return taskRepo.get(taskId);
}

      



Then just add ModelAttribute to the form's submit method.

@RequestMapping(value="/project/task/update", method=RequestMethod.POST)
public String updateTask(@ModelAttribute(value="task") Task task,
                         HttpServletRequest request, ModelMap modelMap) {

    taskRepo.merge(task);
    ...
}

      

+3


a source


It looks like when used @ModelAttribute

to access the command object, the binding happens before you access the command object. To set this command object to whatever you want, before you bind the request parameters to the form, just pass in the attribute id and retrieve it from the database, then bind the WebRequest parameters.

In the POST method

@RequestMapping(value="/project/task/update", method=RequestMethod.POST)
public String updateTask(@ModelAttribute(value="task") Task task,
                         @RequestParam(value="taskId") String taskId,
                         HttpServletRequest request, ModelMap modelMap) {

    // BEFORE binding the parameters to the command object (task), 
    // I want to assign the command object as the one already persisted.
    task = taskRepo.get(taskId);

    // NOW, I want the request parameters to be bound to the task command object.
    WebRequestDataBinder binder = new WebRequestDataBinder(task);
    ServletWebRequest webRequest = new ServletWebRequest(request);
    binder.bind(webRequest);

    // Persist the changes.
    taskRepo.merge(task);

    // BACK to the setupForm method/form view
    return "/project?id=" + task.getProject().getId();
}

      



Spring Documentation 2.5.xWebRequestDataBinder

is where you can find Juergen Hoeller's Example for "manual data binding" for this type of application.

MyBean myBean = new MyBean();
// apply binder to custom target object
WebRequestDataBinder binder = new WebRequestDataBinder(myBean);
// register custom editors, if desired
binder.registerCustomEditor(...);
// trigger actual binding of request parameters
binder.bind(request);
// optionally evaluate binding errors
Errors errors = binder.getErrors();
...

      

+1


a source







All Articles