Issue
I've been working on implementing Punchout
in my eCommerce Application. My implementation works as follows.
Everything was working fine till yesterday, then the session started to getting dropped when the redirection to store front took place.
My Observation:
The HttpServletRequest
object is RequestFacade
before the redirection takes place, but after I redirect, it becomes ApplicationHttpRequest
. I can find the RequestFacade
wrapped in ApplicationHttpRequest
but I cannot find the object I put in the session. Below is the function I am using to put the object in session.
/**
* Creates an object of {@link PunchoutSessionDTO} and puts it in
* the session, making it a punchout session.
*
* @param punchoutTransaction
* The {@link PunchoutTransaction} object passed from the
* {@link PunchoutStoreEntryController}.
* @param session
* The {@link HttpSession}.
*/
public void createPunchoutSession(PunchoutTransaction punchoutTransaction, HttpSession session) {
// Create a PunchoutSessionDTO object.
PunchoutSessionDTO state = new PunchoutSessionDTO();
// Initialize it with the variables from the PunchoutTransaction
// object passed to it.
state.setBrowserFormPost(punchoutTransaction.getCallbackURL());
state.setBuyerCookie(punchoutTransaction.getBuyerCookie());
state.setFromId(punchoutTransaction.getFromId());
state.setToId(punchoutTransaction.getToId());
state.setPoTransId(punchoutTransaction.getTransactionId());
state.setOciPunchout(punchoutTransaction.getTransactionType() == PunchoutTransaction.TYPE_OCI);
// And put it in the session, so that the session could be
// identified as a punchout session.
session.setAttribute("PunchoutState", state);
// Set the max inactive interval of the session to the value
// provided in the store property. If such store property is
// not found, a default of 5 minutes is used.
/*String vid = punchoutTransaction.getVendorId();
Integer timeout = PunchoutStorePropertyFactory.getTimeoutPeriod(vid);
session.setMaxInactiveInterval( (timeout == null ? 5 : timeout) * 60); */
logger.info("Punchout Session Created for " + punchoutTransaction.getBuyerCookie());
}
Everything was working fine till I decided that I should set a timeout value for the session. After this point, problem started to occur. At first, I thought that I am messing it up by passing the incorrect value for setMaxInactiveInterval()
, so I commented it. To my surprise, the session was getting dropped anyway.
Please Note:
- We are using
Apache Tomcat
onWindows 8.1
.
Server version: Apache Tomcat/7.0.54 Server built: May 19 2014 10:26:15 Server number: 7.0.54.0 OS Name: Windows 8 OS Version: 6.2 Architecture: amd64 JVM Version: 1.7.0_51-b13 JVM Vendor: Oracle Corporation
We are using Spring 2.5. Yes! And we cannot migrate since this application is very huge (Over 10,000 source files).
The URL patterns
*.po
and*.html
are mapping to the same servlet, so the redirection occurs within the same servlet.
Google Searches:
Why does HttpServletRequest object changes.
HttpServletRequest changes to ApplicationHttpRequest
HttpServletRequest to ApplicationHttpRequest
Spring ServletRequest object changing
HttpServletRequest changes after redirection
This silly mistake is pissing us off since last 3 days. Any help would be appreciated! Please point out any silly mistake I have made, and some good tips related to session handling/management are the most welcome ones. If you think that I have not included enough information, please point it out as well. Thanks :)
Solution
Yes, I am answering my own question. I wish to go in details so that future comers may find their answers.
Turns out I am an idiot who is redirecting to absolute path.
Redirection is the key.
No matter whether the servlet you are redirecting to resides on the same application server, is within the same application or it even shares the same servlet. Any request redirected to absolute paths has their own context! So the request object created for them are completely new and has their separate sessions. A session is only maintained if the redirection is being sent on the same port
, host
and webapp
. If redirection is done within the same application, use relative paths using relative paths is the best practice.
Redirecting from https://localhost/servlet1.html
to http://localhost/servlet2.html
are very different, even though the URLs map to the same servlet (Please notice the difference).
Redirecting from https://localhost/servlet1.html
to https://192.168.x.x/servlet2.html
or https://127.0.0.1/servlet2.html
would bear the same results.
The best practice here would be redirecting to paths relative to your application. This would share the session object in the most efficient way.
Using response.sendRedirect("servlet2.html");
is best thing do here (in my opinion).
Understanding the Cookies
A session is identified by the JSESSIONID
cookie. If the browser forwards this cookie, then the session is forwarded to the other servlet or controller (or whatever). HTTP
and HTTPs
are different protocols and hence, different cookies are used. Similarly, localhost
and IP addresses are different hosts for a browser, hence different cookies are used. The JSESSIONID
cookie is forwarded if the protocol
, host
and webapp context
remains the same, which however, has the same meaning as using relative paths in the redirection. Redirecting to the relative addresses could be thought of as a safe way to redirect on the same host, protocol and application context. It is the browser that decides if it is going to forward your JSESSIONID
cookie or not
Answered By - Jay