In my project I have two pages first one is for entering the data and the second one is for showing the data to the user. When I refresh the result page data is dublicated. I tried to fix this but I am not familiar with PRG pattern. I want to prevent the duplication if the user refreshes the result page.
#RequestMapping(value = { "/display-form", "mainPage.html" }, method = RequestMethod.GET)
public ModelAndView displayForm() {
ModelAndView mv = new ModelAndView("mainPage");
mv.addObject("formData", new SampleModel());
return mv;
}
#RequestMapping(value = "/send-form-data", method = RequestMethod.POST)
public ModelAndView processForm(#Valid #ModelAttribute("formData") SampleModel formData, BindingResult res) {
ModelAndView mv = new ModelAndView();
fmv.validate(formData, res);
mv.addObject("formData", formData);
service.delete(1);
if(res.hasErrors())
{
mv.setViewName("mainPage");
}
else
{
mv.setViewName("result");
service.create(formData);
mv.addObject("list", service.findAll());
}
return mv;
}
Try to create the ModelAndView instance with redirection, so that when actions completes, you get a 3xx redirection (to the initial form, for example):
ModelAndView mv = new ModelAndView("redirect:/display-form");
// .. as before ..
Related
My application has a method to update a conference. After doing so I have a modelandview with a redirect to the main conference list. This all works fine although the message which I add as an object to the modelandview does not display.
My method in my controller:
#PostMapping("/updateConference")
public ModelAndView updateConference(
#ModelAttribute("conference") #Valid ConferenceDto conferenceDto, BindingResult result) {
if(result.hasErrors()){
return new ModelAndView("updateConference","conferenceDto", conferenceDto);
}
try {
conferenceService.updateConference(conferenceDto);
} catch (ConferenceAlreadyExistException uaeEx) {
ModelAndView mav = new ModelAndView("updateConference","conferenceDto", conferenceDto);
mav.addObject("message", uaeEx.getMessage());
return mav;
}
ModelAndView mav = new ModelAndView("redirect:/teacher/configure"); // Problem is here
mav.addObject("message", "Successfully modified conference.");
return mav;
}
In my html I have the line:
<div th:if="${message != null}" th:align="center" class="alert alert-info" th:utext="${message}">message</div>
After updating the conference it goes back to configure.html although the message does not show. In the url I can see http://localhost:8080/teacher/configure?message=Successfully+modified+conference
I have looked at this thread although it did not help.
I tried to experiment by setting ModelAndView mav = new ModelAndView("configure") and the message displays but my conference list is empty and the url is http://localhost:8080/teacher/updateconference
Any tips is highly appreciated!
EDIT
I have tried to use RedirectAttributes as crizzis pointed out & this page and have this now:
#PostMapping("/updateConference")
public String updateConference(
#ModelAttribute("conference") #Valid ConferenceDto conferenceDto, BindingResult result, RedirectAttributes attributes) {
if(result.hasErrors()){
attributes.addFlashAttribute("org.springframework.validation.BindingResult.conferenceDto", result);
attributes.addFlashAttribute("conferenceDto", conferenceDto);
return "redirect:/teacher/updateConference";
}
try {
conferenceService.updateConference(conferenceDto);
} catch (ConferenceAlreadyExistException uaeEx) {
attributes.addFlashAttribute("conferenceDto", conferenceDto);
attributes.addFlashAttribute("message", uaeEx.getMessage());
return "redirect:/teacher/updateConference";
}
attributes.addFlashAttribute("message", "Successfully modified conference.");
return "redirect:/teacher/configure";
}
My get method:
#GetMapping(path = "/updateConference/{id}")
public String showUpdateConferenceForm(#PathVariable(name = "id") Long id, Model model){
Optional<Conference> conference = conferenceService.findById(id);
if (!model.containsAttribute("ConferenceDto")) {
model.addAttribute("conference", new ConferenceDto());
}
return "updateConference";
}
This works as intended and my message is shown on my configure.html . However, when I have an error in BindingResults the application goes to an error page and I get this in the console:
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
Use RedirectAttributes which has addFlashAttribute method. You can set the success or failure message like you did and access that message through the key in the redirected page as you need.
when the error occurs you are redirecting to the same method instead of this you can just render the template in case there is error. I do this way.
I have a JSP page as task.jsp. So I want to display this page only once in a year i.e. in the month of March every year.
I dont have any idea how to schedule it. Please help me. Following is my sample controller code:
#RequestMapping(
value = "task.htm",
method = RequestMethod.GET
)
public ModelAndView taskPost(#ModelAttribute("task") Task task, HttpServletRequest request) {
ModelAndView model = new ModelAndView("task");
//do something
return model;
}
You can throw a ResponseStatusException:
#RequestMapping(value = "task.htm", method = RequestMethod.GET)
public ModelAndView taskPost(#ModelAttribute("task") Task task,HttpServletRequest request {
if(LocalDate.now().getMonth() != Month.MARCH) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Unable to find resource");
}
ModelAndView model = new ModelAndView("task");
//do something
return model;
}
See more:
ResponseStatusException (javadoc)
https://www.baeldung.com/spring-response-status-exception
I have a thymeleaf template that reads a URL parameter:
http://xxxx:8080/department?action=edit
In this way:
<input type="text" th:placeholder="#{department.id}" class="form-control" th:field="*{id}" th:readonly="${param.action[0] == 'edit'}">
Basically this let's you edit if action=edit is in the URL. This works fine, but when I handle the POST method, the modelAndView redirect to /departent alone without the parameters when there are errors:
#RequestMapping(value = "/department", method = RequestMethod.POST)
public ModelAndView department(HttpServletRequest request, #Valid Department department,
BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
if (bindingResult.hasErrors()) {
// data with errores, try again
modelAndView.setViewName("department");
} else {
// all ok. Save and continue
departmentService.updateDepartment(department);
modelAndView.setViewName("redirect:departments");
}
return modelAndView;
}
When the page reload, I have the following error message:
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "param.action[0] == 'edit'" (template: "department" - line 24, col 103)
The reason is that the new URL is:
http://xxxx:8080/department
The think that I need to use a URL parameters is because the link is generated by A HREF link.
I've tried:
modelAndView.getModelMap().put("action", "edit");
But this doesn't work.
I would simplify this by making param.action[0] == 'edit' a variable and simply adding that to the model. Like:
model.addAttribute("isReadOnly", someVariableHereThatMakesItReadOnly);
and
th:readonly="${isReadOnly}" in your form.
This makes your view less complex and allows you to unit test the value of isReadOnly on the server-side. Then you can do:
#PostMapping("/department")
public String postDepartment(#Valid Department department,
BindingResult result) {
if (result.hasErrors()) {
//add error information here
model.addAttribute("isReadOnly", true);
return "department"
}
departmentService.updateDepartment(department);
return "redirect:/departments";
}
There are likely multiple ways you can do this. This is just one way.
You could also probably do return "redirect:/department?action=edit" in your post method, but then you'd need to get creative about how to display any error messages.
If you don't want to change too much your code, you add to html:
<input type="hidden" name="requestedAction" th:value="${param.action[0]}">
And change the RequestMapping method to:
#RequestMapping(value = "/department", method = RequestMethod.POST)
public ModelAndView department(HttpServletRequest request, #Valid Department department, BindingResult bindingResult, #RequestParam String requestedAction) {
ModelAndView modelAndView = new ModelAndView();
if (bindingResult.hasErrors()) {
// data with errores, try again
modelAndView.setViewName("department?action=" + requestedAction);
} else {
// all ok. Save and continue
departmentService.updateDepartment(department);
modelAndView.setViewName("redirect:departments");
}
return modelAndView;
}
Using the redirectAttributes.addFlashAttribute("object",objectvalue);
Like this way it is successfully redirecting the object value to the next controller, but when we returned the view in the next controller it display the result in html page in browser. Then the problem starts when we refresh or reload the page then values disappears.
My code is
#RequestMapping(value = "/addRoom", method = RequestMethod.POST)
public String saveRoom(Room room,
ModelMap model, RedirectAttributes ra) {
amenitiesService.saveRoom(room);
Floor floor = amenitiesService.getFloorInfo(room.getFloorId());
String floorName = floor.getFloorName();
ra.addFlashAttribute(room);
ra.addFlashAttribute("floorName", floorName);
ra.addFlashAttribute("message","Room information is saved successfully.");
return "redirect:/redirectedUrl";
}
#RequestMapping(value = "/redirectedUrl")
public String redirecturl(Room room, ModelMap model) {
return ADMIN_VIEW + SAVE_ROOM;
}
please any one suggest me how to redirect the object values to next controller with permanent not temporary visible like flash attributes
use this it may be work
#RequestMapping(value = "/redirectedUrl")
public String redirecturl(Room room, ModelMap model, RedirectAttributes re) {
String name=(String)re.getFlashAttributes("floorName");
return ADMIN_VIEW + SAVE_ROOM;
}
I have a page which i enter parameters to query a list of records.
When the query button is clicked i get the list when an item form the list is clicked it takes me back to the first page with the record in display.
When i hit another button 'new' to clear the page and return an empty page a parameter is there in the url and it sets the value of an item on the page.The item that is there in the url is the crimeRecNo.
How can i get rid of this i want to return an empty page?
Scenario
I am on a page with the following url :http://adomain/crimeTrack/crime_registration.htm
I click Query which does a POST to another url which displays the list of records :http://adomain/crimeTrack/crimeList.htm
On the above page in 2 above i then select one record which does a POST and takes me to the followig url: http://adomain/crimeTrack/getCrime/6.htm - where 6 is the crimeRecNo.
I am now on the above url and i hit the 'NEW' button to get a blank form with the url in 1 above. When i hit new a POST is done to the controller method in code sample 4 under
This method does a redirect to the url which is mapped to a GET method however the final url looks like this : http://adomain/crimeTrack/%20crime_registration.htm?crimeRecNo=6
The value 6 remains in the crimeRecNo field and the entire form is not cleared.
Under is the controller methods:
1. Initial page request
#RequestMapping(value = "crime_registration.htm", method = RequestMethod.GET)
public ModelAndView loadPage(HttpServletRequest request,HttpServletResponse response, #ModelAttribute Crime crime,BindingResult result, ModelMap m, Model model, SessionStatus status,HttpSession session) throws Exception {
try {
logger.debug("In Crime Registration Controller");
myCriminalList.put("dbcriminalList",
this.citizenManager.getListOfCriminals());
...................
session.setAttribute("page", 0);
return new ModelAndView("crime_registration");
} catch (Exception e) {
logger.debug("Exception In CrimeRegistration Controller : "
+ e.getMessage());
return new ModelAndView("crime_registration");
}
}
2. Query For List of Items
#RequestMapping(value = "crimeList.htm", method = RequestMethod.POST)
public ModelAndView handelCrimeList(#ModelAttribute Crime crime,
BindingResult result, ModelMap m, Model model) throws Exception {
if (crimeManager.getCrimesList(crime).size() <= 0) {
model.addAttribute("dbcriminals", myCriminalList);
........
model.addAttribute("crimeTypeList", crimeTypeManager.getCrimeTypeList(crime.getOffenceCatId()));
model.addAttribute("icon", "ui-icon ui-icon-circle-close");
model.addAttribute("results","Error: Query Caused No Records To Be Retrieved!");
return new ModelAndView("crime_registration");
}
model.addAttribute("crimes", crimeManager.getCrimesList(crime));
return new ModelAndView("crimeList");
}
3. Request For One Item/When item is selected from list
#RequestMapping(value = "getCrime/{crimeRecNo}.htm", method = RequestMethod.POST)
public ModelAndView getCrime(#PathVariable Integer crimeRecNo,
#ModelAttribute Crime crime, BindingResult result, ModelMap m,
Model model, HttpServletRequest request,
HttpServletResponse response, HttpSession session) throws Exception {
try {
model.addAttribute("crime", crimeManager.getCrimeRecord(crimeRecNo));
session.setAttribute("crimeRecNo", crimeRecNo);
//model.addAttribute("victimList", citizenManager.getVictimListByCrimeRecNo(crimeRecNo));
} catch (Exception e) {
logger.error("Exception in CitizenRegistrationController - ModelAndView getCitizen "
+ e);
}
int crimeCatId = crimeManager.getCrimeRecord(crimeRecNo).getOffenceCatId();
logger.info("crime category number is : "+crimeCatId);
myCrimeTypeList.put("crimeTypeList", this.crimeTypeManager.getCrimeTypeList(crimeCatId));
model.addAttribute("dbcriminals", myCriminalList);
.....
session.setAttribute("crimeRecNo", crimeRecNo);
return new ModelAndView("crime_registration");
}
4. Request For NEW Form
#RequestMapping(value = "crime_registration_new.htm", method = RequestMethod.POST)
public String loadNew(HttpServletRequest request,Model model,
HttpServletResponse response,SessionStatus status,HttpSession session) throws Exception {
status.setComplete();
return "redirect: crime_registration.htm";
//return new ModelAndView(new RedirectView("crime_registration.htm"));
}
Adding this to 4 did the trick
#RequestMapping(value = "crime_registration_new.htm", method = RequestMethod.POST)
public String loadNew(HttpServletRequest request,Model model,
HttpServletResponse response,SessionStatus status,HttpSession session) throws Exception {
status.setComplete();
model.addAttribute("crime", new Crime());
return "redirect: crime_registration.htm";
//return new ModelAndView(new RedirectView("crime_registration.htm"));
}