Thursday, March 22, 2007

Screwing up HTTP Session for Servlet/JSP

Prerequisites:
1. Browsers under Mozilla project (e.g. Firefox, SeaMonkey)
2. Enable cookies
3. Tomcat (probably all Java web containers)

Procedure:
1. Write a page that use back-slashes as the directory seperator (e.g. http://www.abc.com\app\page.jsp)
2. Include this page with absolute path in all pages

Why:
1. The browser encode back-slashes as %5C. So, http://www.abc.com\app\page.jsp will be encoded as http://www.abc.com%5Capp%5Cpage.jsp
2. The browser tries to look up the cookies for the domain. However, the browser think that the domain name is www.abc.com%5Capp%5Cpage.jsp instead of www.abc.com
3. The browser cannot find the cookies for the domain. So, it does not send the cookies to the browser.
4. When cookies is enabled, Java Servlet and JSP uses it to store the session ID
5. Since the cookies was not found in the request header, the web container creates a new session and send to session ID with Set-Cookie header.
6. The browser uses the new session ID for the next request.
7. As a result, the web container creates new session for each browser request and the sessions are screwed up.

What about other browsers? I think IE is smart enough to replace all back-slashes to slashes before it does further processing. I don't know about others though...

You may want to ask why you would use back-slash. My answer is "No, you may not but your staff or your outsource partner may." In a workflow engine we are studying, we found the following JavaScript:
document.write("<iframe src='<%=request.getContextPath()%>\\app\\page.jsp'>")

My colleague asked for help about why the session does not work in Firefox. Since the code was written by different parties, we know nothing about the workflow engine. I alone used 6 man-hours to fix the BUG. I think I know fairly well on HTTP and Java Servlet. I tried many possible solutions like finding the HttpSession.invalidate(), session.removeAttribute(), appending the jsessionid, etc. Finally, I used a packet sniffer to dig out the pattern that changes the jsessionid cookie and recognize the weired %5C URL in a GET command.

Monday, March 05, 2007

Adobe Flex Push

There are ready to go assemblers in FDS samples application provided for you to develop your own Flex application with FDS. It is quite impressive that when a client update a piece of data, the FDS can synchronize the data to other Flex client without extra coding. However, what if you only want to push some changes to the client?

Calling update in assembler may be a good option. Using the DataServiceTransaction could be better:
DataServiceTransaction tx = DataServiceTransaction.begin(false);
Rate rate = ... // get the rate from some streaming data source

// do any necessary calculation
tx.updateItem("fds.rate", rate, null, null);
tx.commit();
This snippet should get the job done on the server side. On the client side, you need to handle the FDS message:

<mx:script>
public function handleMessage(event):void {
if (rate.id == event.message.body[2].id) {
rate = event.message.body[2];
}
}
</mx:script>
<mx:label text="{rate.value}"/>
<mx:dataservice id="dsRate" destination="fds.rate" message="handleMessage(event)" />