How to keep request parameters after redirect? - spring

I'm trying to resolve a bug when I send a form with an empty input.
This is my methode:
#RequestMapping(value = "/modifier.html", method = RequestMethod.POST)
public String modifier(ModelMap map, #ModelAttribute("FormObject") FormObject formObject, BindingResult result, HttpServletRequest req) {
formObject.setModif(true);
String idParam = req.getParameter("idTypeOuverture");
if (result.hasErrors()) {
return "redirect:/gestion.html?section=Configuration&panel=4&ouvrir=modifier";
} else {
//Instructions
}
When there are errors (empty input) the controller redirects to this link to tell user to correct errors. The problem is when I check parameters here they look correct (id, name ...), but the id becomes null in the following method:
#Override
public ModelAndView dispatcher(HttpServletRequest request, HttpServletResponse response) throws RorException {
Map<String, Object> myModel = (Map<String, Object>) request.getAttribute(EnumParam.R_MY_MODEL.getKey());
Enumeration<?> keys = request.getParameterNames();
while (keys.hasMoreElements()) {
String paramName = (String) keys.nextElement();
String value = request.getParameter(paramName);
myModel.put(paramName, value);
}
GlobalSession globalSession = (GlobalSession) getApplicationContext().getBean(Utilities.GLOBALSESSION_BEAN_REF);
myModel.put("module", globalSession.getModule().getKeyMessage());
String section = request.getParameter("section");
// This instruction returns null
String idForm = request.getParameter("id");
id = Integer.parseInt(idForm);
// This instruction returns NumberFormatException
ObjectForm of = getForm(id);
// ...
}
Well, I don't know why parameter id changed after redericting? do you have any idea? I tried to redifine parameters in the first method but still got the same NFE.
Thank you in advance.
Thank you

Although the previous answer is accepted, I am adding this answer just for your information.
You can also use RedirectAttributes with and without FlashAttributes also Before issuing redirect, post method should take RedirectAttributes as argument These attributes will be passed as request parameters Look at my code example and see if its helpful.
Way 1 :
#RequestMapping(value={"/requestInfo.html"}, method=RequestMethod.POST)
public String requestInfoPost1(
#ModelAttribute("requestInfoData") RequestInfoData requestInfoData,
BindingResult result,
RedirectAttributes redirectAttributes,
SessionStatus status
) {
// some logic
redirectAttributes.addAttribute("name", requestInfoData.getName());
redirectAttributes.addAttribute("age", requestInfoData.getAge());
// some logic
return "redirect:requestInfoSuccessRedirect";
}
#RequestMapping("requestInfoSuccessRedirect")
public String requestInfoSuccessRedirect()
{
return "requestInfoSuccess";
}
Way 2:
Whatever data is added in flash attribute will be added in session It will be in session only till redirect is successful On redirect, data is retrieved from session and added to Model for new Request. Only after redirect is successful, data is removed
#RequestMapping(value={"/requestInfo.htm"}, method=RequestMethod.POST)
public String requestInfoPost(
#ModelAttribute("requestInfoData") RequestInfoData requestInfoData,
BindingResult result,
RedirectAttributes redirectAttributes,
SessionStatus status
) {
// some logic
redirectAttributes.addFlashAttribute("requestInfoData",
requestInfoData);
// some logic
return "redirect:requestInfoSuccessRedirect";
}
#RequestMapping("requestInfoSuccessRedirect")
public String requestInfoSuccessRedirect()
{
return "requestInfoSuccess";
}

The request parameter is only for one request.
You make a redirect, it means that you make another new "request".
You should add it to the redirect:
return "redirect:/gestion.html?section=Configuration&panel=4&ouvrir=modifier&idTypeOuverture="+idParam;

Related

Spring Boot - redirect to a different controller method

I am creating a very basic application with SpringBoot and Thymeleaf. In the controller I have 2 methods as follows:
Method1 - This method displays all the data from the database:
#RequestMapping("/showData")
public String showData(Model model)
{
model.addAttribute("Data", dataRepo.findAll());
return "show_data";
}
Method2 - This method adds data to the database:
#RequestMapping(value = "/addData", method = RequestMethod.POST)
public String addData(#Valid Data data, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
return "add_data";
}
model.addAttribute("data", data);
investmentTypeRepo.save(data);
return "add_data.html";
}
HTML files are present corresponding to these methods i.e. show_data.html and add_data.html.
Once the addData method completes, I want to display all the data from the database. However, the above redirects the code to the static add_data.html page and the newly added data is not displayed. I need to somehow invoke the showData method on the controller so I need to redirect the user to the /showData URL. Is this possible? If so, how can this be done?
Try this:
#RequestMapping(value = "/addData", method = RequestMethod.POST)
public String addData(#Valid Data data, BindingResult bindingResult, Model model) {
//your code
return "redirect:/showData";
}
sparrow's solution did not work for me. It just rendered the text "redirect:/"
I was able to get it working by adding HttpServletResponse httpResponse to the controller method header.
Then in the code, adding httpResponse.sendRedirect("/"); into the method.
Example:
#RequestMapping("/test")
public String test(#RequestParam("testValue") String testValue, HttpServletResponse httpResponse) throws Exception {
if(testValue == null) {
httpResponse.sendRedirect("/");
return null;
}
return "<h1>success: " + testValue + "</h1>";
}
Below Solution worked for me.
getAllCategory() method displays the data and createCategory() method add data to the database. Using return "redirect:categories";, will redirect to the getAllCategory() method.
#GetMapping("/categories")
public String getAllCategory(Model model) {
model.addAttribute("categories",categoryRepo.findAll());
return "index";
}
#PostMapping("/categories")
public String createCategory(#Valid Category category) {
categoryRepo.save(category);
return "redirect:categories";
}
OR using ajax jQuery also it is possible.
You should return a http status code 3xx from your addData request and put the redirct url in the response.

Adding #ModelAttribute results in 400 (Bad Request) in Delete Request

I can submit a delete request fine with the following:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
However, when I add an #ModelAttribute variable, I get 400 (Bad Request) as the http response code:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id, #ModelAttribute("authUser") User authUser) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
This #ModelAttribute is working fine with a put request handler I have in my #RestController but not in this delete request.
Here's the #ModelAttribute code:
#ModelAttribute("authUser")
public User authUser(#AuthenticationPrincipal SpringAuthUser springAuthUser) throws Exception {
User user = ConstantsHome.userprofileMgr.getUserByUserId(springAuthUser.getUsername(), true, true);
user.updateRights(null);
request.getSession().setAttribute(ConstantsHome.USEROBJECT_KEY, user);
return user;
}
Why would adding #ModelAttribute cause a delete request to return a 400 (Bad Request) http response?
I'm using spring-web-4.1.4 & spring-security-4.0.3
I digged a little and found that specifying a #PathVariable of "id" somehow attaches it to the #ModelAttribute variable (as a Long(!) instead of a String as I specified). I then came across this post that lead me to different ways to resolve the issue :
Values of #PathVariable and #ModelAttribute overlapping.
Ended up with this as a method declaration (replaced "id" with "userId"):
#RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteUser(#PathVariable String userId,
#ModelAttribute("authUser") User authUser) {
...
}
Hopefully this will help someone else quickly that might run into this issue instead of spending a day trying to figure it out...

Unable to access redirectAttributes while redirecting to controller action with Paramerters

In Spring MVC,
When the return value contains redirect: prefix, the viewResolver recognizes this as a special indication that a redirect is needed. The rest of the view name will be treated as the redirect URL. And the client will send a new request to this redirect URL.
We can write a handler method like this to handle the redirect:
#RequestMapping(value="/foo", method = RequestMethod.POST )
public String foo(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("message", "I am message");
return "redirect:/bar";
}
Now we can access this redirectAttribute in bar() like this
#RequestMapping(value="/bar", method = RequestMethod.GET )
public String bar(HttpServletRequest request, HttpServletResponse response, Model model) {
String error = (String) model.asMap().get("message");
}
Normally we can access this the redirectAttribute inside bar() method, But when I specify a URL as parameterised url in return statement like this below
return "redirect:/bar?x=1&y=2";
I am unable to access the redirectAttributes
I further Inspected network in chrome and I found that while using un-parameterised url in return statement jsessionid remains same after redirect, but it does changes while using parameterised urls.
Can anyone please tell me why is this happening or am I going wrong somewhere?
If you want to access the value of paramater x and y in your redirect controller you need to get Parameter from request.
#RequestMapping(value="/bar", method = RequestMethod.GET )
public String bar(HttpServletRequest request, HttpServletResponse response, Model model) {
System.out.println(request.getParameter("y"));
return null;
}

Spring RedirectAttributes clears session after redirect

In my Spring i have used RedirectAttributes to display the message after login success or failure
and i have one SessionAttribute. I set SessionAttributes in two times first one is when i click the menu
i set Object to SessionAttribute and second one is after login success
what my problem is the SessionAttribute which i set after login success is not working if i remove the
RedirectAttributes means it is working fine.
when i searched i found this
addFlashAttribute actually stores the attributes in a flashmap (which is internally maintained in the
users session and removed once the next redirected request gets fulfilled)
when i debug it alwys shows the default one not show the value set after login.
this is for login
#RequestMapping(value = "/sample-client", method = RequestMethod.POST)
public String getClient(HttpServletRequest request, Model model, final RedirectAttributes redirectAttributes) {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
Client client = createClient(userName, password);
if (client != null) {
model.addAttribute("clientObject", client);
redirectAttributes.addFlashAttribute("message", "Logined Successfully");
return "redirect:" + "/sample/user";
} else {
redirectAttributes.addFlashAttribute("error", "true");
return "redirect:" + "/sample/login";
}
}
after login
#RequestMapping(value = "/byName", method = RequestMethod.GET)
public
#ResponseBody
String getUserByName(HttpServletRequest request, #ModelAttribute("clientObject") User user) {
String firstName = request.getParameter("firstName");
String lastName = request.getParameter("lastName");
Integer page = Integer.parseInt(request.getParameter("page"));
return sample.getUserSearchByName(user, firstName, lastName, page);
}
when i checked the clientObject here it shows the default one.

How to add error on Spring MVC simpleformcontroller?

I have this problem in my Spring MVC 2.5 apps and I am not sure what should I do.
Here is my code:
public class AddStationController extends SimpleFormController {
private SimpleStationManager stationManager;
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
StationDetails detail = (StationDetails) command;
//add to DB
int return = stationManager.addStation(detail);
//return value: 1 = successful,
// if not = unsuccessful
if(return != 1){
//how can I add error so that when I display my formview ,
//I could notify the user that saving to the db is not successful?
showform();
}
return new ModelAndView("redirect:" + getSuccessView());
}
}
How is it possible to add some message when I display my formview again so that I could tell the user that adding the station was not successful?
And how to handle that in my jsp?
I at first thought you might want to use Validators but instead I think you can do the following:
public class AddStationController extends SimpleFormController {
private SimpleStationManager stationManager;
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
StationDetails detail = (StationDetails) command;
//add to DB
int return = stationManager.addStation(detail);
//return value: 1 = successful,
// if not = unsuccessful
if(return != 1){
//Account for failure in adding station
errors.reject("exception.station.submitFailure", "Adding the station was not successful");
showform(request, response, errors);
}
return new ModelAndView("redirect:" + getSuccessView());
}
}
Then in your JSP you can do the following:
<form:errors path="*">
Then any errors you bind will show up there.
There are a couple ways to do that. I prefer not to use the showForm() method b/c I want more control. So I do one of the following, I'm sure there will be several alternative answers given for your question.
If you don't want to fail b/c of a specific field you can just send back an error on the model like this:
ModelAndView mav = new ModelAndView(this.getFormView());
mav.addObject(this.getCommandName(), command);
mav.addObject("errorMessage", "The thing you tried to do failed");
return mav;
Then in your jsp you would do this:
<c:if test="${not empty errorMessage}">
${errorMessage}
</c:if>
If you have a specific field that has caused the error you can attach an error to the specific field like this (this rejects the length of a field called "alternateid":
errors.rejectValue("alternateId", "longerThan",
new Object[] { Integer.valueOf(2) }, "Please enter at least two characters.");
ModelAndView mav = new ModelAndView(this.getFormView());
mav.addAllObjects(errors.getModel());
mav.addObject(this.getCommandName(), command);
return mav;
Then in your jsp you would use the form tag library and do this:
<form:errors path="alternateId"/>
That's assuming you're using the spring form tag library.

Resources