elare Technologies’ ATCT (Asynchronous Transfer of Control Threading) is a versatile new programming library that implements a “separation of concerns” approach?one of the key precepts of aspect-oriented programming?to enable programmers and framework developers to create scalable systems capable of complex execution paths with very simple source code.
This article presents two specific situations in which ATCT makes the developer’s job easier, asynchronous messaging and Java scripting. Applied to asynchronous messaging, it simplifies the structure of the code and makes it linear. Applied to scripting engines, ATCT overcomes a current limitation of the JVM. Finally, some internal details about the library are provided with a look under the hood.
ATCT and Asynchronous Messaging
Today, most asynchronous messaging technologies use some form of callback mechanism. Programmers implement one or more interfaces that define a behavioral contract with the underlying messaging engine. When the proper circumstances arise, the engine calls into the client code via a method designated for that purpose. One very popular Java messaging technology is JMS. In the case of JMS 1.1, the interface is called
MessageConsumer and the method is
onMessage(). The JMS specification guaranties that your code is invoked for each incoming message.
Figure 1 shows a sequence diagram that illustrates a generic asynchronous messaging call sequence. The concept applies, but is not limited, to JMS as the messaging engine. Other possible asynchronous messaging technologies include the upcoming SOAP 1.2.
|Figure 1: Typical Sequence Diagram for an Asynchronous Messaging System|
To better understand Figure 1, think of Step 3:
verifyCreditCard() as a request that the back end of an online travel agent would issue prior to authorizing an airplane ticket purchase. A real-life business process might include the additional steps of checking the customer’s rewards point account balance or the availability of sufficient funds. This messaging approach affects the structure of the code. Firstly, it splits the process controller code: one portion sends the request while the second processes the response. Secondly, it requires glue code to maintain some internal state data between successive calls to the messaging engine. This generally takes the form of a persistence store that tracks the details of pending transactions until the response messages are received. The store itself can be anything from a simple HashMap to a relational database.
Multiply the call sequence by the number of messages necessary to implement the complete business process and the code can rapidly become unmanageable. Enter ATCT. Using this technology, programmers can turn the code showed in Listing 1 into the more maintainable code in Listing 2. The entire business process now resides inside one single method. But more importantly, Listing 2 hides the complexity of dealing with the underlying asynchronous system (see Figure 2 for an ATCT version of the sequence diagram in Figure 1). The new code is linear, flowing from one step to the next sequentially, even though some of the method calls wrap around complex asynchronous call sequences. (View the accompanying source code for more details. Although not a working sample, it illustrates the concepts described in this section.)
|Figure 2: ATCT Sequence Diagram for an Asynchronous Messaging System|
The next section covers how using ATCT with new enhancements to the JVM extends current scripting engines.
ATCT for Scripting Engines
The simplicity and wide cross-platform availability of the JVM have spawned many alternative languages that target it as their run-time environment. Some languages are native compilers that directly generate bytecode, while the others are run-time interpreters. Two types of interpreters exist: the ones that implement their own internal execution stack and those that rely on the JVM’s internal stack. However, all these languages share a common limitation inherent to the JVM itself: no way to control the execution stack of the Java bytecode interpreter. Consequently, the interpreters that rely on the JVM cannot offer continuation: the ability to suspend/resume a method’s execution at will. Continuation is a fundamental requirement for scripting a series of asynchronous events.
The programmers of the Apache Cocoon framework are keenly aware of this limitation and discussed it at length. Their powerful Web development framework allows the creation of Web sites using XML documents. It also includes the interesting ability to control the flow between a series of Web pages using a simple script interpreted at run time. This functionality relies on the scripting engine’s ability to support continuation. The JVM’s lack of support for this feature drastically limits the choice of scripting languages that developers can use with Cocoon or in any other similar situation.
To be able to suspend/resume the execution of bytecode would require storing the following state information about the JVM:
Currently, Sun offers no direct way to access the execution state. ATCT is the first portable technology to offer unrestricted Java continuation. Curious about how Velare solved this problem? The next section breaks it down.
Under the ATCT Hood
Java owes part of its success to some key features, including:
Unlike many of the other standard Java objects, Sun unfortunately did not make the
Thread class serializable, preventing developers from saving the JVM’s execution context.
ATCT provides an elegant and powerful solution to the continuation and serialization problems. Its
ATCThread class contains a complete bytecode interpreter with its own private execution context. This solution is pure Java and portable across virtual machines. Effectively working as a secondary interpreter,
ATCThread uses reflection to draw on the JVM for much of its core services while supplementing it with the following:
ATCThread provides the following methods to completely control the execution of bytecode in the secondary interpreter:
start(): starts the execution of a method in the secondary interpreter, using an internal Thread
suspend(): pauses the secondary interpreter. While it is in that suspended state, a developer can serialize the interpreter to a file and store it indefinitely.
resume(): resumes execution of the bytecode in the secondary interpreter
ATCT offers another way to momentarily suspend the
ATCThread interpreter: declare a method as throwing an
ATCSignal exception. When the ATCT interpreter runs into an invocation of that method, it simply ignores the method body and returns control to the native interpreter. Called from the native JVM interpreter, the same method body would be executed normally. Similarly, ATCThread uses the
AISignal exception to discriminate the code that it should execute.
This tried and tested code-marking technique is already familiar to EJB and RMI developers. If it is not flexible enough for your situation, the ATCT API lets you implement custom discrimination heuristics. The upcoming Java 1.5 will offer an interesting alternative scheme with its new declarative programming style.
ATCT Adds Features to Java
Velare Technologies is adding some interesting new features to core Java with ATCT. The library simplifies the programmer’s job in the two areas reviewed in the previous sections. Other possible uses include game scripting engines (using continuation), a simple failover scheme, grid computing, and the creation of some simple agent frameworks where an
ATCThread could be sent across the network and deserialized on a different JVM.