Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples

O'Reilly Book Excerpts: JXTA in a Nutshell

Getting Started with JXTA, Part 2

Related Reading

JXTA in a Nutshell
By Scott Oaks, Bernard Traversat, Li Gong

by Scott Oaks, Bernard Traversat and Li Gong

In part two of this series of book excerpts on getting started with JXTA, from JXTA in a Nutshell, learn about peergroups and discovery, which are important for understanding peer-to-peer Web services.


Peers self-organize into groups. JXTA does not define what these groups are, nor why they exist: the JXTA framework supports the creation of groups and the definition of group membership, but it is up to cooperating peers to define groups, join groups, and leave groups. Among other purposes, peergroups serve to:

The JXTA platform defines two kinds of peergroups:

1. The NetPeerGroup
This is the default peergroup a peer joins after booting the JXTA network; it is sometimes called the World Peergroup. Configuration of the NetPeerGroup is typically done by the administrator in charge of the network domain on which the peer is located. The NetPeerGroup defines the initial scope of operations of a peer and the default services it provides.

2. User peergroups
Users (and applications) can create new peergroups with their own set of customized services and membership policies. User peergroup services are created by either cloning and extending the NetPeerGroup services or by creating new ones. All user peergroups are subsets of the NetPeerGroup.

All peers are automatically members of the NetPeerGroup peergroup; they do not need to take any special actions to join the group, and they cannot leave the group. Peers may opt to join and leave other groups at will. In order to join a group, a peer must discover the group and then ask to join it. Depending on the group, the peer may have to present authentication credentials, and the group will vote on the peer's application.

Let's see how this all works in the context of the shell. When the shell starts, it automatically joins the NetPeerGroup. One way that you can find the group that a shell belongs to is with the whoami -g command:

JXTA>whoami -g
<Description>NetPeerGroup by default</Description>

Any peer can create a peergroup. Peergroups are typically composed of peers that have either a common set of interests (e.g., music or baseball peergroups) or that interact with each other to exchange contents.

Peergroup Services

Peergroups allow us to introduce the notion of protocols and services in the JXTA platform. A peergroup provides a set of services that peers can utilize. The JXTA platform defines seven core services:

This set of core services is used to "seed" the peer so it can discover and find enough resources to support itself. The NetPeerGroup services provide sufficient functionality for allowing this dynamic bootstrapping mechanism. The core services were selected to enable a peer to have enough functionality to create and join a large variety of peergroups:

User peergroups can extend, replace, or add new services, allowing a variety of peergroups to be created.

A peergroup does not need to provide all of these services; it can provide only those that are necessary to support the peers within the group. Most peergroups, however, will provide at least a membership service. Since peers are always members of the NetPeerGroup, they can always obtain these services from the NetPeerGroup.

The NetPeerGroup provides all seven of these services. In general, each of these services defines a specific protocol used to access the service.

Creating Peergroups

Any peer can create a peergroup. The shell creates a peergroup with these commands:

JXTA>mygroupadv = mkadv -g mygroup
JXTA>mkpgrp -d mygroupadv

The first of these commands creates an advertisement (mygroupadv) of a new group with a symbolic name of mygroup (advertisements are discussed in more detail later in this chapter). The mkpgrp command actually creates the group.

When you create a group in this manner, information about the group is broadcast to other peers using a discovery protocol that we discuss in the next section. In general, a peer can find a peergroup in two ways:

1. When a new group is created, an announcement of that group is broadcast, and peers who are listening will discover the new group.

2. A peer can initiate discovery to find groups. In the shell, this is accomplished with the groups -r command:

     JXTA>groups -r
     group discovery message sent

You can see which groups the shell knows about by using the groups command:

group0: mygroup
group1: anothergroup

In this last example, we know about mygroup because that's the group that we created; we know about anothergroup because another peer on the network created that group and we discovered it. Note that the NetPeerGroup does not show up in this list, even though it is also a peergroup.

Each peergroup is uniquely identified by a unique peergroup ID. The peergroup ID is guaranteed to be unique within the entire JXTA network.

Joining Groups

Once a peer has discovered or created a group, it must join the group. This entails sending an application (with any necessary credentials) to the group and awaiting a response. The membership service of the group will vote on the new application and send back either an acceptance or a rejection.

A shell joins a particular group by using the join command:

JXTA>join -d group0
Enter the identity you want to use when joining this peergroup (nobody)
1Identity: jra

After executing this command, the shell is a member of the group mygroup. A quick note about syntax here: group0 comes from the list of groups we obtained with the groups command. You can use the symbolic group name (e.g., mygroup) to join a group only if that shell created the group. To join a group that the shell discovered (such as anothergroup), however, you must use the group# that the shell has assigned. Because the shell caches information about groups, it might have created the group, exited, and restarted. In that case, you must also use the group# that the shell has assigned.

A peer can join multiple groups by executing another join command; the join command can also be used to determine which groups the peer has joined:

JXTA>join -d group1
Enter the identity you want to use when joining this peergroup (nobody)
1Identity: sdo
JXTA> join
Joined group    : mygroup
Joined group    : anothergroup    (current)

Commands that the shell executes will be associated with the current group (anothergroup); the current group can be changed with the chpgrp command:

JXTA>chpgrp mygroup

n this command, you always use the symbolic group name rather than the group# name. The current group is used to find any service that the shell needs; it is also the group printed by the whoami command.

Membership in any group created by the shell is automatic, so these examples work well when dealing with groups created by two different shells. A shell might also discover a different group, however: one that has membership criteria and requires the shell to present some special credentials. Membership in such groups requires that you know how to fill out a credential request, which is group-specific; we'll look at how this works in Chapter 7.

Canceling Group Membership

A peer can cancel its membership in a group. The shell cancels its membership in a group with the leave command:


This command cancels membership in the current group. You cannot leave the NetPeerGroup.


So far, our shell does not have a peer. In the JXTA world, this is not a good thing, as a peerless JXTA application is not very useful. The first thing it must do, therefore, is find other peers with whom it can exchange information. The process of finding other peers is called discovery.

The process of discovery applies to any JXTA resource: peers discover other peers, and they also discover peergroups, pipes, advertisements, and other resources. There are two ways in which peers discover resources: peers discover resources dynamically, and they use special, statically configured peers to tell them about JXTA resources. Discovery occurs within the context of a peergroup: a peer attempts to discover resources within a specific peergroup.

Dynamic Discovery

Peers use the JXTA Peer Discovery Protocol (PDP) to discover JXTA resources dynamically. The PDP defines the lowest-level technique that is available for peers to discover resources. On an IP network, it consists of two parts: a multicast message that is sent on the local network and the use of rendezvous peers to discover peers beyond the scope of the local network. Other network bindings will behave differently, but the essential operation of the PDP is that the requesting peer sends a message, and resources that hear the request will respond directly to the peer. Therefore, a peer using PDP will discover all JXTA resources that are on the local network or are known by the peer's rendezvous peers.

The implementation of discovery is actually a feature of the peergroup in which the peer is running. Certain peergroups may define other protocols by which peers can discover resources within the peergroup. The PDP is implemented by the discovery service that runs within the NetPeerGroup (and most other peergroups).

The peers -r command of the JXTA Shell implements the PDP; it will discover all other JXTA peers on the local network. Before executing this command, you may want to start a shell on another machine on your network (the next part of this series will show you how to start a second shell on the same machine as the first).

Now in the original shell window you can execute commands to discover the second peer:

peer0: name = Test Shell 1
JXTA>peers -r
peer discovery message sent
peer0: name = Test Shell 1
peer1: name = Test Shell 2

If you execute the same commands from the second shell, you'll notice that it numbers the peers differently. The peer numbers are used only internally by the shell application; peers are not numbered in a JXTA sense (except for their unique IDs).

It can take some time for the shell to discover other peers; executing the peers -r command may not necessarily report all of the peers on the network until the shell has completed its discovery process. In addition, some peers may not respond because they miss the multicast message; no reliable network protocol is used to discover peers. On the other hand, as more peers are added to the network, discovery is faster: that's because when a peer responds to a discovery message, it sends information about itself and about all other peers that it has already discovered.

Static Discovery Through Rendezvous Peers

There are special JXTA peers known as rendezvous peers. These peers are like lookup services: they keep a list of peers (and other JXTA resources) that they know about, and other peers query them for that list.

If you've been following along with our example, and you're on a computer connected to the Internet, when you first executed the peers command, you received a list of peers. This is because the shell is configured to contact certain known rendezvous peers on the Internet; by default, it will automatically contact the hosts and These hosts showed up in our earlier example as peers JXTA.ORG 235 and JXTA.ORG 237.

These hosts are the boostrapping set of rendezvous peers for the NetPeergroup. Peers may discover rendezvous peers dynamically and use them in place of these; the intent of the bootstrapping rendezvous peers is to initiate the discovery process of dynamic rendezvous peers.

When the shell contacts the peer at one of these hosts, it will get back a list of all other peers that have discovered that same rendezvous peer. Therefore, a JXTA Shell running on a machine connected to the Internet may automatically discover many peers.

You can use the rdvstatus command within the shell to see if the shell has successfully contacted a rendezvous peer:


Rendezvous Connection Status:

Is Rendezvous : [false]

Rendezvous Connections:

  Rendezvous name: JXTA.ORG 237
  Rendezvous name: JXTA.ORG 235

Rendezvous Disconnections:


In this case, the shell itself is not acting as a rendezvous peer; the shell has made contact with two rendezvous peers.

There can be as many rendezvous peers as peers in the network, although a certain ratio between rendezvous peers and other peers is expected to be maintained, depending on the peergroup discovery policy. Some peergroups will have a few rendezvous peers; others will have many. Smaller peergroups typically need fewer rendezvous peers. Larger peergroups tend to need more rendezvous peers to reduce the chance of creating islands of peers that do not communicate with others.

A peer can dynamically advertise itself or remove itself from the list of rendezvous peers. Peers can discover new rendezvous peers dynamically and add them to their list of known rendezvous peers. As with the shell, any peer can be preconfigured to know about a fixed number of rendezvous peers. Each peergroup can define its own ratio of peers to rendezvous peers to support the peergroup-specific requirements.

Because a peer knows the address of a rendezvous peer, it can use whatever network protocol it wants to contact it (assuming, of course, that the rendezvous peer also supports that protocol). In the shell, the preconfigured rendezvous peers are all defined as using HTTP as their transport mechanism.

Other Discovery Mechanisms

JXTA services and applications are free to use any other technique to find each other. The shell, for example, can be configured to pass its requests to the rendezvous peers through a proxy; this is useful if you must pass through a firewall to get to the Internet. In this case, the shell wraps the standard PDP message into an HTTP request that it sends to the proxy server; the proxy forwards it just as it would any other HTTP message. When the rendezvous peer receives the request, it puts its answer back into the HTTP response and sends it to the proxy, which returns it to the shell.

Any variation on this technique is valid, as long as all the peers agree on the technique. At a minimum, peers will always be able to discover each other using the basic PDP (assuming, of course, that their network topology supports the discovery we described above).

Consider the peers shown in Figure 2-3. When the JXTA Shell joins its local network, it will send out a broadcast version of the PDP. It will get back two responses. One response will come from the JXTA searching service, and the shell will now know about the searching service. The other response will come from the JXTA rendezvous peer. Because the rendezvous peer is sitting on a machine that is attached to both the local and corporate networks, it has previously discovered the searching peer and the file-sharing peer. When the rendezvous peer receives the PDP broadcast method from the shell, it will tell the shell about these two peers.

The shell will then send a PDP message via HTTP directly to JXTA.ORG 237. The rendezvous peer at JXTA.ORG 237 will then tell the shell about all the peers that JXTA.ORG 237 has discovered; this is how the shell can discover the JXTA auction service. In Figure 2-3, the HTTP message passes through a proxy in order to pass through the firewall.

Figure 2-3.

JXTA peers and discovery

Passing through the proxy is a value-added feature of how the JXTA Shell is programmed (and a value-added feature of the standard Java language bindings that we use throughout this book). At a basic level, the PDP works over HTTP; if we were to remove the firewall from this network, then the JXTA file-sharing service could use PDP directly to contact JXTA.ORG 237 and discover the JXTA auction service.

Also note how peer discovery is improved as more peers are added to this example. When a new peer is connected to the local area network and executes the basic PDP to find peers dynamically, it will immediately find the JXTA auction and file-sharing services. That's because the shell has already found these services. When the new peer sends its discovery message, the shell will respond with all the peers it knows about.

Relay Peers

JXTA peers can elect to become relay peers. Relay peers send dynamic discovery requests across different networks.

In Figure 2-3, the JXTA rendezvous peer sits on two different networks. The JXTA Shell discovered the JXTA file-sharing service because it knew about the rendezvous peer and contacted it directly. If the JXTA rendezvous peer was a JXTA relay peer instead, then when the JXTA Shell performed its multicast discovery, the JXTA relay peer would have seen the multicast message and routed it onto the corporate network. This would have been seen by the JXTA file-sharing service, which would have sent a message back to the shell.

The end result here is the same: the shell discovers the service, but the procedure is quite different. In the case of the rendezvous peer, the shell had to have explicit knowledge of the rendezvous peer in order to contact it. In the case of the relay peer, the discovery would happen dynamically.

In practice, peers often serve as both relay and rendezvous peers.

In the next installment, learn JXTA application configuration.

Scott Oaks is a Java Technologist at Sun Microsystems, where he has worked since 1987. While at Sun, he has specialized in many disparate technologies, from the SunOS kernel to network programming and RPCs.

Bernard Traversat is a well-known developer in the Java Community and an active member of the Project JXTA. Bernard is the Engineering Manager for the JXTA CORE.

Li Gong is a well-known developer in the Java Community and an active member of the Project JXTA. Li is the JXTA Engineering Director for the JXTA CORE.

Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.