Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Take control of the servlet environment, Part 3

Beware of the cookie monster

  • Print
  • Feedback

Page 3 of 6

    public void addCookie( Cookie cookie )
    {
        if( null != _request ) // debugging
        {
            if( null != cookie ) // naughty servlet
            {
                Cookie warped =
                    new Cookie(
                        Util.getPrefix( _request ) + cookie.getName(),
                        cookie.getValue() );
                warped.setMaxAge( cookie.getMaxAge() );
                super.addCookie( warped );
            }
        }
    }


The RequestWrapper strips off the domains at the servlet's request. It also discards any cookies that lack the expected prefix; now, the servlet will not receive two cookies with the same name.

Our version of the RequestWrapper overrides the getCookies() method to iterate through the superclass's set of cookies, stripping off the prefixes and discarding unexpected cookies; it then returns the clean versions:

    public Cookie[] getCookies()
    {
        Vector list = new Vector();
        Cookie[] cookies = super.getCookies();
        if( null != cookies )
        {
            String prefix = Util.getPrefix( super );
            for( int x = 0; x < cookies.length; x++ )
            {
                if( ( null != cookies[x] )
                 && ( cookies[x].getName().startsWith( prefix ) ) )
                {
                    String name = cookies[x].getName();
                    String value = cookies[x].getValue();
                    Cookie warped =
                        new Cookie(
                            name.substring( prefix.length(),
                                            name.length() ),
                            value );
                    warped.setMaxAge( cookies[x].getMaxAge() );
                    list.addElement( warped );
                }
                else
                {
                    // skip it (sub- or super- domain cookie bug)
                }
            }
        }
        Cookie[] gold = new Cookie[ list.size() ];
        list.copyInto( gold );
        return( gold );
    }


That sums up the power and versatility of RSEF. The icing on the cake is that you can seamlessly combine this cookie fix with the database storage solution discussed in Part 2, taking advantage of both. The bootstrap servlet discussed in Part 1 helps you achieve this combination of features.

Back in session

Now that you have a firm grasp on cookies, let's use them to improve the session wrapper discussed in Part 2. If, for some reason, you do not have access to a centralized database for storing your session data, you can store it in the client's cookies. This approach features some advantages; for example, no server-side storage (i.e., database) or server-side garbage collection (expired sessions) are required. However, the session data must transfer from the browser to the server each time a request is issued, and back again when the page is served.

One cookie at a time

The simplest and easiest way to implement the session-stored-in-cookies solution is to use a separate cookie for each name-value pair of session data. In the downloadable source code, available in Resources below, you'll find the class net.rudiment.servlet.session.cookie.SessionWrapper that performs such logic.

In order to differentiate the session-related cookies from other cookies, you will prefix the cookie names with some arbitrary value. The wrapper class contains a simple utility method for this:

    private static final String prefix = "session/";
    private String mangle( String name )
    {
        return( prefix + name );
    }


When placing a piece of data into the session, the wrapper mangles the name and writes it to a cookie:

    public void putValue( String name, Object value )
    {
        String ser = Serialize.objectToString( value );
        Cookie cookie = new Cookie( mangle( name ), ser );
        cookie.setMaxAge( -1 );
        _response.addCookie( cookie );
        // cache it in case it is referenced again
        // during this servlet execution
        super.putValue( name, value );
    }


(Note: The Serialize tool referenced above, and later on, stretches outside the scope of this article. The tool utilizes object I/O streams in conjunction with byte array I/O streams to convert an object into an array of bytes, or vice versa. Then, the byte array is Base64 encoded or decoded and will pass safely between the browser and the server.)

  • Print
  • Feedback

Resources
  • Books