I'm facing a problem I don't really know how to solve. I am developing a Bug Tracker (learning purposes only). I have a page to create a new issue and one page to edit an issue. Both, for now, have their own controllers.
EditIssueController.java
@Controller
@RequestMapping(value = "/issues/{issueId}")
@SessionAttributes("issuePackage")
public class EditIssueController {
@Autowired
private IssueService issueService;
[...]
@ModelAttribute("issuePackage")
public IssueTagEnvironment populateIssue (@PathVariable("issueId") Integer issueId) {
IssueTagEnvironment issueTagEnv = new IssueTagEnvironment();
issueTagEnv.setIssue(issueService.getIssueById(issueId));
return issueTagEnv;
}
@InitBinder
public void initBinder (WebDataBinder binder) {
[...]
}
@RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView editIssue (@PathVariable("issueId") Integer issueId,
@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage) {
ModelAndView mav = new ModelAndView("/issues/EditIssue");
[...]
IssueTagEnvironment issueTagEnv = new IssueTagEnvironment();
issueTagEnv.setIssue(issueService.getIssueById(issueId));
[...]
mav.addObject("issuePackage", issueTagEnv);
return mav;
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public String updateIssue (@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage,
BindingResult result) {
if (result.hasErrors() == true) {
return "redirect:/issues/{issueId}/edit";
}
issueService.updateIssue(issuePackage.getIssue());
return "redirect:/issues/{issueId}";
}
}
CreateIssueController.java
@Controller
@SessionAttributes("issuePackage")
public class CreateIssueController {
@Autowired
private IssueService issueService;
[...]
@ModelAttribute("issuePackage")
public IssueTagEnvironment populateNewIssue () {
return new IssueTagEnvironment();
}
@InitBinder
public void initBinder (WebDataBinder binder) {
[...]
}
@RequestMapping(value = "/issues/CreateIssue", method = RequestMethod.GET)
public ModelAndView createIssueGet (@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage) {
ModelAndView mav = new ModelAndView("/issues/CreateIssue");
[...]
issuePackage.getIssue().setReporter(SecurityUtils.getCurrentUser());
return mav;
}
@RequestMapping(value = "/issues/CreateIssue", method = RequestMethod.POST)
public String createIssuePost (@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage,
BindingResult result,
SessionStatus status) {
if (result.hasErrors() == true) {
return "redirect:/issues/CreateIssue";
}
[...]
issueService.createIssue(issuePackage.getIssue());
status.setComplete();
return "redirect:/issues/" + issuePackage.getIssue().getId();
}
}
So far everything seems correct (and in indeed works). But here are the dragons:
I understand what the problem is: The controller
is not completing the session/status by executing status.setComplete()
.
My question here is, how to solve this problem?
Thanks in advance to the community!
For your current example, it is easy to fix , just change createIssueGet
method to :
public ModelAndView createIssueGet () {
ModelAndView mav = new ModelAndView("/issues/CreateIssue");
IssueTagEnvironment issuePackage = new IssueTagEnvironment();
ModelAndView mav = new ModelAndView("/issues/CreateIssue");
mav.addAttribute("issuePackage", issuePackage);
[...]
[...]
}
That way you are sure that you always use a fresh IssueTagEnvironment
object in that controller. And Spring will put it in session as you put it in model.
But the problem still remains : if you do not properly call status.setComplete()
, you leave in session an object that should not be there, and like you said dragons may be there
I stopped using @SessionAttributes
for that reason, and only use a hidden field (for the id) and a Converter
from the id to a full object using the service layer, hoping it should be in cache and does not hit the database. Not really nice, but not really worse than that.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.