What are lightweight services?
IBM Lightweight Services (LWS) are long-running, server-side programs developed in lightweight programming languages such as JavaScript. We consider JavaScript a lightweight language because its relative simplicity makes it easy to learn and use. It tends to be associated with DHTML, where it is used as an event-driven scripting language in Web pages. LWS uses JavaScript as a high-level, dynamic language to develop server-side processes with access to Web services, Sametime instant messaging, and high-performance publish/subscribe.
LWS is especially suited to developing personal services, or server side applications that operate on behalf of individual users. In recognition of this programming style, the term agent is used for a program installed on the server and agent instance for a running copy of that program. Agent instances are individually created and initialized, and can be configured to service different users with varying security attributes.
An agent consists of a script paired with information about the execution environment it requires, and metadata such as author and version information. When an agent is installed, these resources are copied to the server and stored in the LWS database. Clients can then create agent instances, each with its own configuration and program state.
Consider the following simple JavaScript program:
var phoneNumbers = new Object();
function setPhoneNumber(name, number) {
phoneNumbers[name] = number;
}
function getPhoneNumber(name) {
return phoneNumbers[name];
}
|
When the JavaScript code is initialized, the top-level property phoneNumbers is set with a generic object, which is used as a hash table. Notice that once the program is initialized, no code will execute until one of the two functions is invoked. Agent scripts do not have a "main loop" or a long-running sequence of top level commands. They consist of simple initialization code and JavaScript functions that act as event-handlers.
While this style of script is already familiar to Web page developers, LWS introduces some important new features. LWS provides a programming environment that's transactional and persistent -- important features for developing robust, fault-tolerant scripts to coordinate processes on the server. Later, you'll see how the JavaScript functions above can be called by a Web services client; when the functions are invoked they run within a WebSphere transaction. For example, if a JavaScript error were to occur in the setPhoneNumber function, any modifications to the phoneNumbers property would be rolled back, or undone.
The transactional variant of JavaScript is possible because the state of each agent instance is stored in a database between events. In addition to protecting against script errors, this means that a script's program state
remains valid across server failures. In the example above, the value of the phoneNumbers property will be preserved even after WebSphere is restarted.
Transactional JavaScript is useful for recovering from errors, but what about agents that communicate with non-transactional applications? An example would be Sametime instant messaging, where operations such as sending a message cannot be rolled back. To address this issue, LWS provides isolation from non-transactional resources. Most of the APIs available to agents are asynchronous, such that a result or error condition is processed by an event-handler in a new transaction. Because of this programming style, most operations can be delayed until the end of the current transaction. For example, if two Sametime messages are sent in the course of processing a JavaScript event, nothing is sent to the instant messaging server until the top level event-handler returns successfully. If a JavaScript error occurs, the messages are simply discarded.
Standard JavaScript (ECMAScript -- see Resources) defines a basic programming language, but doesn't contain a function for communicating with other applications. In a Web page, JavaScript is extended with objects that represent HTML elements and browser features. LWS provides JavaScript extensions for communicating by Web services, Sametime instant messaging, and high-performance publish/subscribe. For example, if a LWS developer specifies a dependency on the WebServices Extension, an object named WebServices is added as a top level property. This object exposes a JavaScript API for calling remote Web services and processing the responses.
The WebServices Extension is especially interesting because it lets agents act as both Web service consumers and providers. To consume services, or act as a Web services client, an agent script constructs request objects (with or without the aid of a Web Services Description Language (WSDL) file) and calls the remote server asynchronously.
To provide Web services, the LWS tooling lets developers export a set of JavaScript functions as Web service operations. Unlike methods in Java, a JavaScript function's parameters do not specify type information. However, you can append this information in LWS, allowing JavaScript functions to accept and return specific SOAP types. Figure 1 below shows how to expose a function as a Web service in the LWS perspective for WebSphere Studio Application Developer.
Figure 1. Exposing a function as a Web service
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
This article focuses on developing services in JavaScript, but LWS also supports multiple runtimes. A runtime is responsible for executing code and storing the program state for agent instances, and is selected by the agent developer when creating a new LWS project. LWS includes a JavaScript-specific runtime based on the Mozilla Rhino engine (see Resources), and a runtime based on IBM's Bean Scripting Framework (BSF -- see Resources). The Rhino Runtime supports advanced features such as JavaScript constructors and DHTML-style event handlers, while the BSF Runtime provides a choice of several scripting languages. Note that both runtimes support JavaScript, but scripts developed for the two runtimes have a number of differences. The LWS distribution also includes BSF examples developed in interpreted Python.
LWS is especially well suited to interacting with users, whether you're developing workflow escalation agents, a CRM system, or other user-centric applications. In these scenarios, a developer would typically install an agent to handle a specific process or task. An enterprise application would then create a new instance of that agent for each user or instance of a process, supplying configuration data detailing its specific task.
You can use the phone book script above to quickly prototype a service that might otherwise be implemented using Enterprise JavaBeans technology. You can also use LWS to complement conventional WebSphere applications with functions not generally available in J2EE 1.2, including:
- Self-scheduling (creating timers that periodically trigger script events)
- Invoking Web services asynchronously
- Logging into Sametime instant messaging servers.
Because of these features, LWS makes it easy to script together Web service client operations. A simple agent can dispatch multiple Web service requests simultaneously, accumulate the results, notify users, and take corrective action when operations fail.
LWS includes a new perspective for IBM WebSphere Studio Application Developer, which lets users rapidly modify, install, and debug agents. Because of the way agent instances are stored, installing or modifying an agent does not require any modifications to the underlying database schema. The Install button in Figure 2 below completes, within a few seconds, the following tasks:
- Removes any instances of the agent created earlier in this debug session.
- Installs (or reinstalls) the agent on the remote LWS server.
- Creates a new agent instance with the specified configuration information.
- Opens a command-line window for interacting with the new agent instance.
- Opens a new log window for monitoring the debug output of the new instance.
Figure 2. Installation view
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
For the phone book service example, you can immediately test your agent code using the Command Line view. When the user enters a JavaScript expression, it is evaluated on the server within the context of the selected agent instance and in a new transaction. Once you've confirmed that your functions work as expected, you would try to invoke the agent instance as a Web service. The release of LWS on alphaWorks (see Resources) contains tutorials on this and other development tasks.
I hope you'll find LWS useful for rapidly prototyping services and integrating J2EE applications with asynchronous, non-transactional middleware such as Lotus Sametime instant messaging. If you're interested in evaluating LWS you can download the server, development tools, and documentation from IBM's alphaWorks Web site (see Resources). The alphaWorks release contains several tutorials for developing agents.
See Part 2 of this series, "Extending J2EE with script-based agents," to learn how to extend a conventional J2EE enterprise application to include lightweight services and how to create and manage an agent instance for each user of the system.
- Learn more about the release of IBM Lightweight Services on alphaWorks.
- Read Part 2 of this series, "Extending J2EE with script-based agents."
- Browse the language specifications for ECMAScript.
- Explore the Mozilla Rhino JavaScript engine.
- Check out IBM's Bean Scripting Framework (BSF).
- Get technical information about developing with Lotus Sametime from Lotus Developer Domain.
- Learn more about WebSphere Studio Application Developer or download the trial version of WebSphere Studio Application Developer Version 4.0.3. And visit WebSphere Developer Domain while you're looking!
Christopher Vincent is a software engineer on the Internet Technology Team, IBM Server Group. His research interests include instant messaging, publish/subscribe infrastructure, rapid application development, and dynamic programming languages. He received M.Eng. and B.S. degrees from MIT, where he worked at the MIT Artificial Intelligence Laboratory. You can contact him at crv@us.ibm.com.