If I understood you well:
- browser sends
POST /insertdata
to www.mypage.com
- data gets inserted, server responds with
OK 200
- when user refreshes the page, the process is initiated again which inserts duplicate data
You can avoid it with redirection like this:
response.sendRedirect("http://www.mypage.com/insertsuccessful");
Place this code at the end of your servlet/JSP handling the POST. This is what will happen:
Note: the status code (302) and location header get set automatically by the sendRedirect
method.
Now when user refreshes the page it will be the www.mypage.com/insertsuccesful
which won't POST the duplicate data anymore.
You can also make www.mypage.com/insertfailed
page, and redirect to it if you catch an exception in your POST handler.
tutorial
update 2
To follow up on @JB Nizet's comments (thx for being careful), let's suppose that your webapp is deployed with a context path, e.g. www.mypage.com/webapp
, and review the following scenarios:
- the URL of your page for insert (
http://www.mypage.com/webapp/insertdata?redirectOnOK=/insertsuccessful
) contains a query string parameter redirectOnOk
which defines where the client will be redirected upon successful insert ->http://www.mypage.com/webapp/insertsuccessful
- webapp employs URL rewriting
- you are using Session for login control
1st scenario
The first thing to notice is that http://www.mypage.com/webapp/insertdata?redirectOnOK=/insertsuccessful
is not a valid URL. It is not valid because you don't expect a slash (/
) after a question mark (?
):
scheme://domain:port/path?query_string#fragment_id
A valid URL can contain english alphabet letters, numbers, dot (.
), hyphen (-
), underscore (_
) and a tilde (~
). Some other punctuation characters are reserved and every other character (and sometimes even the reserved characters) must be URL-encoded:
http://www.mypage.com/webapp/insertdata?redirectOnOK=%2Finsertsuccessful
Since a reserved character slash (/
) isn't expected after a reserved character question mark (?
) it must be encoded. This is the solution for the first scenario:
String redirectRelativeUrl = new URLDecoder().decode(request.getParameter("redirectOnOk"),"UTF-8");
response.sendRedirect(request.getContextPath() + redirectRelativeUrl)
If you are using non english alphabet charaters when forming the query string the keys and values should always be URL encoded:
String safe = new UrlEncoder().encode("ž@Š","UTF-8");
2nd scenario
URL rewriting is a mechanism for mapping URL's based on regular expressions. In other words, the browser requests:
http://www.mypage.com/webapp/resource/someName/12
If under the context root there is a JSP page resource.jsp
, then a URL rewrite rule can be defined to map the above to:
http://www.mypage.com/webapp/resource.jsp?name=someName&count=12
So if you are redirecting programmatically from your serlvet/JSP you must also apply the (outbound) URL rewrite rules. In the above example the inbound rules are:
/someName/12
-> ?name=someName&count=12
/webapp/resource
-> /webapp/resource.jsp
The outbound rules need to be applied when redirecting programmatically from server:
name=someName&count=12
-> /someName/12
/resource.jsp
-> /resource
The rules are presented this way for the sake of simplicity, and are not regular expressions actually. The solution in this case is:
response.sendRedirect(response.encodeRedirectURL(request.getRequestURI() + "?" + request.getQueryString())
getRequestURI
returns /webapp/resource.jsp
getQueryString
returns name=someName&count=12
encodeRedirectURL
has input /webapp/resource.jsp?name=someName&count=12
- the browser gets redirected to
/webapp/resource/someName/12
3rd scenario
Initiating a HTTP session is really simple:
Session session = request.getSession();
this has the consequence that it sets a JSESSIONID
cookie:
jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
If the browser has disabled the cookies, upon programmatic redirect the user won't be authenticated anymore, meaning that he will have to login again. The solution in this case is:
String relativeRedirectUrl="/insertSucessful";
response.sendRedirect(response.encodeURL(request.getContextPath() + relativeRedirectUrl));
encodeURL
appends ;jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
to input if cookies are disabled
- the browser gets redirected to
/webapp/insertSucessful;jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
Conclusion
- Errors that emerge from invalid URL syntax are hard to debug, and very hard to notice. It is good practice to log URL's before redirecting to them.
- It is better to use relative URL's because then you can deploy your webapp's on multiple servers with different domain names, and on different context path's without changing the source code or values in some property files.