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

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?

Related

Why is Controller not loading view?

Hi I'm making a car rental app and I have two controllers atm, the first controller handles two form views, the second is for displaying a table of data sent from the controller.
First Controller
indexController
#Controller
#RequestMapping("/")
public class IndexController {
#Autowired
private UserService userService;
#Autowired
private CustomerFactory userFactory;
#PostMapping("/register")
public String registerUser(#ModelAttribute User user){
User u = userFactory.createUser(user.getName(), user.getPassword());
userService.saveUser(u);
return "login";
}
#GetMapping("/login")
public String login(){
return "login";
}
#PostMapping("/login")
public String loginUser(#ModelAttribute User user){
User authenticatedUser = userService.authenticate(user.getName(), user.getPassword());
System.out.println(authenticatedUser.toString());
return "car-list";
}
}
Second Controller
Vehicle Controller
#Controller
#RequestMapping("/car-list")
public class VehicleController {
#GetMapping
public String carList(Model model){
List<Vehicle> vehicles = new ArrayList<>();
Vehicle VWGolf = new BasicCar();
Vehicle Duster = new SUVDecorator(new BasicCar());
vehicles.add(Duster);
Location limerick= new Location("Limerick");
Location cork = new Location("Cork");
VehicleUpdatePublisher golfSubject = new VehicleUpdatePublisher(VWGolf, "Volkswagen Golf");
VehicleUpdatePublisher dustersubject = new VehicleUpdatePublisher(Duster, "Dacia Duster");
golfSubject.attach(limerick);
dustersubject.attach(limerick);
VehicleUpdatePublisher ferrariSubject = new VehicleUpdatePublisher(VWGolf, "Ferrari 458");
VehicleUpdatePublisher rollsRoyceSubject = new VehicleUpdatePublisher(Duster, "Rolls Royce Ghost");
ferrariSubject.attach(cork);
rollsRoyceSubject.attach(cork);
model.addAttribute("location1", limerick.getLocationName());
model.addAttribute("vehicle1Name", golfSubject.getVehicleName());
model.addAttribute("vehicle2Name", dustersubject.getVehicleName());
model.addAttribute("location2", cork.getLocationName());
model.addAttribute("vehicle3Name", ferrariSubject.getVehicleName());
model.addAttribute("vehicle4Name", rollsRoyceSubject.getVehicleName());
return "car-list";
}
}
My first controller handles the first two views index.html and login.html
The second controller handles car-list.html, my problem is when I submit my login.html form through the loginUser() function it doesn't move to the car-list view. It just brings it to a blank page.
The url stays as localhost:8080/login but if I put localhost:8080/car-list in it brings it to my view with the table displayed. I think its some issue with my mapping but I'm not sure?
Any help appreciated.
Can add code for the views if needed.

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

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:/";
}

How can I check if the user have correctly submitted the previous form into a Spring MVC application that contemplate some steps?

I am pretty new in Spring MVC and I have the following situation.
I am working on a Spring MVC application that implement a user registration process. The prcess is divided into 4 steps. In each step the user insert some information into a form that is submitted and that is handled by the related method into the controller class. Each of these controller method take the related command object that contains the information of the submitted form.
So I have something like this:
#Controller
public class RegistrazioneController {
// This is the first step and show a view that contain the first form:
#RequestMapping(value = "/registrationStep1")
public String registrationStep1(Model model) {
return "/registrazione/registration-step1";
}
#RequestMapping(value = "/registrationStep2", method = RequestMethod.POST)
public String registrationStep2(#ModelAttribute RegistrationStep1 registrationStep1, Model model) throws APIException {
.......................................................
.......................................................
.......................................................
return "/registrazione/registration-step2";
}
#RequestMapping(value = "/registrationStep3", method = RequestMethod.POST)
public String registrationStep3(#ModelAttribute RegistrationStep3 registrationStep3, Model model) throws APIException {
.......................................................
.......................................................
.......................................................
return "/registrazione/registration-step3";
}
// This method return the final view after the completation of the user registration:
#RequestMapping(value = "/registrationStep4", method = RequestMethod.POST)
public String registrationStep2(#ModelAttribute RegistrationStep4 registrationStep4, Model model) throws APIException {
.......................................................
PERFORM THE USER REGISTRATION
.......................................................
return "/registrazione/registration-step4";
}
}
So it works pretty fine. My problem is that the application have tho check that, when enter into a registration step, the previous steps are completed (the previous form was compiled and submitted).
So I think that I have to do something like this, for example: ** when enter into the registrationStep3() have to check if the command object of the previous registrationStep2() step method was correctly setted (it is valid), so it means that the user have completed the previous registration step.
The application have to prevent that the user try to acces the registration starting from a step without having complete the previous steps of the registration process.
What is the best way to implement this behavior?
I have worked in some Sap Hybris projects and this platform suggest to use the following process :
Step1Form, Step2Form and Step3Form, if you have first name and last name in your 1 step form you ll have the same in Step1Form class as attributes.
and for each class create a validator, in the next step controller u have to validate the previous step if it is not valid redirect the user to the previous step.
you already have RegistrationStep1, and RegistrationStep2 and RegistrationStep3
lets create a validator for RegistrationStep1 :
import org.apache.commons.validator.routines.EmailValidator;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
#Component(value = "registrationStep1Validator")
public class RegistrationStep1Validator implements Validator
{
#Override
public boolean supports(final Class<?> aClass)
{
return RegistrationStep1.class.equals(aClass);
}
#Override
public void validate(final Object object, final Errors errors)
{
final RegistrationStep1 step1= (RegistrationStep1) object;
final String name = step1.getName();
final String email = step1.getEmail();
if (email.isEmpty or email == null)
{
errors.reject("email", "Email must not be blank or null");
}
if (name.isEmpty or name== null)
{
errors.reject("name", "Name must not be blank");
}
if (!EmailValidator.getInstance().isValid(email))
{
errors.reject("email", "Email must be valid");
}
}
}
//later in your controller
#RequestMapping(value = "/registrationStep2", method = RequestMethod.POST)
public String registrationStep2(#ModelAttribute RegistrationStep1 registrationStep1,final BindingResult bindingResult, Model model) {
registrationStep1Validator.validate(registrationStep1,bindingResult);
if (bindingResult.hasErrors())
{
return "/registrazione/registration-step1";
}
return "/registrazione/registration-step2";
}

How to call one controller to another controller URL in Spring MVC?

Hi I am new to Spring MVC ,I want to call method from one controller to another controller ,how can I do that .please check my code below
#Controller
#RequestMapping(value="/getUser")
#ResponseBody
public User getUser()
{
User u = new User();
//Here my dao method is activated and I wil get some userobject
return u;
}
#Controller
#RequestMapping(value="/updatePSWD")
#ResponseBody
public String updatePswd()
{
here I want to call above controller method and
I want to update that user password here.
how can I do that
return "";
}
any one help me .
Can do like this:
#Autowired
private MyOtherController otherController;
#RequestMapping(value = "/...", method = ...)
#ResponseBody
public String post(#PathVariable String userId, HttpServletRequest request) {
return otherController.post(userId, request);
}
You never have to put business logic into the controller, and less business logic related with database, the transactionals class/methods should be in the service layer. But if you need to redirect to another controller method use redirect
#RequestMapping(value="/updatePSWD")
#ResponseBody
public String updatePswd()
{
return "redirect:/getUser.do";
}
A controller class is a Java class like any other. Although Spring does clever magic for you, using reflection to examine the annotations, your code can call methods just as normal Java code:
public String updatePasswd()
{
User u = getUser();
// manipulate u here
return u;
}
You should place method getUser in a service (example UserService class) .
In the getUser controller, you call method getUser in the Service to get the User
Similarly, in the updatePswd controller, you call method getUser in the Service ,too
Here no need to add #reponseBody annotation as your redirecting to another controller
Your code will look like
#Controller
class ControlloerClass{
#RequestMapping(value="/getUser",method = RequestMethod.GET)
#ResponseBody
public User getUser(){
User u = new User();
//Here my dao method is activated and I wil get some userobject
return u;
}
#RequestMapping(value="/updatePSWD",method = RequestMethod.GET)
public String updatePswd(){
//update your user password
return "redirect:/getUser";
}
}

Spring Framework 3 and session attributes

I have form object that I set to request in GET request handler in my Spring controller. First time user enters to page, a new form object should be made and set to request. If user sends form, then form object is populated from request and now form object has all user givern attributes. Then form is validated and if validation is ok, then form is saved to database. If form is not validated, I want to save form object to session and then redirect to GET request handling page. When request is redirected to GET handler, then it should check if session contains form object.
I have figured out that there is #SessionAttributes("form") annotation in Spring, but for some reason following doesnt work, because at first time, session attribute form is null and it gives error:
org.springframework.web.HttpSessionRequiredException: Session attribute 'form' required - not found in session
Here is my controller:
#RequestMapping(value="form", method=RequestMethod.GET)
public ModelAndView viewForm(#ModelAttribute("form") Form form) {
ModelAndView mav = new ModelAndView("form");
if(form == null) form = new Form();
mav.addObject("form", form);
return mav;
}
#RequestMapping(value="form", method=RequestMethod.POST)
#Transactional(readOnly = true)
public ModelAndView saveForm(#ModelAttribute("form") Form form) {
FormUtils.populate(form, request);
if(form.validate())
{
formDao.save();
}
else
{
return viewForm(form);
}
return null;
}
It throws Exception if controller called first time even though added #SessionAttributes({"form"}) to class. So add following populateForm method will fix this.
#SessionAttributes({"form"})
#Controller
public class MyController {
#ModelAttribute("form")
public Form populateForm() {
return new Form(); // populates form for the first time if its null
}
#RequestMapping(value="form", method=RequestMethod.GET)
public ModelAndView viewForm(#ModelAttribute("form") Form form) {
ModelAndView mav = new ModelAndView("form");
if(form == null) form = new Form();
mav.addObject("form", form);
return mav;
}
#RequestMapping(value="form", method=RequestMethod.POST)
#Transactional(readOnly = true)
public ModelAndView saveForm(#ModelAttribute("form") Form form) {
// ..etc etc
}
}
The job of #SessionAttribute is to bind an existing model object to the session. If it doesn't yet exist, you need to define it. It's unnecessarily confusing, in my opinion, but try something like this:
#SessionAttributes({"form"})
#Controller
public class MyController {
#RequestMapping(value="form", method=RequestMethod.GET)
public ModelAndView viewForm(#ModelAttribute("form") Form form) {
ModelAndView mav = new ModelAndView("form");
if(form == null) form = new Form();
mav.addObject("form", form);
return mav;
}
#RequestMapping(value="form", method=RequestMethod.POST)
#Transactional(readOnly = true)
public ModelAndView saveForm(#ModelAttribute("form") Form form) {
// ..etc etc
}
}
Note that the #SessionAttributes is declared on the class, rather than the method. You can put wherever you like, really, but I think it makes more sense on the class.
The documentation on this could be much clearer, in my opinion.
if there is no defined session object so I think it's gonna be like this:
#SessionAttributes({"form"})
#Controller
public class MyController {
#RequestMapping(value="form", method=RequestMethod.GET)
public ModelAndView viewForm() {
ModelAndView mav = new ModelAndView("form");
if(form == null) form = new Form();
mav.addObject("form", form);
return mav;
}
#RequestMapping(value="form", method=RequestMethod.POST)
#Transactional(readOnly = true)
public ModelAndView saveForm(#ModelAttribute("form") Form form) {
// ..etc etc
}
}
#Controller
#SessionAttributes("goal")
public class GoalController {
#RequestMapping(value = "/addGoal", method = RequestMethod.GET)
public String addGoal(Model model) {
model.addAttribute("goal", new Goal(11));
return "addGoal";
}
#RequestMapping(value = "/addGoal", method = RequestMethod.POST)
public String addGoalMinutes(#ModelAttribute("goal") Goal goal) {
System.out.println("goal minutes " + goal.getMinutes());
return "addMinutes";
}
}
On page addGoal.jsp user enters any amount and submits page. Posted amount is stored in HTTP Session because of
#ModelAttribute("goal") Goal goal
and
#SessionAttributes("goal")
Without #ModelAttribute("goal") amount entered by user on addGoal page would be lost
I'm struggling with this as well. I read this post and it made some things clearer:
Set session variable spring mvc 3
As far as I understood it this basically says:
that Spring puts the objects specified by #SessionAttributes into the session only for the duration between the first GET request and the POST request that comes after it. After that the object is removed from the session. I tried it in a small application and it approved the statement.
So if you want to have objects that last longer throughout multiple GET and POST requests you will have to add them manually to the HttpSession, as usual.

Resources