Reputation: 1119
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.
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.
Apache Tomcat
on Windows 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.
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 :)
Upvotes: 1
Views: 3125
Reputation: 177
This is how it works, It first checks whether relative redirect available or not then it else construct absolute path.
// Generate a temporary redirect to the specified location
try {
String locationUri;
// Relative redirects require HTTP/1.1
if (getRequest().getCoyoteRequest().getSupportsRelativeRedirects() &&
getContext().getUseRelativeRedirects()) {
locationUri = location;
} else {
locationUri = toAbsolute(location);
}
setStatus(status);
setHeader("Location", locationUri);
if (getContext().getSendRedirectBody()) {
PrintWriter writer = getWriter();
writer.print(sm.getString("coyoteResponse.sendRedirect.note",
Escape.htmlElementContent(locationUri)));
flushBuffer();
}
} catch (IllegalArgumentException e) {
log.warn(sm.getString("response.sendRedirectFail", location), e);
setStatus(SC_NOT_FOUND);
}
Upvotes: 1
Reputation: 1119
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.
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).
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
Upvotes: 3