Discovering Services using Multicast Objects

In this example we will locate a Service on the network using the Object Multicast feature of the ORB.

The server will create a multicast object and publish its object reference in COS Naming using the JNDI/COS provider. The client will get this object reference using JNDI and then invoke on it passing it a service name and a unicast callback object. The multicast object servant will get the object for the desired service and do a call back to the client to register the service.

Discoverable

All services that can be discovered will implement this interface. The discover method is called by the client to discover a service with a given name. A Discoverer interface is passed on this method so that the service can register itself back with the discoverer.

To make this more useful, the interface could also support service selection based on certain attributes.

package discovery;
                                                                           
import java.rmi.Remote;
import java.rmi.RemoteException;
                                                                           
public interface Discoverable extends Remote
{
    void discover(String serviceName, Discoverer discoverer)
        throws RemoteException;
}

Discoverable Implemetation

This implementation of the Discoverable interface is constructed using the service name and the service remote object. The discover method registers the service with the Discoverer, if the service name matches the requested service name.

package discovery;
                                                                           
import java.rmi.Remote;
import java.rmi.RemoteException;
                                                                           
public class DiscoverableImpl implements Discoverable
{
    private Remote _service;
    private String _serviceName;
                                                                           
    DiscoverableImpl(String serviceName, Remote service)
    {
    |   _service     = service;
    |   _serviceName = serviceName;
    }
                                                                           
    public void discover(String serviceName, Discoverer discoverer)
        throws RemoteException
    {
    |   if (_serviceName.equals(serviceName))
    |       discoverer.registerService(_service);
    }
}

Discoverer

The Discoverer interface is used as the callback by the program that wishes to discover a service.

package discovery;
                                                                           
import java.rmi.Remote;
import java.rmi.RemoteException;
                                                                           
public interface Discoverer extends Remote
{
    void registerService(Remote service) throws RemoteException;
}

Discoverer Implementation

This implementation of the Discoverer knows that the Hello service will register with it. It calls the sayHello method on the service.

package discovery;
                                                                           
import java.rmi.Remote;
import java.rmi.RemoteException;
                                                                           
import javax.rmi.PortableRemoteObject;
                                                                           
import helloWorld2.Hello;
                                                                           
public class DiscovererImpl extends PortableRemoteObject
    implements Discoverer
{
    public DiscovererImpl() throws RemoteException {}
                                                                           
    public void registerService(Remote service) throws RemoteException
    {
    |   Hello hello = (Hello) service;
    |   System.out.println(hello.sayHello());
    }
}

Server

The server first constructs a multicast Group, then it creates a Discoverable object and makes it join the Group. The object reference returned by joinGroup is published in COS Naming using JNDI. The server then hangs around waiting for invocations.

package discovery;
                                                                           
import util.Util;
                                                                           
import java.util.Hashtable;
import java.net.InetAddress;
                                                                           
import javax.naming.Context;
import javax.naming.InitialContext;
                                                                           
import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
                                                                           
import helloWorld2.Hello;
import helloWorld2.HelloImpl;
                                                                           
import com.sssw.jbroker.api.multicast.Group;
                                                                           
public class Server
{
    public static void main(String[] args)
    {
    |   try {
    |   |                                                                  
    |   |   // create the jBroker ORB
    |   |   ORB orb = ORB.init(args, null);
    |   |                                                                  
    |   |   // create a Group
    |   |   Group group = Group.createGroup(orb, InetAddress.
    |   |       getByName("230.0.0.1"), "discover");
    |   |                                                                  
    |   |   // create the discoverable
    |   |   Discoverable discoverable = new DiscoverableImpl(
    |   |       "hello", new HelloImpl());
    |   |                                                                  
    |   |   // make the discoverable join the Group
    |   |   Object objref = group.joinGroup(discoverable);
    |   |                                                                  
    |   |   // create the JNDI Environment
    |   |   Hashtable env = new Hashtable();
    |   |   env.put("java.naming.corba.orb", orb);
    |   |                                                                  
    |   |   // get the initial naming context
    |   |   Context ctx = new InitialContext(env);
    |   |                                                                  
    |   |   // bind the discoverable objref using JNDI
    |   |   ctx.rebind("discoverable", objref);
    |   |                                                                  
    |   |   // wait for invocations
    |   |   System.out.println("waiting for invocations ...");
    |   |   orb.run();
    |   |                                                                  
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
}

The multicast object reference published in the COS namespace can be viewed using the parseIOR utility:

   parseIOR iiopname://localhost/discoverable

The following information is dumped:

Type Id  = RMI:discovery.Discoverable:0000000000000000
Profiles = 1
    
    Multicast Object Protocol (MOP) Profile:

        version    = 1.0
        IP address = 230.0.0.1
        port       = 2506
        obj key    = 
            4A424B52 00050005 00000000 E6000001  JBKR........?...
            64697363 6F766572                    discover
        
        components = 1
            
            TAG_JBROKER_MULTICAST_TTL : 
                01                                   .

Note: The above IOR contains a Multicast Object Protocol Profile and that the TTL is 1. When the client invokes on this object reference, the ORB uses MOP instead of IIOP to talk to this object.

Client

The client just looks up the multicast object from the COS namespace using JNDI and then invokes the discover method on it passing a Discoverer callback object.

package discovery;
                                                                           
import util.Util;
                                                                           
import java.util.Hashtable;
                                                                           
import javax.naming.Context;
import javax.naming.InitialContext;
                                                                           
import org.omg.CORBA.ORB;
                                                                           
public class Client
{
    public static void main(String[] args)
    {
    |   try {
    |   |                                                                  
    |   |   // create the jBroker ORB
    |   |   ORB orb = ORB.init(args, null);
    |   |                                                                  
    |   |   // create the JNDI Environment
    |   |   Hashtable env = new Hashtable(5, 0.75f);
    |   |   env.put("java.naming.corba.orb", orb);
    |   |                                                                  
    |   |   // get the initial naming context
    |   |   Context ctx = new InitialContext(env);
    |   |                                                                  
    |   |   // lookup the Discoverable objref
    |   |   Discoverable discoverable = (Discoverable) ctx.
    |   |       lookup("discoverable");
    |   |                                                                  
    |   |   // discover hello object(s)
    |   |   discoverable.discover("hello", new DiscovererImpl());
    |   |                                                                  
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
}

The server will callback on the passed object to register the Hello service and the client will invoke the sayHello method on it printing Hello World! on the screen.



Copyright © 2003, 2004 Novell, Inc. All rights reserved. Copyright © 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.