public class Job implements java.io.Serializable{
String msg;
public Job(){
//Just to distinguish one job from the next
msg = Long.toString(System.currentTimeMillis());
}
public void process(){
//Put complex algorithm here
System.out.println("Job generated on server at: "+msg);
}
}
public interface JobQueue extends java.rmi.Remote{
//Get the next job on the queue
Job getJob() throws java.rmi.RemoteException;
}
import java.rmi.*;
import java.rmi.server.*;
public class JobQueueImpl extends UnicastRemoteObject
implements JobQueue {
public JobQueueImpl() throws RemoteException {
super();
try {
Naming.bind("rmi://localhost/JobQueue",this);
System.out.println("Server Ready");
} catch (Exception e){
System.err.println("Failed to start RMI server: "
+ e.getMessage());
}
}
//The method that will be invoked remotely by clients
public Job getJob(){
return new Job();
}
public static void main(String[] args){
try {
new JobQueueImpl();
} catch (RemoteException e){
System.err.println("Failed to start RMI server: "
+ e.getMessage());
}
}
}
import java.rmi.*;
public class Worker {
public Worker(){
try {
//Get a reference to the remote server on this machine
JobQueue queue = (JobQueue)Naming.lookup(
"rmi:///JobQueue");
//Request a job from the remote server
Job myJob = queue.getJob();
//Start processing the Job.
myJob.process();
} catch(Exception e){
System.err.println("Error connecting to server: "
+e.getMessage());
}
}
public static void main(String[] args){
new Worker();
}
}
This example is an extension on the previous example. This example assumes
that you may have more than one type of Job that you want processed
by client machines.
It illustrates how both local and remote objects can be extended. By creating
a new server object that extends from the previous JobQueueImpl we can re-use
code from the old server.
By extending the new Job types from the old Job type we don't need to modify
any of the client code.
public class Matrix extends Job {
public void process(){
System.out.println("Would be processing a matrix");
}
}
public class Prime extends Job {
public void process(){
System.out.println("Would be computing primes");
}
}
import java.rmi.*;To run the above example, simply place the three new files into the same directory as the first example, then run:
import java.rmi.server.*;
public class PolyJobQueueImpl extends JobQueueImpl {
int index = 1;
Job[] list = { new Matrix() , new Prime() };
public PolyJobQueueImpl() throws RemoteException {
//JobQueueImpl takes care of the binding for us
super();
}
//Polymorphically extend getJob to return the new Job types
public Job getJob(){
index = (index+1) % list.length; //Walk the index
return list[index];
}
public static void main(String[] args){
try {
new PolyJobQueueImpl();
} catch (RemoteException e){
System.err.println("Failed to start RMI server: "
+ e.getMessage());
}
}
}
For simplicity sake this example only allows a single client to register
but could be easily modified to store a collection of clients.
As this is a fairly drastic change in the design of this example,
most of the code has changed. The only code that remains the same is the Job
class.
public interface CallbackJobQueue extends java.rmi.Remote{
void register(CallbackWorker aClient) throws java.rmi.RemoteException;
}
import java.rmi.*;
import java.rmi.server.*;
public class CallbackJobQueueImpl extends UnicastRemoteObject
implements CallbackJobQueue {
CallbackWorker client;
public CallbackJobQueueImpl() throws RemoteException {
super();
try {
//Bind to the registry running on this machine
Naming.bind("rmi://lpc1.itec.uni-klu.ac.at/JobQueue",this);
System.out.println("Server Ready");
} catch (Exception e){
System.err.println("Failed to start RMI server: "
+ e.getMessage());
}
//Loop forever and give out jobs (better use wait/notify)
while(true){
if (client != null){
client.processJob(new Job());
}
try {
Thread.sleep(1000); //Sleep for a sec.
} catch(InterruptedException e){}
}
}
public void register(CallbackWorker aClient){
client = aClient;
}
public static void main(String[] args){
try {
new CallbackJobQueueImpl();
} catch (RemoteException e){
System.err.println("Failure with RMI server: "
+ e.getMessage());
}
}
}
public interface CallbackWorker extends java.rmi.Remote{
public void processJob(Job newJob) throws java.rmi.RemoteException;
}
import java.rmi.*;To run the above example, place all of the code into the directory with the previous examples and run the following commands:
import java.rmi.server.*;
public class CallbackWorkerImpl implements CallbackWorker{
public CallbackWorkerImpl(){
try {
UnicastRemoteObject.exportObject(this);
CallbackJobQueue server =
(CallbackJobQueue)Naming.lookup(
"rmi:///JobQueue");
//Register with the server, then just wait for jobs
server.register(this);
} catch (Exception e){
System.err.println("Failed to setup for RMI");
}
}
public void processJob(Job newJob){
newJob.process();
}
public static void main(String[] args){
new CallbackWorkerImpl();
}
}