Make room for JavaSpaces, Part 1

Ease the development of distributed apps with JavaSpaces

This article begins a second thread of the Jiniology series. In June, Bill Venners launched Jiniology with an overview of Jini technology -- a powerful new infrastructure for building and deploying distributed systems that are organized as federations of services. This thread, which will be featured every other month in this column, focuses on JavaSpaces, a core Jini service from Sun Microsystems that provides a high-level means of creating collaborative and distributed applications. If you're building applications with Jini, you'll want to know how to use JavaSpaces to coordinate the participants in a Jini federation. But it's also important to remember that you can use JavaSpaces separately from Jini, as a tool for building general distributed systems in Java. In either case, JavaSpaces is worth a look, because it can significantly ease the design and coding of distributed applications.

In this series, we will begin by introducing you to the unique JavaSpaces programming model, which is quite different from other network and distributed tools with which you might be familiar. In subsequent articles, we will cover the details of the JavaSpaces API and how you can use it to glue processes together into a distributed application, and describe how JavaSpaces interacts with other components of Jini. Throughout the series, you'll see that JavaSpaces is simple (the API consists of only a handful of operations), expressive (a large number of problems can be solved using JavaSpaces), and powerful (you can build sophisticated distributed systems with small amounts of JavaSpaces code).

Let's get started.

A new distributed computing model

Building distributed applications with conventional network tools usually entails passing messages between processes or invoking methods on remote objects. In JavaSpaces applications, in contrast, processes don't communicate directly, but instead coordinate their activities by exchanging objects through a space, or shared memory. A process can write new objects into a space, take objects from a space, or read (make a copy of) objects in a space; Figure 1 depicts several processes (represented by Dukes) interacting with spaces using these operations. When taking or reading objects, processes use simple matching, based on the values of fields, to find the objects that matter to them. If a matching object isn't found immediately, then a process can wait until one arrives. In JavaSpaces, unlike conventional object stores, processes don't modify objects in the space or invoke their methods directly -- while there, objects are just passive data. To modify an object, a process must explicitly remove it, update it, and reinsert it into the space.

Figure 1. Processes use spaces and simple operations to coordinate activities Copyright Sun Microsystems, Inc.

Spaces are object stores with several important properties that contribute to making JavaSpaces a powerful, expressive tool. Let's take a closer look:

  • Spaces are shared: Many remote processes can interact with a space concurrently -- the space itself handles the details of concurrent access, leaving you to focus on the design of the high-level protocols between your processes.

  • Spaces are persistent: Spaces provide reliable storage for objects. When you store an object in a space, it will remain there indefinitely until it is removed. You can also request a lease time during which an object should be stored. Once stored in the space, an object will remain there until its lease time (which can be renewed) is over, or until a process explicitly removes it. We will discuss leases in more depth later in this series.

  • Spaces are associative: Objects in a space are located via associative lookup, not by memory location or by identifier. Associative lookup provides a simple means of finding the objects in which you're interested according to their content, without having to know what the object is called, who created it, or where it is stored. To look up an object, you create a template (an object with some or all of its fields set to specific values, and the others left as null to act as wildcards). An object in the space matches a template if it matches the template's specified fields exactly. You'll see that, with associative lookup, you can easily express queries for objects such as "Are there any tasks to compute?" or "Are there any answers to the prime factor I asked for?"

  • Spaces are transactionally secure: JavaSpaces makes use of Jini's transaction service to ensure that an operation on a space is atomic (either the operation is applied, or it isn't). Transactions are supported for single operations on a single space, as well as multiple operations over one or more spaces (either all the operations are applied, or none are). As you will see later in the series, transactions are an important way to deal with partial failure.

  • Spaces let you exchange executable content: While in a space, objects are just passive data -- you can't modify them or invoke their methods. However, when you read or take an object from a space, a local copy of the object is created. As with any other local object, you can modify its public fields and invoke its methods, even if you've never seen an object like it before. This capability gives you a powerful mechanism for extending the behavior of your applications through a space.

As this series progresses, we will show you how these properties play a key part in letting you create distributed applications that work well in the Jini environment, where networking is often spontaneous, and processes join and leave the computation dynamically, sometimes because of device or network failure.

Origins of JavaSpaces

We've described JavaSpaces as a new distributed computing model, but its origins can be traced back to Yale University in the early 1980s. There, Dr. David Gelernter developed a tool called Linda for creating distributed applications. Linda consists of a small number of operations combined with a persistent store called a tuple space. These operations are orthogonal to any particular programming language; they are part of a coordination language that can be added to any other computation language. The result of the Linda research was surprising: by using an object store along with a small number of simple operations, you can easily implement a large class of parallel and distributed problems using techniques that alleviate many of the pitfalls of building networked systems. In other words, space-based systems are not only simple (requiring only a few operations), but also expressive (lending themselves well to solving many distributed problems).

Dr. Gelernter's work inspired Sun's JavaSpaces service, and also influenced the design of the lookup and discovery components of the core Jini technology (which you'll see as the Jiniology series progresses). While JavaSpaces inherited the space model from Linda, the designers of JavaSpaces have updated the model in significant ways, leveraging the power of Java objects, Jini, RMI, and object serialization.

JavaSpaces in context

Our description so far has been a little abstract, so let's consider a few examples of real distributed applications that you can model as processes exchanging objects through spaces.

Chat systems

Consider a simple multiuser chat system, in which a space serves as a chat area that holds all the messages making up a discussion. To talk, a participant deposits message objects into the space. All chat members wait for new message objects to appear, read them, and display their contents. Late arrivals can examine the existing message objects in the space to review previous discussion. In fact, since the space is persistent, a new participant can view the discussion long after everyone else has gone away, and participants can even come back much later to pick up the conversation where they left off. The list of chat participants can also be kept in the space and updated whenever someone joins or leaves the conversation.

Compute servers

Now consider analyzing realtime radio telescope data for signs of extraterrestrial life (much as the SETI@home project does). Such data is voluminous, and analyzing it is a computationally intensive job that is well suited to parallel computation by a network of computers -- in other words, a "compute server." Using the JavaSpaces technology, a series of tasks -- for instance, one task per chunk of data that needs to be analyzed -- is written into the space. Each participating computer searches the space for a task, removes it, completes the necessary computational work, drops the result back into the space, and then continues to look for more tasks. This approach scales naturally: it works the same way whether there are 10 computers available or 1,000. The approach also provides natural load balancing, since each worker picks up exactly as much work as it can handle in a given time, with slow computers doing less work and fast computers doing more.

Broker systems

As a third example, consider an online auction system that brings buyers and sellers of goods and services together. Suppose you, as a potential buyer, describe the item (such as a car) you'd like to buy and the price you're willing to pay, wrap the information in an entry, and write the resulting wanted-to-buy entry to a space. At the same time, potential sellers continually monitor the space for the arrival of wanted-to-buy entries that match items in their inventory. For example, Mazda dealers monitor the space for entries that describe Mazdas, while used-car dealers monitor the space for all used-car requests. When a matching request is found and read, a potential seller writes a bid entry into the space, stating an offering price. As a potential buyer, you continually monitor the space for bids on your outstanding requests, and, when you find one that's acceptable, you remove the bids and contact the seller (possibly through the space via another entry).

A brief overview of the API

Now it's time to introduce the JavaSpaces API. As we've already said, it's simple; in fact, in the remainder of this article we will cover everything that you need to know (barring some minor details) about it. However, before we describe the JavaSpace interface and its methods, we first need to talk about entries.

Entries

An object that is stored in a space is called an

entry.

To be an entry, an object just needs to implement the

Entry

interface. As an example, let's define a message entry that you can write into a space:

import net.jini.core.entry.Entry;

public class Message implements Entry { public String content;

// a no-arg constructor public Message() { } }

Here we've defined a Message class with a string field that will hold the content of the message. Because we want to use this class with spaces, we need to implement the interface net.jini.core.entry.Entry, which is found in the package net.jini.core.entry. It's important to point out that Entry is a marker interface; in other words, the interface contains no constants or methods and therefore requires no special work to implement, other than adding implements Entry to your class definition.

Besides implementing the Entry interface, there are a few other conventions that our entries must follow. We'll have more to say about the reasons in later articles, but for now we'll just look at the broad outlines. An entry must have a public constructor that takes no arguments (a so-called no-arg constructor); this requirement stems from the underlying serialization that occurs when entries are transferred in to and out of spaces. Note that our definition of Message contains a no-arg constructor. Another convention is that fields of an entry should be declared public; this lets other processes find your entries in spaces via associative lookup, based on the values of those fields. A third convention is that fields of an entry must contain references to objects, rather than primitive types (that is, if you need to define a primitive type field such as int, you should use the corresponding wrapper class Integer instead). To make sure you are covering all your bases in defining entries, we recommend that you refer to JavaSpaces Principles, Patterns, and Practice,or to the Sun Microsystems JavaSpaces Specification for details. We will also, as mentioned, touch on some of the finer points in later articles.

Other than these requirements, an entry is like any other Java class; you can instantiate it, invoke its methods, and assign values to its public fields. Now that we've defined a Message entry class, let's see what operations are available for interacting with entries in spaces.

The JavaSpace interface

To interact with a space, you need to obtain access to an object that implements the JavaSpace interface. There are many ways of obtaining access to such an object (you can, for example, use the Jini lookup or the RMI registry) and we will cover the details of doing so in the next article. For now, we will concentrate on the JavaSpace interface itself.

1 2 Page
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more