I want to talk about the implications for that marvelous aspect of the fundamental UNIX design: the pipe, and its ability to connect small independent programs so that they could collectively perform functions beyond the capability of any of them alone. What is the equivalent of the pipe in the age of the Web?
-- Tim O'Reilly, JavaOne Keynote: "The Network Really is the Computer."
The JXTA shell is a command-line interface to Sun's JXTA (pronounced "Juxta") peer-to-peer framework. Originally written as a debugging tool for developers, the JXTA Shell affords a ground-floor view of the JXTA environment, much like a traditional shell drops one into the thick of a *nix operating system.
The JXTA shell is a fine demonstration of some of the key features of
the JXTA platform. The shell itself is nothing more than a framework
for dynamically loading and binding commands (read: classes) to the
JXTA underpinnings. This allows you, the user, to extend the shell to
your heart's content. Who'll be the first to write
|Table of Contents|
As we'll see in this article, inter-peer messages in JXTA are nothing more than XML documents, a fact that provides various interesting intersections with Web Services (via XML-RPC and SOAP), syndication (via RSS), Instant Messaging a la Jabber, and more.
This article is an introductory tour of the JXTA shell. We'll step through some of its simple commands and move to more interesting examples constructed from these core building blocks. (For an overview of the JXTA platform, see the accompanying article, The JXTA Position.)
Anyone familiar with command-line shells, whether DOS or *nix, will
feel right at home in the JXTA shell. There are basic commands:
man, cat, env, grep, more, and more. Commands can, of course, be
sewed together using pipes to create compound commands:
env | wc.
Multiple commands on one line are separated by semicolons:
whoami ; man man. All in all, aside from the fact that it's easy to forget
that it's not a complete shell (see "Gotchas"),
there are few surprises.
First things first; we'll download, install and launch the JXTA shell.
Note: At the time of this writing, Windows 2000 users may have trouble with the Windows installer launching and disappearing without doing much of anything, save perhaps hanging around in the background. If this happens, you may want to download the latest nightly build.
|JXTA Application Icon|
|The JXTA Configurator|
|The JXTA Shell|
Note: I found a couple of bugs that can cause the shell not to launch. If, after closing the configurator, the shell does not appear momentarily, double-click the jxta.exe icon to relaunch. Windows 2000 users may find this makes no difference and will need to log out (not reboot, mind you) and log in again before continuing.
This article was written using version 0.9 (build 14e, 04-22-2001).
For versioning, type
version at the command-line.
We'll start with a few old shell favorites.
If at any point you need help, the standard *nix
man provides man(ual) pages for supported
functionality. Typing just
information about man itself, along with a list of available commands.
(For a complete list of JXTA shell commands, see "JXTA Commands.")
env, as expected, displays all defined shell
|Have you explored JXTA? Tell us your first impressions and let others know what you've learned so far.|
|Post your findings|
One thing to note in the above readout is that standard input (reading keyboard input) and output (displaying output to the console) are JXTA pipes, the same conduits by which peers communicate with each other. The same is true for the shell console's consin/consout. We'll delve more into pipes in a bit.
Here are a few more simple commands to try for fun:
man | wc
env | grep -i stdin
cat peer0 | more
Let's get to know ourselves a little, shall we? The
whoami command functions as expected, albeit a
little more interesting than the standard printing of my username.
whoami claims that I am a peer named "milne" with the unique
identifier, "jxta://596162..." I am, by default, a member of the
"NetPeerGroup" -- more on groups in a moment. I
am communicating via TCP directly at IP address 184.108.40.206, port 6001,
and via an HTTP proxy if behind a firewall/NAT. Note that even though
I may be using HTTP to get past my firewall, direct TCP communication
is still useful for peers on my LAN. The second
whoami provides a
little more detail about my current peer-group membership, including
group identifier and available services.
For more details, there's
whoami -l . This is
but a pretty representation of the actual peer advertisement, viewable
in its native XML by printing the "peer0" environment variable we saw
These settings reflect the initial JXTA configurator
settings we breezed through earlier. To reconfigure your JXTA peer
from within the shell, take a gander at the
peerconfig command (type:
So much, then, for the preamble; let's get on to the interesting P2P pieces.
Each application tapping into JXTA is a peer. Your JXTA
shell running on your desktop right now is a peer, as is mine on my
peers command displays all peers
already known to my peer, initially only myself and possibly a peer
I'm using as an intermediary outside my firewall/NAT.
Discovering other peers, peers of peers and so on, is just a
matter of propagating a remote discovery request using
Discovered peers (technically, their peer announcements) are cached
locally, stored in environment variables "peer#" where # is the
sequential integer associated with a particular peer. To flush all
known peers and begin again, use
Each peer belongs to a peer group. By default, each peer is a member of the global "NetPeerGroup" group, analagous to a world without area codes, where every phone number is globally unique. The majority of the time, however, we function within a particular community and can assume the presence of a limited number of appropriate peers. A peer group logically limits the scope of peers with whom you will be communicating, analagous to your local telephone area code. Upon joining a peer group, one sees only other member peers.
As with peers,
to find out what groups are known to your peer, use the
command; to propagate a group remote discovery request, use
To join a group, simply use
join -d group# where
"group#" is the environment variable in which the group advertisement is
stored. You are prompted for an identity; technically a UUID,
anything will do. To leave, use (surprisingly enough)
leave. Here I join the "tiggers" group, look
around for peers and leave.
Discovered group announcements, like peers, are cached locally; flush
The JXTA shell extends the concept of the piping between local
commands (as in
man | wc) to inter-peer communication.
JXTA pipes are unidirectional and asynchronous.
Since JXTA pipes are asynchronous, an output pipe connection can be dynamically disconnected and reconnected to a different input pipe. This disconnection operation can be performed multiple times over the lifetime of the pipe. The ability to transparently redirect output of pipes is an essential feature to build highly available services in a loosely coupled and unreliable environment such as peer-to-peer networks. -- JXTA Shell Documentation (PDF)
While not quite as elegant as using the
| character, piping
from one peer to another in JXTA is almost trivial. As an example,
we'll open two shell windows (call them Pooh
and Piglet) and pipe a couple of simple
text messages between them (from Piglet to
Pooh). Pretend for a moment that these are
two separate peers running on machines on opposite sides of the Hundred Acre Wood.
First, Pooh creates a pipe advertisement and gives it a name ("pipeadv").
He uses this pipe advertisement to create an input pipe
("inpipe") -- the receiving end. After launching another shell window
Shell -s) for Piglet, an environment variable ("pigletmsg") is
readied to receive input from our input pipe. We leave this shell
window in a waiting state and wander over to Piglet's.
Piglet uses the same pipe advertisement to create an output pipe ("opipe"). A new message is created and stored in the environment variable "mymsg." Now Piglet has created a couple of text files named hellopooh and byepoo containing one line of text apiece. In turn, each file is imported and stuffed into the variables "file1" and "file2." The contents are packed into "mymsg" with an associated arbitrary tag, so as to be able to sort them at the other end. Finally, Piglet sends his message via the output pipe and ...
Instantly (or so the theory goes), Pooh receives Piglet's message.
Simply printing the value of the "pigletmsg" variable reveals a
message composed of a couple of XML documents and the associated tags
given to them by Piglet. Instead of simply being displayed, individual documents
can be extracted from the
message and assigned to a variable using the
Since inter-peer messages are nothing more than XML documents, this provides various interesting intersections with Web Services (via XML-RPC and SOAP), syndication (via RSS), Instant Messaging a la Jabber, and more.
While the example above provided some insight into message passing via
pipes under JXTA, the shell does actually have some rudimentary
instant-messaging functionality. More a piping demonstration than
talk resembles the *nix
functionality, with each peer establishing its own talk connection to
Pooh registers a talk user (read: talk advertisement) "pooh" and logs
in (read: starts a listener daemon). He tries to find Piglet, who has
not yet registered as a talk user. We use
Shell -s to
create a new shell for Piglet.
Piglet creates a talk user "piglet" and logs in.
Pooh tries again, this time successful in finding Piglet and sending him a greeting.
Piglet receives Pooh's message -- albeit in rather ugly form. Now,
Piglet can't simply reply to Pooh, as talk is a one-way piped message.
So Piglet establishes his own talk session to Pooh. You'll notice the
slightly different form of
talk -u piglet pooh, resulting
in a much cleaner message with proper attribution in Pooh's shell.
Once our friends are ready to conclude their chat, each enters a
period on a line by itself and optionally logs out. Note that talk
advertisements created by
talk -register hang around
between shell sessions; before one can chat, however, one must
talk -login to start a new listener.
Incidently, as I mentioned a moment ago, a talk registration is simply a JXTA
advertisement stored in a local environment variable. We can take a
closer look using our old friends,
Hardly user-friendly in its shell implemention, such talk functionality has already been implemented in InstantP2P, a Java AWT-based GUI chat/file-sharing demonstration application.
To log out of the JXTA shell, type
exit at the
prompt or just close the shell window. Quite a bit of information is
retained between shell sessions including settings, cached peers, groups and
other advertisements. To clear your peer or group caches, use the
-f option mentioned earlier. To start from
scratch, delete the following files/directories:
PlatformConfig, PlatformPeerGroup, jxtaConfig,
Bear in mind that the JXTA shell is only for demonstration and debugging purposes and should not be relied upon to be absolutely stable or emulate a full shell. At the time of this writing, there are a few gotchas and bugs:
Shell -sare not truly independent. Closing or exiting from the primary shell closes the entire application and all windows.
Disclosure: The author has been a member of the JXTA's Technical Advisory Committee during its pre-launch development.
Copyright © 2009 O'Reilly Media, Inc.