Hello JXTA
Let's start with building something simple, a service that will run in the Java binding, open a listening input pipe, and wait until a message has been received from the pipe. The service will also provide a single method that can be invoked to find a random peer's hello service input pipe and then send it a single message.
HelloService
First we have to define the interface that the Service is going to
export to any application running within the platform. We're going to
build a very simple one, only providing a single method that finds a
peer running HelloService, opens a pipe to it, and sends
it a small message.
public interface HelloService
extends net.jxta.service.Service {
// find another peer to send a message to, then send
// it a message
public void sendMessage();
}
HelloServiceImpl
Next we need to provide an implementation of the service for the platform to run. Initialization of this service should be dealt with first.
public class HelloServiceImpl
extends Object
implements HelloService {
// a handle to the discovery service
private Discovery discovery;
// a handle to the pipe management service
private Pipe pipes;
// the peer group that this service is being
// booted into
private PeerGroup peerGroup;
// the advertisement for the peer group
private PeerGroupAdvertisement peerGroupAdvertisement;
// the advertisement for this service
private ServiceAdvertisement serviceAdvertisement;
// the advertisement
private PipeAdvertisement helloPipeAdvertisement;
// initialize this service
public void init( PeerGroup group, Advertisement advertisement )
throws PeerGroupException {
// save away all the variables given to us
this.peerGroup = group;
this.peerGroupAdvertisement = group.getAdvertisement();
this.serviceAdvertisement = (ServiceAdvertisement)advertisement;
// get handles to the services that we are going to need later
this.discovery = this.peerGroup.getDiscovery();
this.pipes = this.peerGroup.getPipe();
// start the application running
startApp( null );
}
// provide the ability to get a handle to this
// service. in more robust services, a proxy object
// should be passed out to protect the service from
// malicious applications
public Service getInterface() {
return this;
}
// simply return the service advertisement that
// has been passed to us
public Advertisement getAdvertisement() {
return this.serviceAdvertisement;
}
Next we provide a method to start the service. This service
creates a pipe to listen for incoming messages. When it gets a
message, it writes to System.out who sent the message.
Before we open the pipe, however, we need to publish the pipe
advertisement into the peer group so that other peers may find it.
// a simple helper function that will create a pipe advertisement
// for the input pipe that we are going to open up
private PipeAdvertisement createPipeAdvertisement() {
try {
// create the pipe advertisement object
PipeAdvertisement pipeAdvertisement = (PipeAdvertisement)AdvertisementFactory.newAdvertisement( PipeAdvertisement.getAdvertisementType() );
pipeAdvertisement.setPipeID( new PipeID( this.peerGroup.getID() ) );
// create a simple name for the pipe that we can do
// an easy lookup on when we are searching later on
pipeAdvertisement.setName( "HelloService:" + this.peerGroup.getPeerID() );
return pipeAdvertisement;
} catch( InvocationTargetException error ) {
System.err.println( "problem creating the pipe advertisement" );
return null;
}
}
// the input pipe that this service is going to be
// listening on
private InputPipe helloPipe;
// the thread that the service is going to be
// running within
private Thread runningThread;
// start this service -- calling this method will spawn
// a thread that we can use to listen for messages coming
// down the pipe
public int startApp( String[] arguments ) {
// create the pipe that we are going to use to listen for
// messages
try {
// now we are going to publish the pipe that we are
// going to use both in our local cache and into the
// caches of the other peers in this peer group
this.helloPipeAdvertisement = createPipeAdvertisement();
if( this.helloPipeAdvertisement == null )
throw new PeerGroupException();
this.discovery.publish( this.helloPipeAdvertisement, Discovery.ADV );
this.discovery.remotePublish( this.helloPipeAdvertisement, Discovery.ADV );
// create the input pipe that we can use
this.helloPipe = this.pipes.createInputPipe( this.helloPipeAdvertisement );
} catch( IOException error ) {
System.err.println( "problem publishing the advertisement for the input pipie" );
} catch( Exception error ) {
System.err.println( "problem opening the pipe to read from" );
} finally {
if( this.helloPipe == null ) {
System.err.println( "do not have a pipe to read from" );
return 1;
}
}
// start a listening thread that constantly listens
// for messages on the input pipe. as a standard, we choose to
// format our messages with a "sender" symbolic name that
// contains the peer id that sent us the message. when
// a message comes down the pipe, we will just write
// something to System.out
this.runningThread = new Thread( new Runnable() {
public void run() {
try {
// block until we receive a message
Message message = null;
while( ( message = HelloServiceImpl.this.helloPipe.waitForMessage() ) != null ) {
// see if this thread has been
// interrupted
if( Thread.isInterrupted() )
break;
// read the sender information
InputStream senderInputStream = message.pop( "sender" );
byte[] senderBytes = new byte[senderInputStream.available()];
senderInputStream.read( senderBytes );
String sender = new String( senderBytes );
// print out the information from this message
System.out.println( "\"" + sender + "\" says hello" );
}
} catch( IOException error ) {
System.err.println( "problem reading from the input pipe" );
} finally {
HelloServiceImpl.this.helloPipe.close();
}
}
});
// start running the listening thread
this.runningThread.start();
return 0;
}
// the corresponding method to startApp -- this
// interrupts the currently running thread
public void stopApp() {
if( this.runningThread != null )
this.runningThread.interrupt();
}