As we discussed in Part 1 of this series, SMS-based messaging is very convenient for wireless phone users. However, it is not a suitable messaging platform for non-phone mobile devices such as PDAs and WAN-connected handhelds. SMS messaging across different cell networks (such as international calls) can also be expensive or even in some cases impossible. In this second and final installment of our series on mobile P2P messaging, we will introduce you to two general-purpose peer-to-peer networks -- the JXTA P2P and Jabber instant messaging networks -- that you might use in situations that don't lend themselves to SMS. Materials in this article will also appear in my upcoming Prentice Hall book, Java Mobile Enterprise Application Development (see the Resources section below for a link).
JXTA defines a set of open protocols for peer-to-peer networks. These XML-based protocols describe complex operations such as peer discovery, endpoint routing, connection binding, basic query/response message exchange, and network propagation through rendezvous peers. To completely describe these protocols is beyond the scope of this article; interested readers should refer to the official JXTA Web site for more information or read some of the other developerWorks articles on the subject (see the Resources section below for links). To summarize, a JXTA network is made up of several components:
- A peer is the basic element of any JXTA network. A peer implements core JXTA protocols, and operates independently of and asynchronously with all other peers. A peer provides application and/or network services and is capable of advertising itself.
- A peer group is a collection of peers. JXTA defines the protocols that peers use to create, join, and monitor groups. A group provides services such as peer discovery, membership, access control, pipes, resolvers, and monitoring.
- Pipes represent virtual connections among peers. A point-to-point pipe connects two peers; a propagate pipe connects a broadcast peer with multiple listeners. Pipe-connected peers are not necessarily directly physically linked; they can be connected through multiple intermediate pipes.
- Messages are the data exchanged through pipes between peers and endpoints. JXTA defines an envelope format for all messages. Each peer can define its own message content format as long as that format conforms to the XML specification. However, in order for two peers to exchange meaningful information, they must understand each other's message format.
- Advertisements are metadata structures for describing JXTA network resources. All peers and services understand advertisements.
JXTA is a generic P2P framework that goes far beyond simple messaging. It addresses issues like P2P file sharing, P2P application services, and collaborative distributed computing. While the JXTA protocols are designed to be independent of any implementation technology, JXTA's reference implementation is built on the Java platform. This reference implementation uses Java APIs to wrap JXTA protocol messages and provide a programmatic way to access the JXTA network from Java applications.
The power and flexibility of JXTA come at a price: complexity. A JXTA peer needs to take care of a lot of tasks and process messages at the XML-over-socket level. Such a peer would be too complex to run on most mobile devices. In addition, neither XML nor raw socket support are part of the standard J2ME/MIDP specification. To make JXTA networks available to mobile P2P users, we need a set of lightweight JXTA APIs for mobile devices. The JXME project aims to provide JXTA APIs for the CLDC and MIDP platforms. It can also be used in higher-end J2ME profiles, such as the Personal Profile.
JXME uses relays to connect lightweight mobile peers to the rest of the JXTA network. The relays themselves are rendezvous JXTA peers that have full capabilities to handle pipes, advertisements, and peer group services. Mobile peers communicate with relays through binary-over-HTTP connections using messages conforming to the JXTA Binary Message format. Relays offer a number of peer services to mobile peers:
- A relay filters out unnecessary advertisements, and strips down those advertisements that are sent in order to save bandwidth.
- A relay routes (relays) messages to or from mobile peers.
- A relay translates the relayed messages from JXTA XML format to JXTA Binary Message format, and vice versa, in order to enable interoperability between mobile peers and ordinary peers.
- A relay acts as a proxy on behalf of its mobile peers. The relay interacts with other peers and pipes, and uses group services.
As developers, we do not need to worry about the exact format of the mobile-to-relay binary protocols and the exact implementation of relay peers. We just use the API classes provided by JXME.
Figure 1. JXME architecture

You can check out the latest JXME source code -- both the relay and J2ME peer libraries -- from the project's public CVS server (see Resources). You can also download stable binary and source code from the JXME Web site.
Once you've downloaded the JXME package, you can start playing with the demos that come with it. Let's briefly walk through the steps to the run the demos using the Ant build script included in the download package. For a more detailed step-by-step tutorial, please refer to the JXME Web site.
First, you need to run the relay peer on a computer accessible from both your mobile device and your target JXTA community. The build.xml file in the proxy directory contains a runproxy task that will run a JXME relay. Make sure that you check the appropriate boxes to run it as Rendevous, relay and JxtaProxy. Now you can run JXME peers. The download
package includes two sample JXME applications, chat and tictactoe, that you can experiment with.
Now, let's look into the JXME package itself. The JXME API only has three classes, all in the net.jxta.j2me package:
Elementrepresents an element inside a JXTA message. An element contains a name, a namespace, a MIME type, and a binary array of data.Messagerepresents a JXTA message consisting of several elements.Messageprovides methods to access those elements.PeerNetworkis the most useful class. It specifies the JXTA tasks that a mobile peer can perform through the relay. There are several useful methods in thePeerNetworkclass:
createInstance()is a factory method that returns an instance ofPeerNetworkwith a specified peer name.- The
connect()method connects to a relay at a specified HTTP URL. It returns a byte array of persistent state information; this information should be passed through theconnect()method in all subsequent connections to the relay. - The
create()method creates peers, groups, and pipes on the JXTA network through the relay proxy. - The
search()method searches for peers, groups, and pipes. - The
poll()method polls the relay for messages addressed to this mobile peer. It can be called iteratively in a server thread. - The
listen()andclose()methods open and close an input pipe, respectively. - The
send()method sends a message to a specified pipe.
Figure 2. Classes in package net.jxta.j2me

In this section, I will use a tutorial example -- mySend.java, which is included in the JXME source code package available from the JXME Web site -- to illustrate the usage of the API we outlined above. The JXME package consists of voluntary contributions made by many individuals to Project JXTA. The source code is licensed under the Sun Project JXTA Software License, which is based on the BSD license.
The example mobile peer running on a J2ME emulator performs a number of actions via a JXME relay running on the emulator's host PC
(localhost) at port 9700. Of course, in real-world deployment, the mobile peer can run on any mobile device, and you can just change localhost to the IP address of your relay computer. The code for the JXME relay is included in the download package.
The example peer follows walks through a number of steps:
- It establishes a new pipe.
- It searches and finds the pipe it just established.
- It sends a message to itself through that pipe.
- It receives that message.
Let's look at the code for these steps. In Listing 1, the method peer.listen() instructs the relay to
create a new pipe.
Listing 1. Creating a new pipe
// Create a peer and have it connect to the relay.
// A connection to relay is required before any other
// operations can be invoked.
String relayUrl = "http://localhost:9700/";
PeerNetwork peer = PeerNetwork.createInstance("mySendPeer");
byte [] persistentState = peer.connect(relayUrl, null);
// Have the peer create and open a Unicast pipe; PipeID will
// be returned asynchronously in a response message
int listenQueryId = peer.listen("myPipe", null, PeerNetwork.UNICAST_PIPE);
// Have peer search for this Pipe and then send it a Message
String pipeID = findMyPipe();
sendMyMessage(pipeID);
// Finally, have the peer poll for Messages sent to it
recvMessage();
}
|
After the pipe is created successfully, the relay generates a binary message to the mobile peer. The method findMyPipe() polls the relay in a loop until it receives
this message indicating success. It then parses the message and gets the pipe ID.
The binary message has an XML-like structure. Listing 2 demonstrates this process.
Listing 2. Getting the pipe we just created
public String findMyPipe() throws IOException {
// Now poll for all messages addressed to us. Stop when we
// find the response to our listen command
int rid = -1;
String id = null;
String type = null;
String name = null;
String arg = null;
String response = null;
Message msg = null;
while (true) {
// do not use a timeout of 0, 0 means block forever
msg = peer.poll(1);
if (msg == null) {
continue;
}
// look for a response to our search query
for (int i = 0; i < msg.getElementCount(); i++ ) {
Element e = msg.getElement(i);
if (Message.PROXY_NAME_SPACE.equals(e.getNameSpace())) {
String elementName = e.getName();
if (Message.REQUESTID_TAG.equals(elementName)) {
String rids = new String(e.getData());
try {
rid = Integer.parseInt(rids);
} catch (NumberFormatException nfx) {
System.err.println("Recvd invalid " +
Message.REQUESTID_TAG +
": " + rids);
continue;
}
} else if (Message.TYPE_TAG.equals(elementName)) {
type = new String(e.getData());
} else if (Message.NAME_TAG.equals(elementName)) {
name = new String(e.getData());
} else if (Message.ARG_TAG.equals(elementName)) {
arg = new String(e.getData());
} else if (Message.ID_TAG.equals(elementName)) {
id = new String(e.getData());
} else if (Message.RESPONSE_TAG.equals(elementName)) {
response = new String(e.getData());
}
}
}
// PIPE_NAME: myPipe
// PIPE_TYPE: PeerNetwork.UNICAST_PIPE
if (rid == listenQueryId &&
response.equals("success") &&
type.equals("PIPE") &&
name.equals(PIPE_NAME) &&
arg.equals(PIPE_TYPE)) {
return id;
}
}
}
|
In Listing 3, the method sendMyMessage() takes the pipe ID returned from the method findMyPipe() and sends a message through the pipe.
Listing 3. Sending a message through the pipe
public void sendMyMessage(String pipeID)
throws IOException {
Element[] elm = new Element[2];
// Our Message will contain two elements. Receiver should look for
// elements with the same names ("mySend:Name" and "mySend:Message")
// PEER_NAME: mySendPeer
elm[0] = new Element("mySend:Name", PEER_NAME.getBytes(),
null, null);
elm[1] = new Element("mySend:Message", "Hello there".getBytes(),
null, null);
Message msg = new Message(elm);
// PIPE_NAME: myPipe
// PIPE_TYPE: PeerNetwork.UNICAST_PIPE
sendRequestId = peer.send(PIPE_NAME, pipeID, PIPE_TYPE, msg);
System.out.println("send request id: " + sendRequestId);
}
|
As you'll recall, mySendPeer is itself listening to the pipe. Thus, the message we send above will be available to the same mobile peer from the relay. The method recvMessage() polls the relay until it receives the message, and then displays the message content once it has received it, as shown in Listing 4.
Listing 4. Receiving the message
public void recvMessage() throws IOException {
Message msg = null;
while (true) {
msg = peer.poll(1);
if (msg == null) {
continue;
}
for (int i = 0; i < msg.getElementCount(); i++) {
Element e = msg.getElement(i);
if ("mySend".equals(e.getNameSpace()) &&
"Name".equals(e.getName()))
System.out.println("Message from: " +
new String(e.getData()));
if ("mySend".equals(e.getNameSpace()) &&
"Message".equals(e.getName()))
System.out.println("Message: " +
new String(e.getData()));
}
}
}
|
Ultimately, the success of any P2P system depends on its ability to attract users. Although JXTA is a very powerful and technically advanced framework, its technical complexity hinders its adoption. Jabber is a much simpler P2P system than JXTA; it is primarily designed for instant messaging. Jabber has a much larger peer network than JXTA.
Jabber was originally designed to provide interoperability among popular Internet instant messaging systems (AOL, MSN, Yahoo!, ICQ, and so on). It is a powerful and flexible yet simple protocol that can wrap around all existing IM protocols. With powerful features and completely open XML protocols, Jabber is by far the most advanced IM system available today. Jabber can also support many advanced P2P applications, such as calendar groupware and file sharing.
Jabber peers communicate with each other through Jabber servers. Jabber servers can also talk with each other to form large domains of peers that are not directly connected to the same server. All communication among Jabber peers and servers takes the form of open XML-formatted messages sent over raw socket connections. (The specifications for these messages have been submitted to IETF.) As a result, Jabber servers and peers can be implemented independent of any platform. Jabber development libraries are available for the Java platform, C++, C#, Perl, Python, PHP, and even Flash.
The development of Jabber clients for J2ME devices, especially MIDP devices, is not trivial. Any MIDP Jabber client must bundle its own lightweight XML parser. In addition, the MIDP VM and underlying network must support raw socket connections. There are several MIDP 1.0-compatible Jabber clients or libraries available today:
- Al Sutton's KVMJab is an open source Jabber library for the MIDP platform. It provides a simple API for developing MIDP Jabber applications. Although the source code is available, you have to donate to KVMJab development before you can incorporate it in your commercial software.
- uppli's uMessenger is a fully featured Jabber IM client for MIDP. It also supports file sharing.
In this article, we discussed basic techniques and tools to extend JXTA and Jabber P2P networks to mobile peers. You should now be able to connect your mobile devices to large existing P2P communities through any TCP/IP-enabled wireless network.
After reading this series, you should understand why P2P is important to mobile applications, what P2P networks are available to mobile peers, and how to use J2ME tools to develop mobile P2P applications. Now you can add P2P features to your J2ME game or enterprise applications and get ready for the boom of mobile commerce in 2003!
-
Part 1 of this series discusses mobile P2P messaging using SMS.
-
developerWorks has published a three-part series of articles on JXTA by Sing Li:
- "The JXTA story" (August 2001)
- "The JXTA command shell" (September 2001)
- "Creating JXTA systems" (April 2002)
-
Read Gerhard Poul's developerWorks article, "Jabber: Instant messaging for e-business" (April 2002), for a technical introduction on Jabber.
-
General information on JXTA is available from the official JXTA Web site.
-
For more on JXME specifically, check out the JXME Web site.
-
Examine the Sun Project JXTA Software License to find out how to use JXTA code in your commercial applications.
-
Download stable JXME code, including the examples discussed in this article.
-
Read these instructions to find out how to run and build the JXME demo application using the Ant build tool.
-
Check out project JXTA's CVS repository for the latest JXME source code download.
-
Visit the official Jabber Web site, which includes a Jabber client library.
Michael J. Yuan is a PhD candidate at the University of Texas at Austin. He is the author of an upcoming Prentice Hall book, Java Mobile Enterprise Application Development. You can contact him at juntao@mail.utexas.edu.



