Is it possible to pass Flash parameters from GET method to POST method in the same controller? - spring

I have two controllers. The first send some data using flash parameters to another one
#PostMapping
public String processOrder(Model model, NewOrder order, RedirectAttributes attributes) {
model.addAttribute(order);
attributes.addFlashAttribute("order", order);
return ("redirect:/sendorder");
}
And it's received by:
#GetMapping
public String showSendOrderForm(Model model, #ModelAttribute("order") NewOrder order) {
OrderDetails details = new OrderDetails();
details.setOrder(order);
model.addAttribute("details", details );
model.addAttribute("companies", companyProxy.getCompanies());
return "orderDetails";
}
Can I use value send in Flash attributes in POST method somehow? Or maybe could I use something else instead of Flash attributes?
POST method:
#PostMapping
public String processTaco(Model model, OrderDetails details, SessionStatus sessionStatus) {
detailsProxy.addOrderDetails(details);
sessionStatus.setComplete();
return "redirect:/";
}

Related

why Spring mvc redirect not working well?

#PostMapping("/regist")
public String regist(Person person, Model model) {
Person p = new Person("name", "age");
model.addAttribute("person", p); //add person to model
model.addAttribute("hobby", "reading);
return "redirect:/info";
}
#GetMapping("/info")
public String info() {
return "result";
}
Why (person) model.addAttribute("person", p) not appended to url like (hobby) when redirecting?
Model attributes are not used for redirects. Have a look at RedirectAttributes instead.
A specialization of the Model interface that controllers can use to
select attributes for a redirect scenario. Since the intent of adding
redirect attributes is very explicit -- i.e. to be used for a redirect
URL, attribute values may be formatted as Strings and stored that way
to make them eligible to be appended to the query string or expanded
as URI variables in org.springframework.web.servlet.view.RedirectView.
This interface also provides a way to add flash attributes. For a
general overview of flash attributes see FlashMap. You can use
RedirectAttributes to store flash attributes and they will be
automatically propagated to the "output" FlashMap of the current
request.
Example usage in an #Controller:
#RequestMapping(value = "/accounts", method = RequestMethod.POST)
public String handle(Account account, BindingResult result, RedirectAttributes redirectAttrs) {
if (result.hasErrors()) {
return "accounts/new";
}
// Save account ...
redirectAttrs.addAttribute("id", account.getId()).addFlashAttribute("message", "Account created!");
return "redirect:/accounts/{id}";
}
A RedirectAttributes model is
empty when the method is called and is never used unless the method
returns a redirect view name or a RedirectView.
After the redirect, flash attributes are automatically added to the
model of the controller that serves the target URL.

Spring REST Controller should PUT JSON and then redirect to specified page

I wrote a #RestController with one #PutMapping. Everything works technically fine. When the PutMapper is called, the JSON Object is rendered in my browser. But that's exactly the point what the customer doesn't want of course. What I'm trying to do is to send the JSON Object via PUT Method and then show a specified View. How can I handle this?
This is my RestController:
#RestController
public class UserRESTController {
private UserController userController;
#Autowired
public UserRESTController(UserController userController) {
this.userController = userController;
}
#PutMapping("/admin/changeUser")
public UserModel changeUser(#ModelAttribute("user") #Valid UserModel user, BindingResult result, Model model) {
if (result.hasErrors()) {
model.addAttribute("error", true);
userController.showUserToEdit(user.getUserId(), model);
}
model.addAttribute("editSuccess", true);
model.addAttribute("userId", user.getUserId());
model.addAttribute("userFirstName", user.getFirstName());
model.addAttribute("userLastName", user.getLastName());
userController.showUserList(Optional.empty(), Optional.empty(), Optional.empty(), model);
return user;
}
}
The Line
userController.showUserList(Optional.empty(), Optional.empty(), Optional.empty(), model);
calls another, non-REST-Controller, which simply renders a List of all users.
What can I do to get the user list after the JSON is sent?

How can I return a response Body with Spring Rest MVC when i have also to return a Web page for MVC process?

This is my Code, i know that i should not make 2 return statements, but just for explaining my issue. Thanks
#PostMapping
#ResponseStatus(HttpStatus.Created)
public String addStudent(#RequestBody Student student){
return StudentRep.save(Student);// Should be PayLoad Client Response
return “Student”; // Should be redirect to Student.html
}
You don't need to return a ResponseBody. You can simply add attributes to your Model and then use them in your views.
#PostMapping
#ResponseStatus(HttpStatus.Created)
public String addStudent(#RequestBody Student student, Model model){
String id = StudentRep.save(Student);// Should be PayLoad Client Response
model.addAttribute("studentId", id);
// Will redirect to Student.html where you can use the id attribute.
return “Student”;
}
Now, if you were using Thymeleaf, you could use this new attribute anywhere you want in your template. I am not sure how you are creating your templates, so I just used Thymeleaf as an example.
<p th:text=${id}></p>
Now if you want to return a Stundet object, you would need to the following changes to your controller.
#PostMapping
#ResponseStatus(HttpStatus.Created)
public String addStudent(#RequestBody Student student, Model model){
StudentRep.save(Student);// Should be PayLoad Client Response
model.addAttribute("student", student);
// Will redirect to Student.html where you can use the student attribute.
return “Student”;
}
I think that i find the solution of my answer.
I should annotate the controller that contains my method by #RestController instead of #Controller.
So then, the response will automatically return a JSON HTTP response.

Can't access Model attributes during validation

I'm using Spring 3.1 and have web pages using validation. The field-level validation, and the display of errors, works OK. My problem is with Model attributes not being available during the validation form display.
Let's say I've code:
#RequestMapping(value="/edit", method=RequestMethod.GET)
public String getEdit(#RequestParam("id") Long id, Model model) {
model.addAttribute("mytitle", "Hello There");
return "editObject"
}
#RequestMapping(value="/edit", method=RequestMethod.POST)
public String postEdit(#RequestParam("id") Long id, #Valid #ModelAttribute("object") MyData object, BindingResult result) {
if(result.hasErrors()) {
return "editObject";
}
[snip]
}
If I have an error the hasErrors() is detected and short-circuits to the map "editObject". However, the model attributes aren't available.
What do I use here? I tried adding a Model reference to the postEdit parameter list and adding in again things like the "mytitle" attribute.
Thanks,
Jerome.
When postEdit controller render the editObject view, you are in a new request, so you are loosing the model (previously set for getEdit action).
What you need to do it re-set any values needed in a new model:
#RequestMapping(value="/edit", method=RequestMethod.POST)
public String postEdit(#RequestParam("id") Long id, #Valid #ModelAttribute("object") MyData object, BindingResult result, Model model) {
if(result.hasErrors()) {
model.addAttribute("mytitle", "Hello There");
model.addAttribute("object", object);
return "editObject";
}
If you need to keep those attributes for different views you can store them in a session for example (so that you won't have to re-set them for each new request).

Force Initialization of #ModelAttributes in Spring MVC 3.1

I am writing a wizard-like controller that handles the management of a single bean across multiple views. I use #SessionAttributes to store the bean, and SessionStatus.setComplete() to terminate the session in the final call. However, if the user abandons the wizard and goes to another part of the application, I need to force Spring to re-create the #ModelAttribute when they return. For example:
#Controller
#SessionAttributes("commandBean")
#RequestMapping(value = "/order")
public class OrderController
{
#RequestMapping("/*", method=RequestMethod.GET)
public String getCustomerForm(#ModelAttribute("commandBean") Order commandBean)
{
return "customerForm";
}
#RequestMapping("/*", method=RequestMethod.GET)
public String saveCustomer(#ModelAttribute("commandBean") Order commandBean, BindingResult result)
{
[ Save the customer data ];
return "redirect:payment";
}
#RequestMapping("/payment", method=RequestMethod.GET)
public String getPaymentForm(#ModelAttribute("commandBean") Order commandBean)
{
return "paymentForm";
}
#RequestMapping("/payment", method=RequestMethod.GET)
public String savePayment(#ModelAttribute("commandBean") Order commandBean, BindingResult result)
{
[ Save the payment data ];
return "redirect:confirmation";
}
#RequestMapping("/confirmation", method=RequestMethod.GET)
public String getConfirmationForm(#ModelAttribute("commandBean") Order commandBean)
{
return "confirmationForm";
}
#RequestMapping("/confirmation", method=RequestMethod.GET)
public String saveOrder(#ModelAttribute("commandBean") Order commandBean, BindingResult result, SessionStatus status)
{
[ Save the payment data ];
status.setComplete();
return "redirect:/order";
}
#ModelAttribute("commandBean")
public Order getOrder()
{
return new Order();
}
}
If a user makes a request to the application that would trigger the "getCustomerForm" method (i.e., http://mysite.com/order), and there's already a "commandBean" session attribute, then "getOrder" is not called. I need to make sure that a new Order object is created in this circumstance. Do I just have to repopulate it manually in getCustomerForm?
Thoughts? Please let me know if I'm not making myself clear.
Yes, sounds like you may have to repopulate it manually in getCustomerForm - if an attribute is part of the #SessionAttributes and present in the session, then like you said #ModelAttribute method is not called on it.
An alternative may be to define a new controller with only getCustomerForm method along with the #ModelAttribute method but without the #SessionAttributes on the type so that you can guarantee that #ModelAttribute method is called, and then continue with the existing #RequestMapped methods in the existing controller.

Resources