Skip to main content

How to create a peerGroupService

7 replies [Last post]
Joined: 2007-01-11

Hi, i'd like to create a peerGroupService, but i don't know how...the JxtaProgGuide doesn't explain it, and other books i have, like Jxta in a nutshell are out of date...can anyone help me with an example??

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2007-05-27


I am new to jxta and tried to get trough the examples, but I find it very difficult to understand the Rendezvous-concept in total. In that Restaurant example you implemented the interface RendezvousListener and registered to the RendezvousService, but the method waitForRendezvousConnection is never called. Is that right? So, what is the meaning of the RendezvousService in this configuration?

And what about the RendezvousEvent.BECAMERDV - Event. Do a normal Edge-Peer configure itself becomming a rendezvous-Peer or do I have to do this programmaticly?

In the case I want to configure a Peer to be a Rendezvous-Peer, do I have to do anything else, than

manager = new NetworkManager(NetworkManager.ConfigMode.RENDEZVOUS, "RdPeer");
PeerGroup netPeerGroup = manager.getNetPeerGroup();

I tried that, but the peers waiting for a rendezvous connection never found one. I am really confused and would be glad, if anyone can help me. Thank's a lot.

Joined: 2007-01-11

Hi tra (I'm writing to you, cause it seem that you're the only one able to help me!)...only now i've seen your posted code in details, and it looks like a simple example of publishing a PeerService, not a PeerGroupService...isn't it??

Joined: 2007-05-22

Hello everybody,

I attach chapter10.jar with a slightly modified version of a sample from Brendon J. Wilson's book showing how to create and use peer group service. It is the only sample of a peer group service that I was able to find. This sample works fine for me with JXTA 2.4.1 on my local network. However, when I try to run it on the Internet, the sample started on one machine fails to find the new peer group which was created by the sample previously started on another machine. This is surprising given that I am certain that I have connectivity between these two computers - I can ping these computers using the ping shell command defined in Daniel Brookshier's book.

Also JXTA JXSE 2.5RC2 "Pavlova" Release Announcement states:
"- For the authors of Peer Group services, there have been important changes in how services are started. Services which depended upon being able to get references to other services in their init() method will now fail." In fact, when I try this sample with JXSE 2.5RC2 it throws some exceptions and fails to even start.

Knowing how to correctly define a new peer group service is absolutely crucial for my application. I would highly appreciate some samples on this topic.



Joined: 2007-01-11

thanks tra, you're great!!!!

Message was edited by: papelito

Joined: 2003-06-16

> Hi, i'd like to create a peerGroupService, but i
> don't know how...the JxtaProgGuide doesn't explain
> it, and other books i have, like Jxta in a nutshell
> are out of date...can anyone help me with an example??
I recently updated the tutorials from the book. Here is
one of the example for PeerGroupService.



import java.util.*;

import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.exception.PeerGroupException;
import net.jxta.document.AdvertisementFactory;
import net.jxta.document.StructuredDocumentFactory;
import net.jxta.document.Advertisement;
import net.jxta.document.Element;
import net.jxta.document.MimeMediaType;
import net.jxta.document.StructuredDocument;
import net.jxta.document.StructuredTextDocument;
import net.jxta.document.StructuredDocumentUtils;
import net.jxta.discovery.DiscoveryService;
import net.jxta.pipe.PipeService;
import net.jxta.pipe.InputPipe;
import net.jxta.pipe.OutputPipe;
import net.jxta.pipe.PipeID;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.protocol.PeerGroupAdvertisement;
import net.jxta.protocol.ModuleImplAdvertisement;
import net.jxta.protocol.ModuleClassAdvertisement;
import net.jxta.protocol.ModuleSpecAdvertisement;
import net.jxta.endpoint.Message;
import net.jxta.platform.ModuleClassID;
import net.jxta.platform.ModuleSpecID;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.rendezvous.RendezvousListener;
import net.jxta.peergroup.NetPeerGroupFactory;
import net.jxta.credential.AuthenticationCredential;
import net.jxta.credential.Credential;
import net.jxta.impl.membership.pse.StringAuthenticator;
import net.jxta.platform.NetworkConfigurator;
import net.jxta.membership.InteractiveAuthenticator;
import net.jxta.membership.MembershipService;
import net.jxta.rendezvous.RendezVousService;
import net.jxta.rendezvous.RendezvousEvent;

// RestoPeer represents a restaurant that receives auction requests
// for french fries from HungryPeers. RestoPeers offers three sizes of
// french fries (small, large, medium). Each restaurant assignes a
// different price to each size. Each restaurant also offers a special
// offering.
// Each resturant is uniquely identified by its brand name.

public class RestoPeer {

transient NetworkManager manager; // Network manager
private PeerGroup netpg = null; // The NetPeerGroup
private PeerGroup restoNet = null; // The restoNet Peergroup

private String brand = "Chez JXTA"; // Brand of this restaurant
private String specials = "large ($3.00)"; // Current restaurant special

// Services within the RestoNet peergroup
private DiscoveryService disco = null; // Discovery service
private PipeService pipes = null; // Pipe service
private PipeAdvertisement myAdv = null; // My RestoPeer pipe advertisement
private InputPipe pipeIn = null; // Input pipe that we listen to
// for requests from Hungry Peers

private int timeout = 3000; // discovery wait timeout
private int rtimeout = 8000; // resolver pipe timeout

public static void main(String args[]) {
RestoPeer myapp = new RestoPeer();

// Method to start the JXTA platform, join the RestoNet peergroup and
// advertise the RestoPeer service
private void startJxta() {

manager = new NetworkManager("RestoPeer");
manager.start("principal", "password");
//Get the NetPeerGroup
netpg = manager.getNetPeerGroup();
manager.login(netpg, "principal", "password");
System.out.println("Peer Name " + netpg.getPeerName());

// Discover (or create) and join the RestoNet peergroup
try {
} catch (Exception e) {
System.out.println("Can't join or create RestoNet");

// Discover (or create) and publish a RestoPeer pipe to receive
// auction request for fries from HungryPeers
if (!createRestoPipe()) {
System.out.println("Aborting due to failure to create RestoPeer pipe");

// Advertise the RestoPeerService

// Start the RestoPeer server loop to respond to Hungry peers
// fries requests.

// Discover (or create) and join the RestoNet peergroup
private void joinRestoNet() throws Exception {

int count = 3; // maximun number of attempts to discover
System.out.println("Attempting to Discover the RestoNet PeerGroup");

// Get the discovery service from the NetPeergroup
DiscoveryService hdisco = netpg.getDiscoveryService();

Enumeration ae = null; // Holds the discovered peers

// Loop until wediscover the RestoNet or
// until we've exhausted the desired number of attempts
while (count-- > 0) {
try {
// search first in the peer local cache to find
// the RestoNet peergroup advertisement
ae = hdisco.getLocalAdvertisements(DiscoveryService.GROUP,
"Name", "RestoNet");

// If we found the RestoNet advertisement we are done
if ((ae != null) && ae.hasMoreElements())

// If we did not find it, we send a discovery request
DiscoveryService.GROUP, "Name", "RestoNet", 1, null);

// Sleep to allow time for peers to respond to the
// discovery request
try {
} catch (InterruptedException ie) {}
} catch (IOException e){
// Found nothing! Move on

PeerGroupAdvertisement restoNetAdv = null;

// Check if we found the RestoNet advertisement.
// If we didn't, then either
// we are the first peer to join or
// no other RestoNet peers are up.
// In either case, we must create the RestoNet peergroup

if (ae == null || !ae.hasMoreElements()) {
"Could not find the RestoNet peergroup; creating one");
try {
// Create a new, all-purpose peergroup.
ModuleImplAdvertisement implAdv =

restoNet = netpg.newGroup(
null, // Assign new group ID
implAdv, // The implem. adv
"RestoNet", // Name of peergroup
"RestoNet, Inc.");// Description of peergroup

// Get the PeerGroup Advertisement
restoNetAdv = netpg.getPeerGroupAdvertisement();

} catch (Exception e) {
System.out.println("Error in creating RestoNet Peergroup");
throw e;
} else {
// The RestoNet advertisement was found in the cache;
// that means we can join the existing RestoNet peergroup

try {
restoNetAdv = (PeerGroupAdvertisement) ae.nextElement();
restoNet = netpg.newGroup(restoNetAdv);
"Found the RestoNet Peergroup advertisement");
} catch (Exception e) {
System.out.println("Error in creating RestoNet PeerGroup from existing adv");
throw e;

try {
// Get the discovery and pipe services for the RestoNet Peergroup
disco = restoNet.getDiscoveryService();
pipes = restoNet.getPipeService();
} catch (Exception e) {
System.out.println("Error getting services from RestoNet");
throw e;

System.out.println("RestoNet Restaurant (" + brand + ") is on-line");

// Method to handle fries auction requests from HungryPeers.
// The method waits for HungryPeer requests pipe messages to arrive.
// Incoming requests contain a pipe advertisement to respond to
// the HungryPeers requester and a fries size. The method
// generates a bid offer for the request, opens an output pipe to
// the HungryPeer requester, and send the response.
private void handleFriesRequest() {

InputStream ip = null; // Input Stream to read message
PipeAdvertisement hungryPipe = null; // HungryPeer Requester pipe

StructuredDocument request = null; // Request document
StructuredDocument bid = null; // Response document
// Document mime types
MimeMediaType mimeType = new MimeMediaType("text", "xml");
Element el = null; // Element in document
String name = null; // Name of the sender
String size = null; // Fries size Requested
OutputPipe pipeOut = null; // Output pipe to respond to
// HungryPeer requester

System.out.println("RestoNet Restaurant (" + brand +
") waiting for HungryPeer requests");

// Loop waiting for HungryPeer Requests
while (true) {
Message msg = null; // Incoming pipe message
try {
// Block until a message arrive on the RestoPeer pipe
msg = pipeIn.waitForMessage();
// If message is null discard message
if (msg == null) {
if (Thread.interrupted()) {
// We have been asked to stop
System.out.println("Abort: RestoPeer interrupted");

// We received a message; extract the request
try {
// Extract the HungryPipe pipe information
// to reply to the sender
ip = msg.getMessageElement(null, "HungryPeerPipe").getStream();

// Construct the associated pipe advertisement
// via the AdvertisementFactory
hungryPipe = (PipeAdvertisement)
AdvertisementFactory.newAdvertisement(mimeType, ip);

// Extract the sender name and fries size requested
// building a StructuredDocument
ip = msg.getMessageElement(null, "Request").getStream();
request = StructuredDocumentFactory.newStructuredDocument
(mimeType, ip);

// Extract the fields from the structured Document
Enumeration enumn = request.getChildren();

// Loop over all the elements of the document
while (enumn.hasMoreElements()) {
el = (Element) enumn.nextElement();
String attr = (String) el.getKey();
String value = (String) el.getValue();

// Extract the HungryPeer Requester Name
if (attr.equals("Name")) {
name = value;

// Extract the Fries size requested
else if (attr.equals("Fries")) {
size = value;
} catch (Exception e) {
continue; // Broken content; silently discard

System.out.println("Received Request from HungryPeer "
+ name
+ " for "
+ size
+ " Fries.");

// The auction request is valid. We can
// create the output pipe to send the response bid to
// the HungryPeer requester
try {
"Attempting to create Output Pipe to HungryPeer " +

// Create an output pipe connection to the HungryPeer
pipeOut = pipes.createOutputPipe(hungryPipe,
// Check if we have a pipe
if (pipeOut == null) {
// Cannot conect the pipe
System.out.println("Could not find HungryPeer pipe");
} catch (Exception e) {
// Pipe creation exception
System.out.println("HungryPeer may not be listening anymore");

// We have a pipe connection to the HungryPeer.
// Now create the Bid Response document
try {
// Construct the Response document
bid = StructuredDocumentFactory.newStructuredDocument(

// Set the Bid values (Brand, price, special)
// in the response document
el = bid.createElement("Brand", brand);
el = bid.createElement("Price", friesPrice(size));
el = bid.createElement("Specials", specials);

// Create a new pipe message
msg = new Message();

// Push the Bid offer in the message
StringMessageElement sme =
new StringMessageElement("Bid", bid.toString(), null);
msg.addMessageElement((String) null, sme);

// Send the message

// Close the output pipe connection
} catch (Exception ex) {
"Error sending bid offer to HungryPeer " + name);

System.out.println("Sent Bid Offer to HungryPeer (" + name +
") Fries price = " + friesPrice(size) +
", special = " + specials);
} catch (Exception e) {
System.out.println("Abort RestoPeer interrupted");

// Determine the price of the French fries depending on the size
private String friesPrice(String size) {
if (size.equals("small"))
return "$1.50";
if (size.equals("medium"))
return "2.50";
if (size.equals("large"))
return "3.00";
return "error";

// This routine creates a Module Spec advertisement to be
// associated with a RestoPeer
private void createRestoPeerService() {
try {
// First create the Module class advertisement associated
// with the service.
// The Module class advertisement is used
// to advertise the existence of the service.
// In order to access the service, a
// peer will have to discover the associated module spec
// advertisement.
ModuleClassAdvertisement mcadv = (ModuleClassAdvertisement)

mcadv.setName("JXTAMOD:RestoNet:Service:" + brand);
mcadv.setDescription("RestoPeer service");

ModuleClassID mcID = IDFactory.newModuleClassID();

// Publish the Module Class advertisement
// it in my local cache and to my peergroup.

// Create the Module Spec advertisement associated
// with the service.
// The Module Spec advertisement will contain
// all the information necessary for a client to contact
// the service; for instance it will contain a pipe
// advertisement to be used to contact the service
ModuleSpecAdvertisement mdadv = (ModuleSpecAdvertisement)

// Set up some of the information field about the
// service. In this example, we set the name,
// provider and version and a pipe advertisement. The
// module creates an input pipes to listen on this pipe
// endpoint.
mdadv.setName("JXTASPEC:RestoNet:Service:" + brand);
mdadv.setVersion("Version 1.0");

// Set a pipe advertisement for the Service. The pipe is
// used as the mean to communicate with the service. The
// HungryPeer client MUST use this pipe to talk the
// service.
// The pipe advertisement is stored in the service advertisement
// params; the client retrieves it from the params.

// Display the advertisement as a plain text dcoument.
StructuredTextDocument doc = (StructuredTextDocument)
mdadv.getDocument(new MimeMediaType("text/plain"));
StringWriter out = new StringWriter();

// Publish the service advertisement
} catch (Exception ex) {
System.out.println("Error publishing RestoPeer Advertisement");

// Create the resto pipe associated with this RestoPeer.
// Discover first if a pipe advertisement exists, if
// not create and publish it.
private boolean createRestoPipe() {

int count = 3; // Discovery retry count
Enumeration ae = null; // Discovery response enumeration

try {

System.out.println("Attempting to Discover the Restaurant RestoPipe");

// get the discovery and pipe services for the RestoNet Peergroup
disco = restoNet.getDiscoveryService();
pipes = restoNet.getPipeService();

// check if I have already published myself
// one should always check if the advertisement
// is there
while (count-->0) {
try {

// check first locally if we have the advertisement cached
ae = disco.getLocalAdvertisements(DiscoveryService.ADV
, "name"
, "RestoNet:RestoPipe:"
+ brand);

// if we find our pipe advertisement we are done
// no need to create one
if (ae != null && ae.hasMoreElements()) {

// we did not find the advertisement locally, let's
// send a remote request
DiscoveryService.ADV, "name",
"RestoNet:RestoPipe:" + brand, 1, null);

// nothing really to do here, so
// wait a little to give a chance for the request
// to come back
try {
} catch (Exception e){
} catch (IOException e){
// found nothing! move on

// we searched for our pipe advertisement we could not find
// one so let's go an create one
if (ae == null || !ae.hasMoreElements()) {
"Could not find the Restaurant Pipe Advertisement");

// Create a pipe advertisement for our RestoPeer
myAdv = (PipeAdvertisement)
PipeAdvertisement.getAdvertisementType() );

// assign a unique ID to the pipe

// the sympolic name of the pipe is build from
// the brand name of RestoPeer. So each RestoPeer
// as a unique name.
myAdv.setName("RestoNet:RestoPipe:" + brand);

// set the type of the pipe

// we have the advertisement, we can publish
// our pipe advertisement into our local cache
// and to the RestoNet PeerGroup

System.out.println("Created the Restaurant Pipe Advertisement");

} else {

// we got it so we do not need to create one
myAdv = (PipeAdvertisement) ae.nextElement();
System.out.println("Found Restaurant Pipe Advertisement");

// create my input pipe to listen for hungry peers
// requests
pipeIn = pipes.createInputPipe(myAdv);

} catch (Exception e) {
System.out.println("Could not initialize the Restaurant pipe");
return false;

return true;
* A simple and re-usable exmaple of starting and stopping a JXTA platform
* @author Mohamed Abdelaziz (hamada)
* @created December 17, 2005

public class NetworkManager implements RendezvousListener {

private PeerGroup netPeerGroup = null;
private boolean started = false;
private boolean stopped = false;
private RendezVousService rendezvous;
private final Object connectLock = new Object();
private String instanceName = "NA";
private final File home = new File(System.getProperty("JXTA_HOME", ".cache"));

* A simple and re-usable exmaple of starting and stopping a JXTA platform
* @param instanceName Node name
public NetworkManager(String instanceName) {
this.instanceName = instanceName;

* Creates and starts the JXTA NetPeerGroup using a platform configuration
* template. This class also registers a listener for rendezvous events
* @param principal principal used the generate the self signed peer root cert
* @param password the root cert password
public synchronized void start(String principal, String password) {
if (started) {
try {
File instanceHome = new File(home, instanceName);
NetworkConfigurator config = new NetworkConfigurator();
if (!config.exists()) {
config.setDescription("Created by Network Manager");
try {

// config.addRdvSeeding(new URI(""));
// config.addRelaySeedingURI(new URI(""));
} catch ( use) {
try {;
} catch (IOException io) {
} else {
try {
File pc = new File(config.getHome(), "PlatformConfig");
} catch (Exception ex) {
// create, and Start the default jxta NetPeerGroup
NetPeerGroupFactory factory = new NetPeerGroupFactory(config.getPlatformConfig(), instanceHome.toURI());
netPeerGroup = factory.getInterface();
System.out.println("Node PeerID :" + netPeerGroup.getPeerID().getUniqueValue().toString());
rendezvous = netPeerGroup.getRendezVousService();
started = true;
} catch (PeerGroupException e) {
// could not instantiate the group, print the stack and exit
System.out.println("fatal error : group creation failure");

* Establishes group credential. This is a required step when planning to
* to utilize TLS messegers or secure pipes
* @param group peer group to establish credentials in
* @param principal the principal
* @param password pass word
public void login(PeerGroup group, String principal, String password) {
try {
StringAuthenticator auth = null;
MembershipService membership = group.getMembershipService();
Credential cred = membership.getDefaultCredential();
if (cred == null) {
AuthenticationCredential authCred = new AuthenticationCredential(group, "StringAuthentication", null);
try {
auth = (StringAuthenticator) membership.apply(authCred);
} catch (Exception failed) {

if (auth != null) {
if (auth.isReadyForJoin()) {

cred = membership.getDefaultCredential();
if (null == cred) {
AuthenticationCredential authCred = new AuthenticationCredential(group, "InteractiveAuthentication", null);
InteractiveAuthenticator iAuth = (InteractiveAuthenticator) membership.apply(authCred);
if (iAuth.interact() && iAuth.isReadyForJoin()) {
} catch (Throwable e) {
// make sure output buffering doesn't wreck console display.
System.err.println("Uncaught Throwable caught by 'main':");
} finally {

* Stops and unrefrences the NetPeerGroup
public synchronized void stop() {
if (stopped && !started) {
netPeerGroup = null;
stopped = true;

* Gets the netPeerGroup object
* @return The netPeerGroup value
public PeerGroup getNetPeerGroup() {
return netPeerGroup;

* Blocks if not connected to a rendezvous, or
* until a connection to rendezvous node occurs
* @param timeout timeout in milliseconds
public void waitForRendezvousConncection(long timeout) {
if (!rendezvous.isConnectedToRendezVous() || !rendezvous.isRendezVous()) {
System.out.println("Waiting for Rendezvous Connection");
try {
if (!rendezvous.isConnectedToRendezVous()) {
synchronized (connectLock) {
System.out.println("Connected to Rendezvous");
} catch (InterruptedException e) {
System.out.println("thread interrupted");

* rendezvousEvent the rendezvous event
* @param event rendezvousEvent
public void rendezvousEvent(RendezvousEvent event) {
if (event.getType() == RendezvousEvent.RDVCONNECT ||
event.getType() == RendezvousEvent.RDVRECONNECT ||
event.getType() == RendezvousEvent.BECAMERDV) {
switch (event.getType()) {
case RendezvousEvent.RDVCONNECT:
System.out.println("Connected to rendezvous peer :" + event.getPeerID());
case RendezvousEvent.RDVRECONNECT:
System.out.println("Reconnected to rendezvous peer :" + event.getPeerID());
case RendezvousEvent.BECAMERDV:
System.out.println("Became a Rendezvous");
synchronized (connectLock) {

Joined: 2007-02-04

Hi tra.

Thanks for the code example. I've been trying to use it and other examples but keep getting the following error, which suggests to me that maybe I have an out-of-date minimalBC.jar - is that correct? If so, where can I get the latest version?

Exception in thread "main" java.lang.NoSuchMethodError: org.bouncycastle.jce.X509Principal.getEncoded()[B
at net.jxta.impl.membership.pse.PSEUtils.genCert(
at net.jxta.platform.NetworkConfigurator.createPSEAdv(
at net.jxta.platform.NetworkConfigurator.getPlatformConfig(

Joined: 2007-01-25

I guess, you can find latest version of Bouncy Castle Crypto APIs here: