Piotr Sagalara
Piotr Sagalara

Reputation: 2485

Controller doesn't work properly

I have a problem with controller in my spring mvc application.

I am getting all the entities from database and put them in the table in my jsp page.

I am adding an entity, the function works well, it adds an entity and refresh the page. But there is a problem when I try to refresh page...the same entity is added again, in general after adding an entity every refresh execute the post method again and finally i have many same entities.

This is the post method to add new entities:

@RequestMapping(value = "/adminpanel", method = RequestMethod.POST)
public ModelAndView addNewSoftware(@ModelAttribute VersionInformation versionInformation) 
{

    ModelAndView model = new ModelAndView("panel");

    persistanceDAO.insertVersionInformation(versionInformation);
    systemVersionsList.clear();
    systemVersionsList.addAll(persistanceDAO.getSystemVersions());
    model.addObject("systemVersionsList",systemVersionsList);
    model.addObject("versionInformation", new VersionInformation());

    return model;
}

This is my GET method:

@RequestMapping(value = "/adminpanel/add", method = RequestMethod.POST)
public ModelAndView addNewSoftware(@ModelAttribute VersionInformation versionInformation) 
{

    ModelAndView model = new ModelAndView("panel");

    persistanceDAO.insertVersionInformation(versionInformation);
    systemVersionsList.clear();
    systemVersionsList.addAll(persistanceDAO.getSystemVersions());
    model.addObject("systemVersionsList",systemVersionsList);
    model.addObject("versionInformation", new VersionInformation());

    return model;
}

Another problem is that when I am deleting an entity, the entity is deleted, but the site doesn't refresh. This is my post method responsible for deleting entity:

@RequestMapping(value = "/adminpanel/delete", method = RequestMethod.POST)
public ModelAndView deleteSoft(@ModelAttribute(value="currentId") int currentId, @ModelAttribute VersionInformation versionInformation) 
{

    ModelAndView model = new ModelAndView("panel");

    persistanceDAO.deleteSystemVersion(currentId);
    systemVersionsList.clear();
    systemVersionsList.addAll(persistanceDAO.getSystemVersions());
    model.addObject("systemVersionsList",systemVersionsList);
    model.addObject("versionInformation", new VersionInformation());


    return model;
}

Upvotes: 2

Views: 982

Answers (4)

Bnrdo
Bnrdo

Reputation: 5474

You probably are looking at Post/Redirect/Get pattern. If you are using Spring 3.1 and above, implementing this would be easy using flash attribute.

Modification of your code with Post/Redirect/Get Pattern applied

@RequestMapping(value = "/adminpanel/add", method = RequestMethod.POST)
public String addNewSoftware(@ModelAttribute VersionInformation versionInformation, 
                                    final RedirectAttributes redirectAttributes){

    ModelAndView model = new ModelAndView("panel");

    persistanceDAO.insertVersionInformation(versionInformation);
    systemVersionsList.clear();
    systemVersionsList.addAll(persistanceDAO.getSystemVersions());
    redirectAttributes.addFlashAttribute("systemVersionsList",systemVersionsList);
    redirectAttributes.addFlashAttribute("versionInformation", new VersionInformation());

    return "redirect:/adminpanel/show-panel";
}

@RequestMapping(value = "/adminpanel/show-panel", method = RequestMethod.GET)
public ModelAndView showSoftwarePanel(@ModelAttribute("systemVersionsList") List<YouDidNotShowTheTypeOFSystemVersionList> systemVersionsList,
                                    @ModelAttribute("versionInformation") VersionInformation versionInformation){
    ModelAndView model = new ModelAndView("panel");
    model.addObject("systemVersionsList", systemVersionsList);
    model.addObject("versionInformation", versionInformation);

    return model;
}

After doing that, your page is now safe from multiple form submit problem.

Upvotes: 1

Ayub Malik
Ayub Malik

Reputation: 2578

I think the problem is that when you refresh the page you are resending the data. If so you need to use the Redirect-after-POST pattern.

Try this

@RequestMapping(value = "/adminpanel/add", method = RequestMethod.POST)
public ModelAndView addNewSoftware(@ModelAttribute VersionInformation versionInformation) 
{

    ModelAndView model = new ModelAndView("redirect:/admin/panel");

    // move these lines
    persistanceDAO.insertVersionInformation(versionInformation);
    systemVersionsList.clear();
    systemVersionsList.addAll(persistanceDAO.getSystemVersions());
    model.addObject("systemVersionsList",systemVersionsList);
    model.addObject("versionInformation", new VersionInformation());
    // end

    return model;

}

NOTE: You should move the commented lines into a GET method otherwise, your version etc will appear in the URL after redirect

Upvotes: 0

Yugang Zhou
Yugang Zhou

Reputation: 7283

What about using redirect after updating the data.

"Another reason to perform a redirect before displaying the result is to eliminate the possibility of the user submitting the form data multiple times. In this scenario, the browser will first send an initial POST; it will then receive a response to redirect to a different URL; and finally the browser will perform a subsequent GET for the URL named in the redirect response. " quoted from Spring mvc doc

Upvotes: 1

madhead
madhead

Reputation: 33412

GET methods must only be used for idempotent operations. For deletes and inserts you must use POST. And after successful non-idempotent operation you must send a redirect to user, so if he hits refresh no kittens harmed.

Upvotes: 0

Related Questions