Springboot passing ModelAndView from a controller to another - spring-boot

In Springboot 2.7 I have a simple controller that dinamically sets up a page using a static resource:
#RequestMapping(value = "/controller-first", method = RequestMethod.GET)
public ModelAndView controller-first( Locale locale,
HttpServletRequest request,
HttpServletResponse response,
Model model)
{
dinamically manipulate model here...
return new ModelAndView("static_resource_here");
}
With this controller I have a form and submit that calls the second controller. The second controller should keep the ModelAndView from the first controller, modify the ModelAndView and send it to the user. Which is the best solution to implement such controller?

I got it. In the second controller I added a RedirectAttributes, then in the body I write:
//for each attribute changed
attributes.addFlashAttribute("attribute_name", model.getAttribute("name"));
//now redirect to the first controller
return new ModelAndView("redirect:/controller-first");

Related

SpringMVC Controller Method Doesn't Bring in Model

I noticed that when a Form Submit happens, my handler method that captures a #Model object as a parameter does have a valid Model available to me, e.g.
public ModelAndView save(final HttpServletRequest request,
#ModelAttribute(MODEL_NAME) MyModel model,
BindingResult bindingResult)
But when I have a handler method corresponding to a URL redirect from a simple <a href=".."> button/link, e.g.
<a href="myController.do&function=add">
leading to
#RequestMapping(params = "function=add")
public ModelAndView add(final HttpServletRequest request,
#ModelAttribute(MODEL_NAME) MyModel model) throws Exception
in that case, the model object is NULL. The model wasn't carried through the request and made available to me in the handler method.
Is there a way to reexpose the model? I do have the same param in both methods, but in the 2nd one the "model" object is NULL.
If you want to use GET request with you will need to add the model to the URL. Or you can use POST with a form instead.
See: how to pass a java object from jsp to spring controller on clicking a link

Neither BindingResult nor plain target object for bean name AFTER redirect

I have a form like this (in a page called add.jsp):
<form:form action="${pageContext.request.contextPath}/add" method="post" modelAttribute="addForm">
</form:form>
On GET request, i populate modelAttribute:
#RequestMapping(value ="add", method = RequestMethod.GET)
public ModelAndView add(Map<String, Object> model) {
model.put("addForm", new AddUserForm());
return new ModelAndView("add");
}
When i perform the form submitting (a POST request), i have the follow method:
#RequestMapping(value ="add", method = RequestMethod.POST)
public ModelAndView add(Map<String, Object> model, #Valid AddUserForm form, Errors errors) {
if (errors.hasErrors()) {
//model.put("addForm", new AddUserForm());
return new ModelAndView("add");
}
....
}
But i get this error: Neither BindingResult nor plain target object for bean name 'addForm' available as request attribute
My workaround is to add model.put("addForm", new AddUserForm());, the command that i have commented on POST request.... but... where is my error ?
In both case, you are returning the same view (i.e. "add") and this view contains a form with a modelAttribute="addForm" therefore the model MUST contains an object named "addForm".
If you don't wan't to populate your model with a new AddUserForm after a POST with errors, you probably should :
return another view (without the "addForm" model attribute)
or
reuse the same "addForm": model.put("addForm", form);

redirect from get method to post method in spring controller

I have a link retailerId after clicking the link control will go to the below controller:
#Controller
#RequestMapping(value = "/auth/adminsearchowner")
public class AdminSearchOwnerController {
#RequestMapping(value = "/retailerId/{retailerId}",method = RequestMethod.GET)
public ModelAndView viewRetailerInfo(
#PathVariable("retailerId") String retailerId,
#ModelAttribute EditRetailerLifeCycleBean editLicenseBean) {
editLicenseBean.setSelectedIDsString(retailerId);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("editLicenseBean",editLicenseBean);
modelAndView.setViewName("redirect:/auth/adminlicense/viewlicense");
return modelAndView;
}
}
where /auth/adminlicense/viewlicense is in another controller and we have both GET and POST method for this /auth/adminlicense/viewlicense request mapping. I want to call the post method from the earlier controller.
#Controller
#RequestMapping("/auth/adminlicense")
public class AdminViewLicenseController {
#RequestMapping(value = "/viewlicense", method = RequestMethod.GET)
public ModelAndView searchRetailerLicense(
#ModelAttribute("editLicenseBean") EditRetailerLifeCycleBean editLicenseBean,
HttpSession session) {
}
#RequestMapping(value = "/viewlicense", method = RequestMethod.POST)
public ModelAndView getLicenseDetails(
#ModelAttribute EditRetailerLifeCycleBean lifeCycleBean,
HttpSession session) {
}
}
but it is going to GET method. Could you tell me the solution?
There is no solution. A redirect cannot cause a POST to be sent by the browser.
Rethink your design.
Try:
modelAndView.setViewName("forward:/auth/adminlicense/viewlicense");
instead of
modelAndView.setViewName("redirect:/auth/adminlicense/viewlicense");
A design in which you are trying to send some data from one controller(server-side) to another(server-side) via user's browser(client-side) is probably not the best idea, anyway.
Hope it helps!

Spring 3 : Binding same controller method to multiple form action

I have a controller method with RequestMapping.PUT and having a URI
#RequestMapping(value = "/add/email", method = RequestMethod.POST)
public String addNewAccountEmail(#Valid #ModelAttribute EmailClass emailObject, BindingResult bindingResult, Model model) {
return displayForm(model);
}
I have a form like :
<form:form id="add-user-email" action="/add/email" name="manageUserAddEmail" method="post" modelAttribute="accountEmail">
I want to have more form pointing to same action , but need to do different operations inside addNewAccountEmail method. So how can I achieve this in Spring ? Basically any parameter which can make me differentiate functionalities or somehow I can have multiple methods having same RequestMapping URL and Method ?
I can only use RequestMethod.POST as I have similar requirements for other methods as well.
Basically I do not want the URL to change in Browser when invoking actions, that is why I want all form actions to point to same action URL.
You could point all of your forms at the same controller method and then differentiate the form-specific functionality within that method by looking for form-specific request parameters.
Each form would need to add its own request parameter to identify it - such as:
<input type="hidden" name="form1_param" value="1"/>
And then you can vary the behaviour inside the method by inspecting the HttpServletRequest:
#RequestMapping(value = "/add/email", method = RequestMethod.POST, )
public String addNewAccountEmail(#Valid #ModelAttribute EmailClass emailObject, BindingResult bindingResult, Model model, HttpServletRequest request) {
if (request.getParameter("form1_param") != null) { // identifies 1st form
// Do something
} else if (request.getParameter("form2_param") != null) { // indentifies 2nd form
// Do something else
}
...
}
It would be cleaner however to have multiple controller methods mapped to the same path, but specify different params in the RequestMapping - to differentiate the different forms.
#RequestMapping(value = "/add/email", params="form1_param", method = RequestMethod.POST)
public String addNewAccountEmail1(#Valid #ModelAttribute EmailClass emailObject, BindingResult bindingResult, Model model) {
// Do something specific for form1
return displayForm(model);
}
And also:
#RequestMapping(value = "/add/email", params="form2_param", method = RequestMethod.POST)
public String addNewAccountEmail2(#Valid #ModelAttribute EmailClass emailObject, BindingResult bindingResult, Model model) {
// Do something specific for form2
return displayForm(model);
}
Etc.
#RequestMapping accepts arrays as parameters (with an or semantic).
#RequestMapping(
value = "/add/email",
method = { RequestMethod.POST, RequestMethod.PUT } )

Session Handling in Spring MVC 3.0

I am using session.setAttribute to store user object after login. In next controller, I have #SessionAttribute for the same user and #ModelAttribute for same object to be used in the method mapped to a RequestMapping. After login if I click any link in the user home page it give
HttpSessionRequiredException: Session attribute '' required - not found in session
I am not sure what I am doing wrong. I went through many article and question in this site as well but could find any solution. The user object which I am storing in session stores user's account details which are required in all the controller to get different information from DB. I using SessionAttribute is wrong should I use HttpSession instead in all the controller and get the object from session manually or there is a proper way to handle in spring 3.0. Please note that this user object is not backing any form just login, but contains many other details.
As help would be good.
Have a look at my (non-perfect) use of session data:
#Controller
#SessionAttributes("sharedData")
public class RegistrationFormController {
#Autowired
private SharedData sharedData; // bean with scope="session"
#RequestMapping(value = {"/registrationForm"}, method = RequestMethod.GET)
public ModelAndView newForm() {
final ModelAndView modelAndView = new ModelAndView("registrationForm");
modelAndView.addObject("registrationForm", new RegistrationForm());
// I want to render some data from this object in JSP:
modelAndView.addObject("sharedData", sharedData);
return modelAndView;
}
#RequestMapping(value = {"/registrationForm"}, method = RequestMethod.POST)
public String onRegistrationFormSubmitted(HttpServletRequest request,
#ModelAttribute("registrationForm") RegistrationForm registrationForm, BindingResult result) {
if (result.hasErrors()) {
return "registrationForm";
}
// Perform business logic, e.g. persist registration data
return "formSubmitted";
}
}

Resources