3.2. Desarrollo de la propuesta
3.2.3. Criterios de evaluación
The PacketQueue class is a basic data structure class with a limited set of responsi- bilities. However, it ser ves as a focal point for the flow of information in the server. Packets from the server’s many clients fan in to the PacketQueue. The
Packets are then fanned out to the packet handlers according to the packet’s ele- ment name. Many threads of operation will be active at once in the server and all of them synchronize on the PacketQueue and the packets within it.
COMMAND PROCESSOR DESIGN PATTERN
For those familiar with design patterns, our packet handling system is a minor variation on the Command Processor design pattern.9
“The Command Processor design pattern separates the request for a service from its execution. A command processor component manages requests as separate objects, schedules their execution, and provides additional services such as the storing of request objects for later undo.”
In our Jabber server, the XML parser acts as the command controller accepting requests (our XML stream) and converting them into commands (our Packet
objects). The QueueThread acts as the command processor taking the packets and scheduling their execution. Unlike the command processor design pattern how- ever, the Packets don’t handle their own execution. Instead our packet handler classes act as dual-function command processor suppliers and command proces- sors to provide the entire Packet processing functionality.
The benefits of the command processor pattern apply to our design as well, and they are:
■ Flexibility in the way requests are activated—Supporting alternative activation meth-
ods makes it easier to bridge our Jabber server to other messaging systems.
■ Flexibility in the number and functionality of requests—Especially important with
the rapidly changing Jabber protocols.
■ Programming execution-related services—In particular, we can easily log pack-
ets and replay Jabber sessions by making minor modifications to the
QueueThread.
9 Buschmann et al, Pattern-oriented Software Architecture: a System of Patterns (John Wiley & Sons, 1996),
p. 277. The Command Processor pattern is also covered in Design Patterns: Elements of Reusable Object- Oriented Software (Addison-Wesley, 1994), by Gamma et al, and is referred to in that text as the Com- mand pattern.
78 CHAPTER 3
IM concepts and Jabber protocols
■ Testability at application level—The QueueThread is an excellent point of
entry into the system for testing the XML parsing as well as packet han- dling parts of the server. Once again, the ability to log and replay sessions can be a big help.
■ Concurrency—Packets and their handling is a relatively isolated computa-
tion. The QueueThread can easily distribute processing by handling packets
in parallel threads of execution.
The commander processor pattern has some liabilities, however:
■ Efficiency loss—Converting data formats and providing intermediate process-
ing steps requires additional computation time and storage.
■ Potential for excessive number of command classes—We avoid this issue for the
most part by representing all packets with a single, generic Packet class. We pay for the simplicity in reduced efficiency of the general representation. In addition, a generic Packet class can represent an infinite number of packet classes. Our server has to create extra logic to resolve which packet we’re dealing with (a <message> packet, <presence> packet, etc.)
The PacketQueue (figure 3.3) must:
■ Store Packets—Accept Packet objects pushed onto the back of the Packet-
Queue, maintaining the order of items pushed.
■ Retrieve Packets—Allow Packet objects to be pulled off the front of the Pack-
etQueue, removing the item.
■ Be thread-safe—Allow multiple threads of execution to push and pull Packets
from the PacketQueue without problems.
■ Provide thread synchronization—If the PacketQueue is empty, attempting to
pull Packets from the front will cause the caller to wait (block) until a new Packet is pushed onto the back of the queue or the thread is interrupted. Threads can use this feature to synchronize their actions and conser ve server resources.
Threads that operate on Packet objects can do so efficiently by pulling Packet
objects from the PacketQueue in an infinite loop. The PacketQueue itself will
make sure that these worker threads only execute when there are available Pack- ets in the PacketQueue
XML parsing subsystem 79
The implementation of the PacketQueue is extremely simple. A java.util .LinkedList object is used to store the Packets10 and a sprinkling of Java thread primitives is added to support the server’s multithreaded environment.
In listing 3.4 I have highlighted the thread support code in bold. Notice that the methods push() and pull() are synchronized to protect them from being executed by overlapping threads. Ever y push() method call causes notify- All()to wake up any threads waiting on a pull() method call. The pull()
method blocks on its internal wait() method call while the queue is empty.
public class PacketQueue {
//Actual storage is handled by a java.util.LinkedList LinkedList queue = new LinkedList();
public synchronized void push(Packet packet){ queue.add(packet);
notifyAll();
}
public synchronized Packet pull(){ try {
while (queue.isEmpty()) {
10 The Java library contains many excellent classes that will save you from reinventing the wheel. It is well
worth your time to familiarize yourself with it.
Listing 3.4 The PacketQueue class
p p p p p Figure 3.3
The PacketQueue accepts packets from parallel XML parsing streams, and feeds parallel packet handlers.
80 CHAPTER 3
IM concepts and Jabber protocols
wait();
}
} catch (InterruptedException e){ return null;
}
return (Packet)queue.remove(0); }
}
The loop is necessary because push() calls notifyAll(), waking up all threads waiting on pull(). If only one Packet is pushed onto the queue, the first thread to
execute will remove the Packet from the queue. All the other waiting threads will then run (they won’t run simultaneously because pull() is synchronized), the
queue will be empty, and they will have to block on the wait() call again until the next Packet arrives.
If you don’t understand Java threading code you can trust that this works, write some test code to verify it, or learn more about Java threads. I have tried to keep the amount of threading code to a minimum in the book’s source code but server code tends to be heavily threaded. If you wish to learn more about threads, there are several excellent books about Java threads. In addition, the JavaSoft online documentation (java.sun.com) provides a free tutorial on using Java threads.
Now that we’re ready to take care of XML parsing using the JabberIn- putHandler class.