Example 8-5. Session-tracking code
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
// retrieve current settings from the session
HttpSession session = req.getSession(true);
Cart cart = (Cart) session.getAttribute("shoppingCart");
if (cart == null) {
cart = new Cart( );
session.setAttribute("shoppingCart", cart);
}
// produce the DOM tree
Document doc = CartDOMProducer.createDocument(cart);
// prepare the XSLT transformation
Transformer trans = StylesheetCache.newTransformer(
this.xsltFileName);
// allow cookieless session tracking
if (!req.isRequestedSessionIdFromCookie( )) {
String sessionID = session.getId( );
trans.setParameter("global.sessionID",
";jsessionid=" + sessionID);
}
// send the web page back to the user
res.setContentType("text/html");
trans.transform(new javax.xml.transform.dom.DOMSource(doc),
new StreamResult(res.getWriter( )));
} catch (ParserConfigurationException pce) {
throw new ServletException(pce);
} catch (TransformerConfigurationException tce) {
throw new ServletException(tce);
} catch (TransformerException te) {
throw new ServletException(te);
}
}
The critical lines of code are emphasized. The first of these checks
to see if the session was not obtained using a cookie:
if (!req.isRequestedSessionIdFromCookie( )) {
For the very first request, the cookie will not be present because
the servlet has not had a chance to create it. For all subsequent
requests, the cookie will be missing if the user has disabled cookies
in the browser. Under either scenario, the session identifier is
obtained from the HttpSession instance:
String sessionID = session.getId( );
The servlet API takes care of generating a random session identifier;
you are responsible for preserving this identifier by passing it as a
parameter to the stylesheet. This is done as follows:
trans.setParameter("global.sessionID",
";jsessionid=" + sessionID);
This servlet also takes the liberty of prefixing the session
identifier with ";jessionid=". This makes the XSLT
stylesheet simpler, because it does not have to check if the session
ID is an empty string or not. As implemented here, the value of
global.sessionID can be appended to all URLs:
<a href="/whatever{$global.sessionID}">click here</a>
Example 8-6. Session-tracking XSLT stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
*********************************************************************
** global.sessionID : Used for URL-rewriting to implement
** session tracking without cookies.
******************************************************************-->
<xsl:param name="global.sessionID"/>
<!-- This stylesheet produces XHTML -->
<xsl:output method="xml" indent="yes" encoding="UTF-8"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<!--
*********************************************************************
** This template produces the skeletal XHTML document.
******************************************************************-->
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Shopping Example</title>
</head>
<body>
<!-- Create a form for this page -->
<form method="post" action="/chap8/shopping{$global.sessionID}">
<h1>Shopping Example</h1>
...remainder of page omitted
</form>
</body>
</html>
</xsl:template>
<xsl:template match="cart">
Click on the link to move next:
<a href="/shopping/moveNext{$global.sessionID}?param=value"/>Move Next</a>
...
</xsl:template>
</xsl:stylesheet>
This stylesheet fully illustrates the three key components that make
session tracking with XSLT possible. First, the session identifier is
passed to the stylesheet as a parameter:
<xsl:param name="global.sessionID"/>
Next, this session identifier is used for the form action:
<form method="post" action="/chap8/shopping{$global.sessionID}">
And finally, it is used for all hyperlinks:
<a href="/shopping/moveNext{$global.sessionID}?param=value"/>Move Next</a>
The ?param=value string was added here to
illustrate that request parameters are appended after the session
identifier. Therefore, the full URL will look similar to the
following when the user clicks on the hyperlink:
http://localhost:8080/shopping/moveNext;jsessionid=298ulkj2348734jkj43?param=value