|
![]() |
This example implements a very simple client-server application. A client object display a String
received from a remote server.
We will see how to write classes from which active and remote objects can be created, how to find a remote object and how to invoke methods on remote objects.
Only two classes are needed: one for the server object Hello
and one for the client that accesses it HelloClient
.
This class implements server-side functionalities. Its creation involves the following steps:
main
method in order to instantiate one server object and register it with an URL.
Here is a possible implementation for the Hello
class:
Hello.java |
---|
public class Hello { private String name; private String hi = "Hello world"; private java.text.DateFormat dateFormat = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); public Hello() { } public Hello(String name) { this.name = name; } public String sayHello() { return hi + " at " + dateFormat.format(new java.util.Date())+ " from node : " + ProActive.getBodyOnThis().getNodeURL(); } public static void main(String[] args) { // Registers it with an URL try { // Creates an active instance of class HelloServer on the local node Hello hello = (Hello)org.objectweb.proactive.ProActive.newActive(Hello.class.getName(), new Object[]{"remote"}); java.net.InetAddress localhost = java.net.InetAddress.getLocalHost(); org.objectweb.proactive.ProActive.register(hello, "//" + localhost.getHostName() + "/Hello"); } catch (Exception e) { System.err.println("Error: " + e.getMessage()); e.printStackTrace(); } } } |
Implementing any remotely-accessible functionality is simply done through normal Java methods in a normal Java class, in exactly the same manner it would have been done in a non-distributed version of the same class. This has to be contrasted with the RMI approach, where several more steps are needed:
java.rmi.server.UnicastRemoteObject
, which is the root class of all remote objects.
You may have noticed that class Hello
has a constructor with no parameters and an empty implementation. The presence of this empty no-arg
constructor is imposed by ProActive and is actually a side-effect of ProActive's transparent implementation of active remote objects (as a matter of fact, this
side-effect is caused by ProActive being implemented on top of a 100% Java metaobject protocol). If no such constructor is provided, active objects cannot be created.
If no constructor at all is provided, active objects can still be created because, in this specific case, all Java compilers provide
a default no-arg empty constructor. If a no-arg constructor is provided but its implementation is not empty, unwanted behavior may appear because the no-arg constructor
is always called when an active object is created, whatever code the user can write.
Hello
object
Now that we know how to write the class that implements the required server-side functionalities, let us see how to create the server object. In ProActive, there is actually no difference
between a server and a client object as both are remote objects.Creating the active object is done through instantiation-based creation. We want
this active object to be created on the current node, which is why we use newActive
with only two parameters. In
order for the client to obtain an initial reference onto this remote object, we need to register it in the registry (which is actually the well-known
rmiregistry
) with a valid RMI URL.
HelloClient
ClassHelloClient.java |
---|
public class HelloClient { public static void main(String[] args) { Hello myServer; String message; try { // checks for the server's URL if (args.length == 0) { // There is no url to the server, so create an active server within this VM myServer = (Hello)org.objectweb.proactive.ProActive.newActive(Hello.class.getName(), new Object[]{"local"}); } else { // Lookups the server object System.out.println("Using server located on " + args[0]); myServer = (Hello)org.objectweb.proactive.ProActive.lookupActive(Hello.class.getName(), args[0]); } // Invokes a remote method on this object to get the message message = myServer.sayHello(); // Prints out the message System.out.println("The message is : " + message); } catch (Exception e) { System.err.println("Could not reach/create server object"); e.printStackTrace(); System.exit(1); } } } |
The operation of lookup simply means obtaining a reference onto an object from the URL it is
bound to. The return type of method Proactive.lookupActive()
is Object
, then we need to cast it down into the type of the
variable that holds the reference (Hello
here). If no object is found at this URL, the call to Proactive.lookupActive()
returns
null
.
This is exactly like invoking a method on a local object of the same type. The user does not have to deal with catching
distribution-related exceptions like, for example, when using RMI or CORBA. Future versions of ProActive will provide an
exception handler mechanism in order to process these exceptions in a separate place than the functional code. As class String
is
final
, there cannot be any asynchronism here since the object returned from the call cannot be replaced by a
future object (this restriction on final
classes is imposed by ProActive's implementation).
As already stated, the only modification brought to the code by ProActive is located at the place where active objects are created. All the rest of the code remains the same, which fosters software reuse.
In order to run both the client and server in the same VM, the client creates an active object in the same VM if it doesn't find the server's URL. The code snippet which instantiates the Server in the same VM is the following:
if (args.length == 0) { // There is no url to the server, so create an active server within this VM myServer = (Hello)org.objectweb.proactive.ProActive.newActive(Hello.class.getName(), new Object[]{"local"}); }
To launch the Client and the Server, just type:
> java org.objectweb.proactive.examples.hello.Client &
main
method in the Hello
class.
> java org.objectweb.proactive.examples.hello.Hello &
> java org.objectweb.proactive.examples.hello.HelloClient //localhost/Hello
Hello
class.
remoteHost> java org.objectweb.proactive.examples.hello.Hello &
clientHost> java org.objectweb.proactive.examples.hello.HelloClient //remoteHost/Hello