Class JDBCSession
Database sessions enable front-end webservers to scale easily. (No messy/brittle session migration hacks are required !). Scaling can be near infinite, but after a point (say 100 front ends), the back-end databases may also have to be partitioned (and the appropriate partition/machine invoked for a given session-id).
Note, memory sessions are not needed even for maintaining html form-state
because each form's state can be uniquely created from an initial form
state (common to all users) along with the per-usr data submitted per
request. This is exactly how the form
API works.
However, memory sessions are useful for certain transient things/caches
or for very quick'n'dirty apps, where using a database is more trouble
than it's worth.
Given fast ethernet connections and forward marching processor/peripheral speeds, JDBC session data is typically retrieved on the order of 1-2 milliseconds (or even lesser).
Using this class requires the following database table schema in the database:
create table sessiondata ( session_id varchar(50), name varchar(100) not null, value text -- [or some other character/text type] ); create table sessionmaster ( session_id varchar(50) primary key, -- the session id created timestamp not null, -- session create time accessed timestamp not null, -- session last accessed is_expired bool default 'f', -- true if expired -- a reference to the user table that associates a user_id -- with one or more session_id's. Optional so should be -- nullable if used. user_id <SQL_TYPE_FROM_YOUR_USER_TABLE> ); alter table sessiondata add FOREIGN KEY (session_id) REFERENCES sessionmaster (session_id) on delete cascade; -- The following if a user table is present alter table sessionmaster add FOREIGN KEY (user_id) REFERENCES NAME_OF_USER_TABLE;
When creating these tables, it is also advisable to index the session_id and user_id columns for faster performance.
The above tables can also be created by this class itself. Invoke the main method without any arguments to see usage information. The table names sessionmaster and sessiondata come from final static variables in this class. If you want to use different names, change these variables and recompile this class.
More than one [name, value] pair can be stored in the sessiondata table. This class will automatically store [name, value] pairs as seperate rows and can return a particular [name, value] pair or all [name, value] pairs for the specified session.
Note: This class allows saving data only as Strings/text. However, arbitrary binary data can also be stored but the caller should first base64 encode that data and then save it as a string. Upon retrieval, that data can be base64 decoded.
Note 2: Under some scenarios, it is important to have a separate cleaner process that periodically deletes expired sessions from the database. This process should run via cron, some other stand-alone java code etc., and should delete sessions which are marked expired or whose create_time - last_used_time is greater than the session expiry time. Under other scenarios, sessions may be deleted after a set amount of time from the creation data regardless of when the session was last accessed.
Note 3: Typically, expired session data is simply deleted from the session
tables in the database. (for example, amazon.com users have to persist
their cart manually by clicking on a "save-for-later" button - which moves
data to more persistent tables -- otherwise their cart session is deleted
from the database when the session expires). It is however possible that
instead of deleting sessions, the sessions are instead marked as "expired"
but not deleted from the database. (this is done via the setDeleteExpiredSessions(boolean)
method.
-
Nested Class Summary
Nested Classes -
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptionvoid
add
(Connection con, String sessionID, String key, String value) Saves the tuple [sessionID, key, value] in the database.void
addAll
(Connection con, String sessionID, Map data) Adds all [key, value] pairs in the specified map to the session with the specified sessionID.void
create
(Connection con, String sessionID) Creates a new session.void
create
(Connection con, String sessionID, String userID) Creates a new session.static void
createJDBCTables
(Connection con, String userTableName, boolean mysql) Creates database tables for storing session data.void
delete
(Connection con, String sessionID, String key) Deletes both the key and value specified by the sessionID and key.boolean
exists
(Connection con, String sessionID) Returns true is the specified sessionID is valid (i.e., the specified sessionID exists in the database and has not expired).void
expire
(Connection con, String sessionID) Expires the session.void
Utility method that deletes (or marked as expired depending onsetDeleteExpiredSessions(boolean)
) all sessions in the database that have exceeded the maximum inactive time.get
(Connection con, String sessionID, String key) Returns the value associated with the specified sessionID and key.getAll
(Connection con, String sessionID) Returns a map of all [key, value] pairs associated with the specified sessionID.int
Returns the current expire interval (seconds after which sessions can be considered eligible for removal).getForUser
(Connection con, int userID) Same asgetForUser(Connection, String)
but takes a numeric userID.getForUser
(Connection con, String userID) Returns a List containingsession information
about all sessions associated with the specified ID.static JDBCSession
Returns an instance of JDBCSession.static JDBCSession
getInstance
(Log logger) Returns an instance of JDBCSession.static void
void
put
(Connection con, String sessionID, String key, String value) An alias for the#add
method.void
putAll
(Connection con, String sessionID, Map data) An alias for theaddAll
method.sessionInfo
(Connection con, String sessionID) Returns session information from the session master table.void
setDeleteExpiredSessions
(boolean val) By default expired sessions are deleted from the db.void
setExpireTime
(int seconds) Sessions inactive for greater than these number of seconds will be eligible for expiry.void
tieToUser
(Connection con, String sessionID, String userID) Associates the specified sessionID with the specified userID.update
(Connection con, String sessionID, String key, String newvalue) Updates the value for the specified sessionID and key in the database.
-
Field Details
-
SESSIONDATA_TABLE
- See Also:
-
SESSIONMASTER_TABLE
- See Also:
-
-
Method Details
-
getInstance
Returns an instance of JDBCSession. -
getInstance
Returns an instance of JDBCSession.- Parameters:
logger
- the logging destination for methods in this class. Specify null to use a default logger.
-
setDeleteExpiredSessions
By default expired sessions are deleted from the db. If this is set to false, they are instead marked as expired in the db. -
create
Creates a new session.- Parameters:
con
- a jdbc connectionsessionID
- value for sessionID, theSessionUtil.newSessionID()
can be used to generate this. Should not be null. It is not recommended that the servlet container generated jsession_id cookie be used for this value. This sessionID is then later used to retrieve and work with the created session and this sessionID will typically be stored as a cookie or URL encoded on the client.userID
- a userID to associate with this session. Note, userID's in user tables are typically auto generated numerical sequences. Stringify numerical values before passing them into this method. This value should not be null, otherwise a runtime exception will be thrown.- Throws:
SQLException
- if a SQL error occurs. Note, also thrown if the session_id already exists in the database (since all session_id's must be unique).
-
create
Creates a new session. The specified session can later be optionally to a userID by invoking thetieToUser(Connection, String, String)
method.Note, sessionID's are typically be stored as a cookie or URL encoded on the client and are thus unique per browser/client). A user is not required to login to have session data.
- Parameters:
con
- a jdbc connectionsessionID
- value for sessionID, theSessionUtil.newSessionID()
can be used to generate this. Should not be null. It is not recommended that the servlet container generated jsession_id cookie be used for this value. This sessionID is then later used to retrieve and work with the created session.- Throws:
SQLException
- if a SQL error occurs. Note, also thrown if the session_id already exists in the database (since all session_id's must be unique).
-
expire
Expires the session. By default, deletes all session data associated with the specified sessionID from the database. IfdeleteExpiredSessions
is set to true, then the session is marked as expired in the database but the rows are not deleted from the db.Either way, after this method returns, the sessionID will not longer be valid.
- Throws:
SQLException
-
tieToUser
Associates the specified sessionID with the specified userID.Note: Depending on the application, more than 1 sessionID can be associated with the same userID in the session master table.
- Throws:
SQLException
-
expireInactiveSessions
Utility method that deletes (or marked as expired depending onsetDeleteExpiredSessions(boolean)
) all sessions in the database that have exceeded the maximum inactive time.- Throws:
SQLException
-
setExpireTime
Sessions inactive for greater than these number of seconds will be eligible for expiry.Note: these expired sessions will still not be expired until the
invalid reference
expireInactiveSessions()
Defaults to 8 hours (=60*60*8 seconds)
-
getExpireTime
Returns the current expire interval (seconds after which sessions can be considered eligible for removal). -
exists
Returns true is the specified sessionID is valid (i.e., the specified sessionID exists in the database and has not expired).Note: this method does not expire the session itself or check for non-expired validity. Sessions should be expired as/when needed by calling the
expire(java.sql.Connection,java.lang.String)
method.- Throws:
SQLException
-
sessionInfo
Returns session information from the session master table. This information is returned as ainvalid reference
info
Returns null if the given sessionID has expired and/or was not found in the database.
- Throws:
SQLException
-
getForUser
Returns a List containingsession information
about all sessions associated with the specified ID. Returns an empty list if no sessions are found for the specified userID.Note, the specified userID can be null in which case all sessions with null userID's will be returned.
- Throws:
SQLException
-
getForUser
Same asgetForUser(Connection, String)
but takes a numeric userID.- Throws:
SQLException
-
getAll
Returns a map of all [key, value] pairs associated with the specified sessionID. Returnsnull
if the specified sessionID is not found in the database or if the specified session has expired.- Throws:
SQLException
-
get
Returns the value associated with the specified sessionID and key.Returns null if the specified session has expired, or the specified key does not exist in the database or exists but contains a null in the database.
- Throws:
SQLException
-
delete
Deletes both the key and value specified by the sessionID and key. Does nothing if the sessionID or key does not exist in the database.- Throws:
SQLException
-
add
Saves the tuple [sessionID, key, value] in the database.The specified sessionID must exist and be valid in the database otherwise a SQLException will be thrown.
- Throws:
SQLException
-
addAll
Adds all [key, value] pairs in the specified map to the session with the specified sessionID.- Throws:
SQLException
-
put
An alias for the#add
method.- Throws:
SQLException
-
putAll
An alias for theaddAll
method.- Throws:
SQLException
-
update
public String update(Connection con, String sessionID, String key, String newvalue) throws SQLException Updates the value for the specified sessionID and key in the database.The specified sessionID and keys must exist in the database prior to calling this method,otherwise a SQLException will be thrown.
- Throws:
SQLException
-
main
-
createJDBCTables
public static void createJDBCTables(Connection con, String userTableName, boolean mysql) throws Exception Creates database tables for storing session data. This method can be called programmatically but is typically invoked by the main method. Invoke the main method without any flags to get usage information.- Throws:
Exception
-