JSP form going as empty randomly after submitting with post request. I am using springboott with embedded tomcat in a openshift container. I have seen similar request in 2016 but no reply. Any help is highly appreciated.
JSP:
<textarea id="dataArea" cols="111" rows="28" name="data" Class="prj" onkeydown="limitCounter(this, countdown);" onkeyup="limitText(this, countdown);" onchange="limitText(this, countdown);" onclick="trueCount(this, countdown);">${frm.data}</textarea>
<img src="/prj/web/images/data_button.gif" border="0" style="cursor:hand" title="ALT + S" onclick="javascript:saveData()">
Javascripts:
function saveComments()
{ document.forms[0].action='<%=contextPath%>/saveData';
document.forms[0].submit(); self.close();
}
Controller:
#RequestMapping(value = "/saveData", method ={RequestMethod.POST})
public ModelAndView saveData(ModelMap modelMap, #ModelAttribute("frm") dataForm frm, BindingResult bindingResult, HttpServletRequest request, HttpServletResponse response)
throws Exception { }
We had both these RequestMethod.GET and RequestMethod.POST and removed the GET from the controller, but it did not work.
This code is working fine for 50 to 60 occurrences and the next one fails and the form is empty. We have enabled the logger and it showed the empty form. The immediate next action is working fine. Note: This action is performed from the popup screen. Please let me know if you need any more details
Finally the issue is resolved.
The issue is with the self.close() right after the submit action.
The root cause is the browser and it is triggering the self.close() before the submit action. We have removed the self.close() from there and close it after we received the response from controller. This fixed the issue. Thanks for the below post which helped us to identify the root cause.
Submit a form in a popup, and then close the popup
Related
i'm currently woking on a spring mvc project. I have a page with a form, which represents a configurator.
The user can choose some data in a bunch of select fields and proceeds to the next step, where he gets the same jsp-page but with some more fields, depending on his inputs he made. This will be repeated a few times until he gets his result on another page. Each time a POST will be performed.
Now if the user uses the back function of the Browser he doesn't get to the previous page, but to a browser default "broken page", where Chrome for example says something like "Please confirm resubmission of the form data...". To actually resubmit the data he has to press reload and confirm a popup.
The resubmission itself isn't really a problem, because the data does not get inconsistent, it just performs another call to the backend and receives the data it provides.
The real no-go is the fact that the user has to manually refresh the page and by chance gets confused by the default browser page.
I did some research and found out, that the PRG (Post-Redirect-Get) Pattern might solve this problem.
In fact i can now navigate through the browser or reload the page and does not get the popup or broken page - because it's now a GET request of course.
The problem now is, that if i navigate back, the last page does not contain the data it contained before, but is now empty because no data at all is existing.
I understand that it is now a GET request and no data gets posted, but i thought the previous page would be "reused", like shown here.
Now with the PRG-Pattern the handling of the application is even worse, because if the user reloads or navigates back, he basically has to start from scratch.
Did i misunderstood the meaning of this Pattern?
A quick look into some code, how i implemented this:
#PostMapping("/config")
public String handlePostRequestConfig(RedirectAttributes redirectAttributes, ProductForm productForm){
//Handle productForm and add additional content to it
if(noMoreStepsLeft){
return "redirect:/result";
}
redirectAttributes.addFlashAttribute("form", productForm);
return "redirect:/config";
}
#GetMapping("/config")
public String handleGetRequestConfig(Model model, #ModelAttribute("form") ProductForm productForm{
model.addAttribute("form", productForm);
return getJsp("product");
}
Inside JSP:
<form method="post" action="/config">
<c:foreach items="${form.selectFields}" var="selectField">
<input...>
</c:foreach>
<button type="submit">Submit</button>
</form>
In PRG, P is not the first step of user action flow. PRG is a part of the full flow.
The following shows a flow and how PRG fits in it:
User will hit a URL. For example: http://localhost:8080/myContextPath/config.
This will be handled using a GET handler:
#GetMapping("/config")
public String show(ModelMap model) {
// code
model.put("form", productForm);
return "product"; // returning view name which will be resolved by a view resolver
}
product.jsp:
<form commandName="form" method="post">
<c:foreach items="${form.selectFields}" var="selectField">
<input...>
</c:foreach>
<input type="submit" value="Submit"/>
</form>
This submit action will be handled by a POST handler:
#PostMapping("/config")
public String submit(#ModelAttribute("form") ProductForm productForm,
RedirectAttributes redirectAttributes){
// code, may be service calls, db actions etc
return "redirect:/config";
}
This redirect to /config will be handled again by /config GET handler. (Or you can redirect to any GET handler of course)
I have a simple Maven servlet/jsp application that I deploy to a local Tomcat 9 (via Eclipse). JSP pages are stored under root folder (src\main\webapp\*.jsp) which when Maven installs a WAR, they go under the root folder (MyAppContext\*.jsp along side MyAppContext\META-INF\ and MyAppContext\WEB-INF\).
The servlets' URL patterns are annotated for each servlet, e.g. /doactionone, /doactiontwo, etc. Most servlets perform the dispatching to various JSP pages, but I do have a direct anchor link on one.
I wanted to move these JSP pages into their own respective directory, so I moved them to src\main\webapp\jsp\*.jsp folder, and when the Maven install is run, they get placed under MyAppContext\jsp\.
The only entry I have in web.xml is a welcome file that after relocating the JSP files, it points to jsp\doactionone.jsp which loads that corresponding JSP page. This page contains a simple form:
<form action="doactionone" method="post">
...
<a href="jsp/doactiontwo.jsp">
<input type="submit" />...
</form>
The submission on this page actually calls the right servlet (the one defined with doactionone URL pattern). I also have a link that takes the user to the second page (doactiontwo.jsp).
However, when I navigate to that second page via this link, which has another simple form (see below), and perform the submission (post), I see in browser's debugging that the URL request is http://localhost:8080/MyAppContext/jsp/doactiontwo which, for obvious reason, would return a 404 status (and get no hit to this servlet's doPost() (or doGet()) methods either).
<form action="doactiontwo" method="post">
...
<input type="submit" />...
</form>
If I try to modify the second servlet's URL pattern to /jsp/doactiontwo, I can hit the servlet, but when doactiontwo actually dispatches/forwards the request after processing to the first servlet (doactionone) with:
RequestDispatcher rd = request.getRequestDispatcher("doactionone.jsp");
rd.forward(request, response);
when it gets loaded, when hover over the URL on the first page that initially was pointing to the second JSP page (<a href="jsp/doactiontwo.jsp">), now actually points to:
jsp/jsp/doactiontwo.jsp
The funny part is that the source code of doactionone.jsp still shows it as jsp/doactiontwo.jsp, but hovering over it shows http://localhost:8080/MyAppContext/jsp/jsp/doactiontwo, and when clicked, it obviously results in 404 status.
Can somebody explain why, first of all, the submission on the second JSP page requires the servlet to have a pattern of /jsp/doactiontwo to work rather than /doactiontwo? And is there a way around to avoid appending /jsp to the URL pattern?
And second, why when the second servlet processes the request and dispatches/forwards it to the first page, the URL now contains two jsp/'s?
You need to change your design to allow the controllers, a.k.a. Servlets, to drive your application. In this particular case, use the URL Pattern of second Servlet (doactiontwo) in place of you link:
#WebServlet(urlPatterns = { "doactiontwo" }
public class DoActionTwoServlet extends HttpServlet { /* ... */ }
<form action="doactionone" method="post">
...
<a href="doactiontwo"> <!-- This should match your second servlet's URL pattern -->
<input type="submit" />...
</form>
Now, since the default method when anchor link is invoked is GET, you need to overwrite DoActionTwoServlet's doGet() method, and forward those requests to an actual doactiontwo.jsp:
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
RequestDispatcher rd = request.getRequestDispatcher("jsp/doactiontwo.jsp");
rd.forward(request, response);
}
I am making a JSP/Servlet web app which starts with log in page.
After user enters log in information, a servlet, called LoginServlet, processes the data and if the log in is successful the servlet redirects user to MainPage.jsp like this:
RequestDispatcher rd = request.getRequestDispatcher("MainPage.jsp");
rd.forward(request,response);
It works. It takes me to MainPage.jsp, only the URL is NOT:
http://localhost:8080/RestauRec/MainPage.jsp
it is:
http://localhost:8080/RestauRec/LoginServlet
It is not an actual problem, but still, I want to know why this is and how can I change this?
Note: I don't know if it matters or not but, in the action attribute of the form element (in the log in page) I place LoginServlet. Like this:
<form action="LoginServlet" method="POST">
Thanks in advance!
forward is an action that happens within a single request-response cycle. It uses the forward-to resource to complete the response.
Your browser sends a single request to /someUrl and your server handles it, returning a response.
It is not an actual problem, but still, I want to know why this is and how can I change this?
You'd have to make your client, the browser, send a different request to another URL, possibly because of a redirect.
forward() method won't change the url. sendRedirect() in HttpServletResponse do change the url as well.
response.sendRedirect("MainPage.jsp");
Remember that a new request gets hit to the container when you do redirect. That means all the previous data vanishes and you'll get a brand new request.
I use request.getRequestDispatcher(url).forward(request, response) method in my controller !! I am in trouble. (I know that dispatcher make internal redirect, a forward reuses the current request), when I fill in a form and send request to controller that computes some logic and after forward to some simple page. If I push F5 in browser on my simple page (refresh page) my request will perform again. How to prevent this situation ??
RequestDispatcher will keep request attributes and forward page with same request, that is why if you refresh page controller gets same request and process it again. Use SendRedirect instead.
On the surface, this question will sound a lot like questions that may have been asked previously on SOF but I tried those answers long ago and no luck.
(For example, this question spring 3 not rendering model in jsp)
So I had a Spring 2.0 Controller that extended CancellableFormController, and it contained the following to bind the Command Object to the Form on JSP page render:
public class MyFormController extends CancellableFormController {
....
protected Object formBackingObject(HttpServletRequest request) throws ServletException {
MyCommand myCommand = new MyCommand();
... // add some list info to command object etc in preparation for page render
return myCommand;
}
....
}
The JSP Page looked something like the following:
<form:form method="post" commandName="myCommand">
<c:forEach items="${myCommand.myList}" var="myItem" varStatus="index">
</form:form>
To be clear, between the form tag definitions, a list of items was displayed on the JSP page. This is before any form submission has occurred (ie. at page render time). And what a beautifully simple world we lived in. Everything worked first time and there was peace on earth... sorry, enough sarcasm! ;)
OK, so I happily tried to upgrade this old code to Spring 3 and annotations. My current problem is ONLY getting the Command object to render on page load. When I enter data into form fields and submit the form etc, the data gets bound correctly. What I am trying to do is pre-populate the Command object, and then render that content into the JSP page before the form is populated and submitted.
I initially tried this:
#Controller
#RequestMapping(value = "/myContextPath")
public class MyFormController {
...
#RequestMapping(method = RequestMethod.GET)
public ModelAndView initForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView("myTilesViewName");
MyCommand myCommand = new MyCommand();
...
mv.addObject("myCommand", myCommand);
return mv;
}
...
}
Then I tried each of the following methods (the Controller class construct being the same as the above):
#RequestMapping(method = RequestMethod.GET)
#ModelAttribute("myCommand")
public String initForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
MyCommand myCommand = new MyCommand();
....
return "myTilesViewName";
}
#RequestMapping(method = RequestMethod.GET)
public String initForm(ModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception {
MyCommand myCommand = new MyCommand();
...
model.addAttribute("myCommand", cmd);
return "myTilesViewName";
}
I don't wish to add any confusion. I "imagine" that the answer to this problem is likely the same if I were just returning the view name of a JSP page... However, I am using Apache Tiles to handle the page selection. My definition looks something like:
<definition name="myTilesViewName" extends=".myTemplate">
<put-attribute name="title" value="MyTitle" type="string" />
<put-attribute name="body" value="/WEB-INF/jsp/myPage.jsp" />
</definition>
Please remember everything worked perfectly before with the Spring 2 CancellableFormController code. I have not changed the Tiles config or JSP pages at all so don't believe they are the source of this problem.
Thank you so much to anyone who can offer any assistance. It is certainly appreciated!
UPDATE:
This issue finally related to a Client side (JSP page) related problem. My assumption that "nothing had changed other than in the Controller" was incorrect. Sincere apologies to those who took the time to read this post and consider solutions. For anyone else reading with the same symptoms, please double check your View pages (JSP) and ensure they are syntactically correct for rendering. In my case, I had moved a JSP (with around 2000 lines of code) into a subfolder and broken a relative link to a nested jsp import declaration.