Download Latest Version jelectro.jar (90.0 kB)
Email in envelope

Get an email when there's a new version of JElectro

Home
Name Modified Size InfoDownloads / Week
ReadMe 2013-04-20 7.4 kB
jelectro.zip 2013-04-20 333.9 kB
jelectro.jar 2013-04-20 90.0 kB
Totals: 3 Items   431.3 kB 0
JElectro II 

Project for Java Distributed RMI.


I am very proud to present you the release of April 20, 2013


What's this project :

That makes a lot of time I look for some cool way to connect two jvm instances and to call methods remotely.
I had, a few years ago, the idea to keep socket connected and to manage pull and push information between
client and server using the underlying input stream and output stream of the socket and creating a thread 
for the input stream.
After a while, I work on a project with which I was quite stuck with RMI : I couldn't connect to the client 
from the server.

JElectro comes from this need, to be able to contact client from an RMI server.

The first version, a little big young and strait was able to let two client communicating with each other. 
This means that a client could export a stub (in the RMI sense) and an other client could retrieve this stub and 
call its remote methods.

Last year, in 2012, a classical issue was triggered to me; and wass dealing with both sense connections and 
asynchronous calls. With my previous, it was necessary to have two stubs to be able to make asynchronous calls.
Classical example comes from SQL, when you want to retrieve results from a select but this request is taking some
time and you do not want to wait before printing those lines. 
A second small update introduced callbacks in remote calls. And this was solving this problematic. 


Today, I am really happy to present you my last update, in which there is no more client and server instances. 
All the instance are now both and can be both according to the way you implement them.
Moreover a routing table system allows you to connect instance to any instance you want. The result is a 
complete network with nodes (the JElectro instances) communicating with any other node of the JElectro network.
Let's say that you have 4 computers and two servers. You can build a network like this one :

    C1 --|          |--C3
         |--S1--S2--|
    C2 --|          |--C4
	
	
C1 is able to publish some stubs and C4 is able to see them and to call some remote methods.

Note also that all those nodes are instance of the same class JElectro.



How can you deal with the code :

Fist of all, you have to include the jelectro.jar library into your classpath... of course !

  
Create your first node with this line :
JElectro j1 = new JElectro();

Then activate it and make it waiting for connections :
j1.listenTo(12012);

From an other JVM, create your second node :
JElectro j2 = new JElectro();

Connect it the your first node :
j2.connectTo("IP from your first node", 12012);

And now export your first object like this : 
j2.bind("MyObject", myObject);


Look up for it :
List<MyObjectInterface> myRemoteObjects = j1.lookup("MyObject", MyObjectInterface.class);

and test it :
if (myRemoteObjects.size()> 0) 
	myRemoteObjects.get(0).classSomeMethod()...




A real example of code :


	// Create the first node :
	JElectro j1 = new JElectro();
	j1.listenTo(12001);
	
	// Create your object 
	// Add is an interface with one method add
	j1.bind("Add", new Add() {
	
		@Override
		public double add(double a, double b) {
			return a + b;
		}
	
	});
	
	
	
	// create your second node
	JElectro j2 = new JElectro();
	// And connect it to the first node :
	j2.connectTo("localhost", 12001);
	
	// look for your stub : 
	List<Add> adds = j2.lookup("Add", Add.class);
	
	
	//You have a list of all stubs that exists and that are called "Add".
	// If there are more than one stub, you can execute the one you want .
	System.out.println(adds.size());
	
	// Choose the one you create :
	Add add = adds.get(0);
	
	// And make some tests :
	double r = add.add(10, 20);
	// adds.get(0).add(10, 20);
	System.out.println(r);
	
	System.out.println(add.add(1, 20));
	
	System.out.println(add.add(10, 0xabc));
	
	System.out.println(add.add(10.0033, Math.PI));
	
	
	// shut down your two nodes.
	j1.disconnect();
	j2.disconnect();





Of course this is a non sense to execute this code in one JVM, but this presents you the principal property.



Concerning the callbacks that are a key feature at my eyes :


Let's first create a two interface interfaces :

The first one for the callback :

public interface PrimeCallback extends JElectroCallback {

	void onPrimeNumber(int prime);

	void done();

}


Note that it is necessary that this remote callback extends the interface JElectroCallback



A second one for the stub :

public interface PrimeNumbers {

	boolean getPrimeNumbers(int i, PrimeCallback callback);

}


and it's implementation :


public class PrimeNumbersImpl implements PrimeNumbers {

	@Override
	public boolean getPrimeNumbers(final int i, final PrimeCallback callback) {

		Thread t = new Thread() {
			public void run() {
				for (int p = 0; p <= i; p++) {

					if (isPrime(p)) {
						callback.onPrimeNumber(p);
						/*try {
							Thread.sleep(1);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}*/
					}

				}
				callback.done();
			}

		};

		t.start();
		return true;

	}

	private boolean isPrime(int p) {
		int sqrt = (int) Math.floor(Math.sqrt(p));
		for (int i = 2; i <= sqrt; i++) {
			if (p % i == 0)
				return false;
		}
		return true;
	}

}




Let's now create our two nodes and stubs :

		// JElectro throws exceptions. I capture them ... 
		try {
			
			// the first node instance :
			JElectro j1 = new JElectro();
			j1.listenTo(12001);

			// the second node instance  connected to the first one :
			JElectro j2 = new JElectro();
			j2.connectTo("localhost", 12001);


			// the primenumber calculator present on j1 node
			PrimeNumbersImpl primeNumber = new PrimeNumbersImpl();
			j1.bind("PrimeNumber", primeNumber);

			// The remote object of this prime number calculator.
			PrimeNumbers primeStub = j2.lookup("PrimeNumber", PrimeNumbers.class).get(0);
			
			// Just wait and avoid the jvm to shut down if you just do a test ...
			final Object waiter = new Object();
			
			
			// My result :
			// I want that the calculator give me all the prime number from 0 to 100
			boolean r = primeStub.getPrimeNumbers(100, new PrimeCallback() {

				long last = System.nanoTime();
				List<Long> timeList = new ArrayList<Long>();
				
				@Override
				public void onPrimeNumber(int prime) {
				
					//The calculator sent me a prime number :
					//I print it 
					System.out.println(( System.nanoTime() - last )+ " : " + prime);
					timeList.add(System.nanoTime() - last);
					last = System.nanoTime();
					
					
				}

				public void done() {
					
					// the calculator inform me that he has finish his job.
					
					for (long l : timeList) {
						System.out.println(l);
					}
					
					
					synchronized (waiter) {
						waiter.notifyAll();
					}
				}
			});

			System.out.println(r);

			// wait for the primeNumbers;
			synchronized (waiter) {
				waiter.wait();
			}

			System.out.println("done");

			j1.disconnect();
			j2.disconnect();

		} catch (Exception e) {

			e.printStackTrace();
			
		}



Source: ReadMe, updated 2013-04-20