Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
Another possibility for multiserver session management utilizes the JavaSpaces API (for documentation, see Resources) to maintain records of the session objects. However, if the machine hosting the JavaSpace were to go down because of crashing or maintenance, all session information would be lost. So again, we are left with a single point of failure.
To accomplish the distributed session server with n-nodes, we must address three main problems:
The repository we will use to store the session information is an implementation of the Mnemosyne interface (named after the Greek goddess of memory and mother of the muses). An object that implements Mnemosyne is responsible for managing all objects in the repository. Any other object that wants to write, retrieve, or remove objects
in the repository must call a method of the Mnemosyne.
To be saved to a Mnemosyne, an object must implement the Memory interface, which defines the equalsMemory()operation for determining whether two memory objects are equivalent. That allows the Mnemosyneto figure out what object should be returned on a read or a take request. The Memory interface also extends Serializable so that you can use RMI to transmit the object across the network.
A Mnemosyne uses three other interfaces to represent its state:
CommonContext interface will store all information for the Mnemosyne. Each Mnemosynewill have one instance of a CommonContextobject to allow for synchronization between methods when reading, writing, and taking Memoryobjects. For writing and taking, the CommonContextdefines both "silent" and "loud" methods. The silent methods are used when objects need to be added without any event notifications.
For example, when a Mnemosynereceives a WriteRemoteEvent (a notification that an object has been written to a remote Mnemosyne), it will want to write another object to the CommonContext. However, it doesn't need to notify the other remote Mnemosynes; the original Mnemosynehas notified them. So the write is done "silently" by calling the CommonContext's silentWrite()method. The "loud" methods give details of the event to any interested listeners that are called when an object is first put
into the context.
Transaction interface allows for distributed transactions when reading, writing, or taking Memoryobjects. That means multistep operations can occur on the Mnemosyne.
TransactionContext interface manages a distributed transaction. That makes it possible to abort or commit transactions.
Keeping Mnemosynes synchronized is accomplished with two methods defined by the Mnemosyne: synchronize()and notify(). synchronize()is intended to get a local Mnemosyne"in sync" with a Vector of other Mnemosynes. (Those Mnemosynes may be local or remote, but for the sake of clarity, we will assume they are remote.) A sample implementation of the synchronize()method (from the MnemosyneImplclass) is displayed below. (See Resources for the complete sample code to this article.)
public void synchronize(Vector Mnemosynes)
throws RemoteException, TransactionException
{
// ...
// The MatchAllMemory object is a utility class that
returns true when
// compared against any Memory object
MatchAllMemory matchAllMemory = new MatchAllMemory();
// Obtain all Memory's from the Primary
Mnemosyne Mnemosyne = (Mnemosyne) Mnemosynes.firstElement();
Vector allMemories = Mnemosyne.readAll(matchAllMemory,null);
// Write all Memory's silently as there is no need
// to notify write listeners
commonContext.silentWriteAll(allMemories);
// Register to send and receive events
Enumeration enumeration = Mnemosynes.elements();
while(enumeration.hasMoreElements())
{
Mnemosyne nextMnemosyne = (Mnemosyne) enumeration.nextElement();
// Register to obtain notification
nextMnemosyne.addTakeRemoteEventListener(this, matchAllMemory);
nextMnemosyne.addWriteRemoteEventListener(this, matchAllMemory);
// Register to send notification
addTakeRemoteEventListener(nextMnemosyne, matchAllMemory);
addWriteRemoteEventListener(nextMnemosyne, matchAllMemory);
}
// ...
}The local Mnemosyne object reads all of its Memoryobjects of the first Mnemosyne in the Vector, and silently writes them to its CommonContextobject. Next, the local Mnemosyneadds itself to all remote Mnemosynes, as both a TakeRemoteEventListenerand a WriteRemoteListener. That means that any takes or reads on the remote Mnemosynes will result in a call to the local Mnemosyne's notify() method. Finally, the local Mnemosyne adds the remote Mnemosyneto its list of TakeRemoteEventListeners and WriteRemoteListeners. This ensures that any write or take calls will notify the remote Mnemosyne.
Now our synchronized local Mnemosyne object needs to update all other Mnemosynes whenever a Memoryobject is added or removed. You can accomplish that with the notify() method. Whenever a write or take event occurs, a Mnemosyne calls the notify()method of all appropriate listeners for the event. In the synchronize() method, you register the local Mnemosyne as a listener for take and write events on all remote Mnemosynes. If such an event occurs on any of those remote Mnemosynes, the local Mnemosyne's notify() method will be called. When that happens, the local Mnemosyne must respond to the event. Below is an example of how the Mnemosynecan synchronize itself with the remote Mnemosyne:
public void notify(RemoteEvent remoteEvent) throws RemoteException
{
// Write the written Memory to self, but no need to notify all of the
// Mnemosynes
if(remoteEvent instanceof WriteRemoteEvent)
{
WriteRemoteEvent wre = (WriteRemoteEvent) remoteEvent;
commonContext.silentWrite(wre.getMemory());
}
// Take the written Memory from self, but no need to notify all of the
// Mnemosynes
if(remoteEvent instanceof TakeRemoteEvent)
{
TakeRemoteEvent tre = (TakeRemoteEvent) remoteEvent;
commonContext.silentTake(tre.getMemory());
}
}A Mnemosyne has now been set up that can hold memory objects, synchronize itself with remote Mnemosynes, and keep itself up to date if any remote Mnemosynes gain or lose a Memory object.
To manage HTTP sessions using Mnemosynes, a servlet creates an instance of HttpSession (using the getSession()method from HttpServletRequest), wraps the session in a class that implements Memory (in this example, it is called SessionWrapper), and writes the wrapper class to a Mnemosyneby calling the Mnemosyne object's write() method.
By calling the write() method, the Memoryobject that wraps the session is serialized, sent down the network to the Mnemosyne, and instantiated on the remote machine. When the Memory object is written to the Mnemosyne, a WriteRemoteEventis sent to all WriteRemoteEventListeners registered with the Mnemosyne. This allows all other Mnemosynes to add the new object to their repository as Mnemosynes.
To look up a stored session, a servlet calls the read()method to look for the Memory object that contains the session. If the Mnemosyne finds the object, the object is sent via RMI back to the servlet server.
Finally, to remove the session, the servlet would call the Mnemosyne's take() method. The Mnemosynewould send back the Memory object just like it does on the read, but the object would also be removed from the repository. Also, a TakeRemoteEvent would be sent out to all TakeRemoteEventListeners. That would notify all remote Mnemosynes of the Memoryobject's removal.
Now that we have shown how the repository of objects will be maintained on multiple servers, we will show you how to build an implementation of a session server. On initialization, a session server does the following:
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq