GHads mind

developers thoughts & finds

Archive for the ‘Java development’ Category

Introducing GW2co.net – GuildWars2 Commander Overlay

leave a comment »

Hi folks,

as the creator of http://www.gw2co.net I’m using my blog to promote this little goody 🙂

What is it? It’s a windows 7+ application/overlay above GuildWars2 showing timers and team movements for a game mode called World vs. World. Here three home worlds/servers combat each other player vs. player for a week by killing other raids or conquering castles, towers and supply camps.

GW2co.net now enriches this in multiple ways:

– Cooperative team play by seeing where other teams are heading to. You may have a coordinater in Teamspeak ordering teams to go here and there
– Know beforehand if the camp you’re heading to with your raid still has a timer
– Predict enemy movements be looking at the map overview
– Allows for visibile scouts too so a leader can see which objectives are protected by manpower
– Getting infos about who has claimed an objective and how long it is held

The cool thing about this is the work-out-of-the box character. You as GW2 player just fire up the game and join a WvW map. The GW2co.net Client (after you logged in) can automaticly pick up the map and your character and will (not yet implemented) place you into the correct team based on the leaders teamname and your login. There is nearly zero interaction needed but the team leader will see the new player as a team member.

The client is free and our complete server infrastructure that is able to support thousands of players at the same time costs (incl. Domain) not even 10$ a month. On the technology side we are using many technologies like ZeroMQ, Google AppEngine with Gaelyk and Protocolbuffers. We’ve overcome OS and program language boundaries and created a secure communication over an unsecure tcp socket. There were many challanges and I hope to have the time to blog details here about some of them.

It took me and a friend (plus some recently joined supporters) a year now from idea to the current closed Beta Version and I hope a public Beta for my whole home world “Elonareach” will be ready within four weeks.

Stay tuned,
GHad

Advertisements

Written by ghads

June 23, 2014 at 3:53 pm

Blocking parallel Runnable execution in Java

leave a comment »

Been quite busy lately… But finally a new post:

Ok, let’S get started. For a new approch of updating MongoDB parallel I’m partitioning a SQL-Query and want those queries to execute parallel with worker threads. But i have actions before and after the execution point so I must wait until the last of the workers is done. This can be done with the method of the previous post, but only in a completly asynchronoius way. What I want for this is a blocking way:

  • Put together a list of Runnable workers
  • Call a method to execute those workers parallel
  • The method blocks until all workers are finished

As bonus I do not want to use any concurrent specific constructs inside the threads. A direct call to on workers run() method should behave exactly like a call to the new method with this worker in the parameters list only.

	public static void execute(Collection<Runnable> workers)
			throws Exception
	{
		if (workers == null || workers.isEmpty()) {
			throw new IllegalArgumentException("null or empty");
		}
		final Exception[] exception = new Exception[]{ null };
		final CountDownLatch latch = new CountDownLatch(workers.size());
		final ExecutorService threadPool = Executors.newFixedThreadPool(workers.size() * 2);
		for (final Runnable worker : workers)
		{
			threadPool.submit(new Runnable()
			{
				public void run()
				{
					try
					{
						threadPool.submit(worker).get();
					}
					catch (Exception e)
					{
						exception[0] = e;
					}
					finally
					{
						latch.countDown();
					}
				}
			});
		}
		System.out.println("...now lock");
		latch.await();
		threadPool.shutdownNow();
		if (exception[0] != null) {
			throw exception[0];
		}
	}

Step by step: First the argument is checked to asure no null or empty list is processed. Next a final exception array is initialized to capture at least one exception if a worker thread fails. This can be pumped up to capture an exception per worker by creating an array with the size of the workers collection and throw a MultiException if any of the workers throwed an exception (this is just an axample how it works).

A final latch will be the blocking part. When the current thread reaches the latch.await() command it waits until the latch has been count down to 0. As the latch starts with the number of workers, when all workers are done the current thread unblocks and continues execution.

For worker execution a ThreadPool is created with the double number of worker threads. Why? For each worker there will be a thread that puts the worker into the executor (threadPool.submit(worker)) and waits for the worker to finish (the .get()). That’s what the iteration over the workers does and that’s why all vars are final. When the worker finished either through normal execution or by an exception, the latch is counted down. So when all workers are done, the execute-Method continues after the latch.await() line. Now the executor is shutdown and if any exception occured it is thrown.

That’s it: Any Runnable can be executed without the need to implement a special mechanism inside, as many workers as needed can be executed parallel and the execute-Method blocks until all workers are done. Mission accomplished 🙂

Greetz,
GHad

Written by ghads

December 14, 2011 at 12:18 pm

Java CyclicBarrier and Queue usage

leave a comment »

UPDATE: See below for an update about a race-condition I didn’t think of in the first place…

For updating MongoDB from OracleDB I needed a way with multiple threads to overcome networklatency to our MongoDB Server Cluster. Doing writes/updates with 4 threads resulted in a 3-4 times better performance than using only one thread. But how to implement such an update behavior in a good way using JDK6 concurrent classes/utils?

Basicly one update should do the following steps:

  1. Determine all documents to update (partial updates also possible)
  2. Flag all those documents with a unique tag (using UUID for example)
  3. Run updates concurrently and for each updated document remove the update tag
  4. When all update threads are done, remove all still tagged documents and wait for the next update

This can be achieved by combining a CyclicBarrier, a Queue and an Executor also allowing Thread/Object reuse as long as the update progress is guarded in such a way that only one update runs at one time (using Lock for example).

Here is a basic example code that shows how the update works:

public class CyclicBarrierQueueTesting
{

	private static BlockingQueue<String> queue;

	private static CyclicBarrier barrier;

	private static String updateTag;

	private static String poison = "+++ stop +++";

	public static void main(String[] args)
	{
		// prepare update thread pool
		int numberOfThreads = 4;
		queue = new LinkedBlockingQueue<String>();
		barrier = new CyclicBarrier(numberOfThreads, new Runnable()
		{
			public void run()
			{
				// delete all not updated with updateTag
				// ...
				log("Update done, remove not updated: updateTag= " + updateTag);
				updateTag = null;
			}
		});
		ExecutorService executor = Executors.newFixedThreadPool(4);
		for (int i = 0; i < numberOfThreads; i++)
		{
			executor.submit(new Runner(i, poison, queue, barrier));
		}

		// import all
		barrier.reset();
		List<String> sqlPerLanguge = Collections.nCopies(47, "language");
		updateTag = UUID.randomUUID().toString();
		log("Update all, flagged all with updateTag: updateTag= " + updateTag);
		for (String language : sqlPerLanguge)
		{
			// create a sql query per language
			try
			{
				queue.put(language);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
		// add poison for every thread
		for (int i = 0; i < numberOfThreads; i++)
		{
			try
			{
				queue.put(poison);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}

		// wait for next update (NOT needed in real circumstances)
		while (updateTag != null)
		{
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
			}
		}

		// update some pks
		barrier.reset();
		List<String> somePKs = Collections.nCopies(50, "pk");
		updateTag = UUID.randomUUID().toString();
		log("Update some pks, flagged all products for pks with updateTag: updateTag= " + updateTag);
		for (String pk : somePKs)
		{
			// create a sql query per 10 products
			try
			{
				queue.put(pk);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
		// add poison for every thread
		for (int i = 0; i < numberOfThreads; i++)
		{
			try
			{
				queue.put(poison);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}

		// wait for next update (NOT needed in real circumstances)
		while (updateTag != null)
		{
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
			}
		}

		// shutdown
		log("shutdown");
		executor.shutdownNow();
	}

	public static void log(String str)
	{
		System.out.println(str);
	}

	private static class Runner
			implements Runnable
	{

		private int id;
		private String poison;
		private BlockingQueue<String> queue;
		private CyclicBarrier barrier;

		public Runner(int id, String poison, BlockingQueue<String> queue, CyclicBarrier barrier)
		{
			this.id = id;
			this.poison = poison;
			this.queue = queue;
			this.barrier = barrier;
		}

		public void run()
		{
			boolean run = true;
			while (run)
			{
				try
				{
					try
					{
						String query = queue.take();
						if (query.equals(poison))
						{
							barrier.await();
						}
						else
						{
							log("Thread executes update: id= " + id);
							Thread.sleep(100);
						}
					}
					catch (BrokenBarrierException e)
					{
						e.printStackTrace();
						run = false;
					}
				}
				catch (InterruptedException e)
				{
					run = false;
				}
			}
		}
	}
}

Let’s go top down over the code…

First we need to fix the number of threads and init the objects we want to use: A LinkedBlockingQueue and a CyclicBarrier with a Runnable provided. This Runnable will be executed as soon as all Threads have called barrier.await() indicating the work for one update is done. So then the not updated documents can be removed. Also we init an Executor and start the Threads which will do the update.

Next we want to do a complete update. The way I provide information to the Threads is via SQL-Strings so each Thread executes the query and iterates the ResultSet for updating the MongoDB documents. Here I’m “creating” 47 SQL-Queries. In our production code this is the point where our products are partitionated by language. This way our Products tables can be queried by multiple Threads without overlapping results. Don’t forget to reset the barrier, create an update tag and (not shown here) update all MongoDB documents with the update tag. Now the queries are added into the queue and we also add a special “poison” String per Thread. This String tells the Thread that the update is done when it reaches the end of the queue.

Now all there’s left to do is waiting until the update tag has been resetted. In production code we return from the method as the rest runs async. Of course we use a Lock mechanism to ensure only one update is in progress but in the demo code we just wait. Next is an update on some of the documents which works exactly like described above, only the SQL-Queries change.

The next interesting point is the updating Thread. Here we have a run loop that breaks when interupted by executor.shutdownNow(). First thing the thread does is trying to take on SQL-Query from the queue. As long as the queue is empty this blocks the Thread so we have a clean wait. If there is something in the queue and a Thread has taken the next String, we must compare against the “poison”. If it is the poisen, the thread can stop and tell the barrier so. Else the thread executes the SQL-Query and updates the MongoDB documents and takes next from queue.

That’s it. A clean implementation with helpful classes from the concurrent package. No notify/wait, no Thread.run and total reuse with Threads waiting for work. Basicly just another way of the producer/consumer pattern with a little twist: a barrier for all consumers which when reached executes a Runnable. Easy.

Enjoy and greetings,
Gerhard Balthasar

— UPDATE —

Unfortuatly I overlooked a race-condition when updating the first time into an empty collection. Due to the nature of the find-modify-update way when run with multiple threads, two or more threads can query for the same document and will find none. So both threads will create a document resulting in multiple documents with the same identifier. To prevent this behaviour we need to implement a locking mechanism:

	private ConcurrentMap<String, CountDownLatch> locks = new ConcurrentHashMap<String, CountDownLatch>();

	protected boolean lock(String pk)
	{
		// try to insert new latch and receive prevously inserted latch
		CountDownLatch latch = locks.putIfAbsent(pk, new CountDownLatch(1));
		// if there was no latch before, the current thread can pass
		if (latch == null)
		{
			return false;
		}
		// else the thread must wait
		try
		{
			latch.await();
		}
		catch (InterruptedException e)
		{
			// ignore
		}
		return true;
	}

	protected void unlock(String pk)
	{
		CountDownLatch latch = locks.get(pk);
		if (latch != null)
		{
			latch.countDown();
			locks.remove(pk);
		}
	}

It is used this way:

	DBObject next = collection.findOne(product);
	if (next == null)
	{
		// test if another thread already creates a new document
		wasLocked = lock(pk);
		if (wasLocked)
		{
			// if this thread was locked, another thread has created the document thus this thread is now able to find it
			next = collection.findOne(product);
		}
		else
		{
			// first thread to create the document
			created = true;
		}
	}
	// set all fields and save (incl. waiting for save complete across all ReplicaSets with getLastError())
	// ...
	// if this thread was not locked unlock now to release waiting threads for the same document
	if (created && !wasLocked)
	{
		unlock(pk);
	}

With this approach the first Thread passes the lock, every other Thread must wait upon the latch. When the first Thread has saved the document it releases all other waiting Threads that then issue a new find to catch the new document and continue to update it.

And oh… how to test for duplicates? A simple MapReduce plus count in the shell does the job:

    db.assortment.mapReduce(function () { emit(this.pk, 1); }, function (k, vals) { return Array.sum(vals); }, { out: "duplicates" })
    db.duplicates.count({ "value": { $gte: 2 }})

Big thanx to csanz’s posterous!

Greetz,
GHad
— UPDATE —

Written by ghads

April 12, 2011 at 3:01 pm

MongoDB and Java enums

leave a comment »

Well, there is no way in MongoDB/BSON to de-/serialize Java enums. At least I found none but to implement the Interface DBObject. Having no default implementation I started experimenting with implementing the Interface directly at the enum which would be a massive overhead when using multiple enums. So I decided to create a simple Wrapper like DBRef which does the work for you:

/**
 *
 * Use for put into document: document.put(key, DBEmum.of(SomeEnum.VALUE));
 * Use for get from document: DBEnum.to(SomeEnum.class, document.get(key));
 *
 */
public class DBEnum<T extends Enum<T>>
		implements DBObject
{

	private static final String KEY = "_enum";

	public static <U extends Enum<U>> DBEnum<U> of(U value)
	{
		return new DBEnum<U>(value);
	}

	public static <U extends Enum<U>> U to(Class<U> c, Object o)
	{
		if (o instanceof DBObject)
		{
			Object value = ((DBObject) o).get(KEY);
			if (value == null)
			{
				return null;
			}
			return Enum.valueOf(c, value.toString());
		}
		return null;
	}

	private final T value;

	private DBEnum(T value)
	{
		this.value = value;
	}

	public void markAsPartialObject() { }

	public boolean isPartialObject() { return false; }

	public Object put(String s, Object o) { return null; }

	public void putAll(BSONObject bsonObject) { }

	public void putAll(Map map) { }

	public Object get(String s)
	{
		return value.name();
	}

	public Map toMap()
	{
		return Collections.singletonMap(KEY, value.name());
	}

	public Object removeField(String s) { return null; }

	public boolean containsKey(String s)
	{
		return KEY.equals(s);
	}

	public boolean containsField(String s)
	{
		return KEY.equals(s);
	}

	public Set<String> keySet()
	{
		return Collections.singleton(KEY);
	}

	public String toString()
	{
		return "{ \"" + KEY + "\" : \"" + value.name() + "\" }";
	}
}

Using it this way (example main)…

		Mongo mongo = new Mongo();
		DB db = mongo.getDB("test");
		DBCollection collection = db.getCollection("enum");

		DBObject next = new BasicDBObject("key", DBEnum.of(SomeEnum.VALUE_1));
		collection.insert(next);

		next = collection.findOne(new BasicDBObject("key", DBEnum.of(SomeEnum.VALUE_1)));
		System.out.println(next);

		SomeEnum enumValue = DBEnum.to(SomeEnum.class, next.get("key"));
		System.out.println(enumValue);

… prints the expected results and creates the document:

{
	"_id" : ObjectId("4da421708db0535ebbd175c3"),
	"key" : {
		"_enum" : "VALUE_1"
	}
}

Only real downer is the type must be used explictly. And maybe someone wants to implement this directly into the MongoDB Java driver (and others) so the key could turn to “$enum” and become ‘official’…

Greetings,
GHad

Written by ghads

April 12, 2011 at 2:15 pm

Testing MapReduce (MongoDB) in Java

leave a comment »

Yesterday a co-worker of mine thought about using MapReduce in MongoDB for calculating visibility of products for our company shop. Not convinced that an operation that basicly just groups is the right tool for the job I wanted a way to test MapReduce operations without the hassle to setup a MongoDB with example data for each co-worker and using Javascript from our Java environment (think of debugging…). So I thought about providing a tiny implementation in Java that just behaves like MapReduce in MongoDB (no paralization). This way all of my co-workers can play with their operations and check the practicability of their solution.

So today I quickly coded the following class, which imho also helps to explain the way MapReduce works to newbies:

public abstract class MapReduce<In, Out> {

	public static <Input, Output> Map<Object, Output> execute(MapReduce<Input, Output> operation, Collection<Input> input) {
		if (operation == null || input == null || input.isEmpty()) throw new IllegalArgumentException();

		// map input to emit values
		for (Input in : input) {
			operation.map(in);
		}

		// reduce emitted values
		Map<Object, Output> result = new HashMap<Object, Output>();
		for (Map.Entry<Object, Collection<Output>> entry : operation.emits.entrySet()) {
			Object key = entry.getKey();
			Output reduced = operation.reduce(key, entry.getValue());
			result.put(key, reduced);
		}
		return result;
	}

	private Map<Object, Collection<Out>> emits = new HashMap<Object, Collection<Out>>();

	protected void emit(Object key, Out value) {
		Collection<Out> forKey = emits.get(key);
		if (forKey == null) {
			forKey = new ArrayList<Out>();
			emits.put(key, forKey);
		}
		forKey.add(value);
	}

	public abstract void map(In input);

	public abstract Out reduce(Object key, Collection<Out> emits);

}

So we have an abstract class that defines a “map” and a “reduce” method which must be implemented by the operation. We have an internal method “emit” which must be called from the map method (map phase) to add an entry for the reduce phase per key/unique value (grouping). And we have a static method “execute” to call the abstract methods for a collection of input elements, first for each element the map-method then for all emited values the reduce-method per key.

To test your MapReduce operation the implementation is easy:

public class MapReduce_Test {

	public static class Customer {
		public String name;
	}

	public static class GroupByName extends MapReduce<Customer, Integer> {

		@Override
		public void map(Customer input) {
			emit(input.name, 1);
		}

		@Override
		public Integer reduce(Object key, Collection<Integer> emits) {
			int count = 0;
			for (Integer i : emits) {
				count = count + i;
			}
			return count;
		}
	}

	public static void main(String[] args) {
		// create some customers
		List<Customer> input = new ArrayList<Customer>();
		for (int i = 0; i < 1000; i++) {
			Customer in = new Customer();
			in.name = "name" + (i % 6);
			input.add(in);
		}

		// execute MapReduce operation
		Map<Object, Integer> result = MapReduce.execute(new GroupByName(), input);

		// show result
		System.out.println(result);
	}

}

Here we’re just group by customers name and count the number of occurencies for each name. The output of this Test is: {name1=167, name5=166, name2=167, name3=167, name4=166, name0=167}

So for my co-workers it’s easier to test their operations for MapReduce and if the operation gets the desired output for the given input, we can now transform the map/reduce methods from Java to JavaScript saving JavaScript debug time and headscratching woes 😉

Greetz,
GHad

Written by ghads

February 17, 2011 at 11:17 am

Filter Collections via “Double Brace Initialization”

with 3 comments

Hi again,

here’s another little code I did recently while trying to answer a Stackoverflow-Question.

The author of the question (here) asks for a smarter way to filter collections/lists in Java like it is done in Python/Scala/Groovy, as one-liner.

I immediatly thought of JDK7 closures, but as it is widly known Oracle shifted the featurelists for JDK7 and 8 not long ago and it seems, closures will come not earlier than 2012. But even with closures the accepted answers shows that in its current state event closures would be an akward and over-complicated solution compared to groovy for example (quoted from the seanizers answer):

JDK7 sample code:

findItemsLargerThan(List l, int what){
  return filter(boolean(Integer x) { x > what }, l);
}
findItemsLargerThan(Arrays.asList(1,2,5,6,9), 5)

Groovy sample code:

  Arrays.asList(1,2,5,6,9).findAll{it > 5}

You see…

So I started to experiment with pure Java to find a solution that is easy to read and easy to program while not beein too verbose. After some hours I came up with the following code

List<Integer> filtered = new Filter<Integer>(Arrays.asList(1,2,5,6,9)) {
  {
    findAll(it > 5);
  }
};

I thinks it’s quite elegant, because it’s readable pure Java code and fits one line sans code-formating. How does it work? Obvisually one needs a class Filter. The abstract Filter class implements the List interface (delegates all methods to an internal List variable) and takes the collection to filter (assigned to the internal List variable) as argument for its constructor and throws a RuntimeException when the collection is null or empty. Then we have the double brace initialization pattern which allows to dynamicly and anonymously subclass the filter class while providing an instance initalizer which will be executed after the constructor of the Filter class is done. Inside the instance initializer all we do now is a method call to findAll(), which takesa boolean argument. But where does “it” come from and how will “it” be mapped to each element of the collection?

“it” is a variable inside the Filter class. As the instance initializer is executed after the constructor, we can set “it” to the first element of the collection to filter. The instance initializer is then executed and the boolean condition it > 5 is evaluated. So at the time findAll() is executed, the condition whether to include the first element in the filtered result is already done. So the magic to repeat the evaluation for each element must be inside the findAll() method:

protected void findAll(boolean b) {
  // exit condition for future calls
  if (values.size() > 1) {
    // only repeat for each entry, if values has multiple entries
    Constructor constructor = this.getClass()
       .getDeclaredConstructors()[0];
    Iterator iterator = values.iterator();
    boolean first = true;
    while (iterator.hasNext()) {
      T element = iterator.next();
      // don't evalute again for the first entry
      if (first) {
        if (!b) {
          iterator.remove();
        }
        first = false;
      } else {
        // else repeat Filter invocation for all elements
        Filter filtered = null;
        try {
          // invoked constructor for the element
          filtered = (Filter) constructor.newInstance(
            new Object[] { null, Arrays.asList(element) });
        } catch (Exception e) {
          e.printStackTrace();
        }
        // if values is empty, the condition didn't match and the
        // element can be removed
        if (filtered != null && filtered.isEmpty()) {
          iterator.remove();
        }
      }
    }
  } else {
    // one element can be checked directly
    if (!b) {
      values.clear();
    }
  }
}

(a little bit more polished than my answer at Stackoverflow)

First thing is to define an exit condition as the findAll() method will be executed multiple times eventually. The condition says, if there is more than one element in the list, we must iterate, else we can look at the evaluted boolean condition directly. In the last case “false” will just clear the internal List, whereas “true” does not change it.

When iteration is needed we get the constructor of this class once (there is only one) and take the next element. If it is the first one, we already know the evaluated condition and thus remove or keep the first item. For all other items we will create a new instance of the anonymous class that extended Filter via instance initalizer in the first place. By creating a new instance and providing a list as argument with a single element, the instance initializer is called again after the constructer set “it”. So the evaluation of the boolean condition starts again, but for the next element this time. After instance creation it’s a simple check whether the boolean condition had matched or not. If the internal List is empty, the condition was “false” and the element can be removed from the Filter instance that iterates the elements and creates new instances.

So the only catch is that there are n-1 additional instances created for a collection n to filter, when n is the number of elements. But as Instance creation is quite cheap these days and every additional instance does not need to iterate again, this runs quite fast. I’m sure there is still potential to optimize the Filter class as new ArrayLists are created here and there but im very satisfied with the result so far.

The filter class can be used for each kind of object, for example checking if people are 18 would be “findAll(it.getAge() >= 18);”, if there is a People Class with a getAge() method.

So long this time, hope you enjoyed this blogpost (feedback is appriciated).
Greetz,
GHad

Written by ghads

September 22, 2010 at 3:49 pm

Java Event handling via Enumerations

leave a comment »

It’s been a while

but I’m still active. Just had no time posting updates, but today I’ll start over, hoping to get more updates done more frequently. I want to start with a series of Java related posts showing some API usage code for my personal API JBase I developed over the last year. I will not post implementation details as far as full code but I’ll highlight one part and will give you hints about how to get it coded by yourself.

To start I will show an Event raising and handling system via Enumerations. There is no 3rd party library involved, just pure Java 5+ code is involved. So why Events?

Well it turns out that unless you use Bindings, updating a UI from model values or listenting for user actions involes an eventing system that needs quite a lot of work when used like it is promoted by Swing (i.e. WindowListener):

– A class for each event type (WindowEvent)
– An interface for the Listener (WindowListener) with a method per event (windowsActivated, windowsClosed, …)
– An internal raise method (processWindowEvent)
– An add method/remove method per listener interface (addWindowListener, removeWindowListener)
– List handling for keeping the listeners references (windowListeners)
– Synchronizing for multi-threading (when accesing the list)
– Did I forget somthing?

So scaling is a mess especially as changing any part leads to massive editing because of a tight coupling. For adding a new event type for example one needs all of the above. For adding new events (adding a method to the interface) all implementing listeners classes must be changed! And so on…

So I tried to solve those issues by decoupling the events completly from the class by using an Enumeration for the event type and an enumeration variable per event.

Use it like this:


public class SimpleEvent_Example implements SimpleEvent.Listener {

 public static void main(String[] args) {
   SimpleEvent.addListener(new SimpleEvent_Example());

   System.out.println("Raise SOME...");
   SimpleEvent.SOME.raise("some id");

   System.out.println("Raise OTHER...");
   SimpleEvent.OTHER.raise("other id");
 }

 public void handle(SimpleEvent event, String id) {
   switch (event) {
   case SOME:
     System.out.printf("SimpleEvent_Example.handle SOME: id= %1$s", id);
     System.out.println();
     break;
   case OTHER:
     System.out.printf("SimpleEvent_Example.handle OTHER: id= %1$s", id);
     System.out.println();
   break;
   }
 }
}

Easy, hm?

Let’s look at this line by line. The class implements an interface and thus listens to SimpleEvent, which would normaly be the Event class (e.g. WindowEvent). The Enumeration contains a non-static inner interface called Listener which is implemented here. For listing to multiple Event this would just be ‘implements SimpleEvent.Listener, OtherEvent.Listener’ and so on. It’s clearly declared at which event types this class listens to, so it should not be that confusing but very obvious on a second thought.

In the main method we first create a new instance of the example class and add this instance as listener to the Enumeration/event type. It has static methods for adding and removing Listeners so this is straight forward.

Next the event SOME of the type SimpleEvent is raised. As the enumeration variable IS the event it has a raise method. So this is completly decoupled from any class actually raising the event. Here the raise method is public but you can still make it package protected for example if you like to limit which class is allowed to raise events. So the event SOME of the event type SimpleEvent is like the previously mentioned windowsActivated event of the event type WindowEvent.

The handle method is implememted as declared in the Listener interface. For acting upon an event, the raised event is provided as well as the argument id from raising the event. A simple switch on event makes reacting to multiple events inside one method possible instead of using a method per event like with WindowListener (windowsActivated, windowsClosed, …). Now when adding a new event, you do not NEED to edit all Listeners anymore, if you design your switch right (don’t forget about default).

What’s missing is the source. But as the Listeners interface and the raise method is up to the developer when creating the Enumeration for the event type, an additional source parameter can be added at will.

How is SimpleEvent implemented then? Simple of course:


public enum SimpleEvent {

 // 1. declare events as enum variables
 SOME, OTHER;

 // 2. add the non-static interface for listeners
 public interface Listener {

   public void handle(SimpleEvent event, String id);

 }

 // 3. create delegator for handling listeners and events
 private static JEvents<Listener, SimpleEvent> EVENTS = JEvents.<Listener, SimpleEvent> create();

 // 4. add raise method and delegate to event types raise method
 public void raise(String id) {
   EVENTS.raise(this, new Object[] { id });
 }

 // 5. create static delegates for adding and removing listeners
 public static boolean addListener(Listener listener) {
   return EVENTS.addListener(listener);
 }

 public static boolean removeListener(Listener listener) {
   return EVENTS.removeListener(listener);
 }
}

As you can see there is not much code involved but there is a static instance of JEvents doing all the hard stuff in the background. So let’s look a little deeper inside the enum first and then go into JEvents…

The first few lines of the Enumeration is just standard stuff: declaring the events as enum variables and defining the listeners interface. Here we have one constraint though: the first parameter of each liteners interface method must be the Enumeration itself and is called ‘event’ by convention. One can always add more listeners methods but this is usally not needed as the event is an enumeration variable so you can switch inside the method implemtation instead of implementing multiple methods.

The third step creates the background instance of the class JEvents. This create call is just another way of providing concrete type information to a generic static create method instead of passing the class types. The JEvents instance uses the type information to restrict the raise and listeners add and remove methods to the correct interface and Enumeration, giving you a little type-savety for free.

At step four the non-static raise method is added to make the raise calls from the usage example possible. As the event itself is known by then (the selected enumeration variable) ‘this’ can be used when calling JEvents. As you can see the second part of the raise call looks rather akward but is needed. Here you need to pass all the arguments matching the parameter signature of one of the listeners methods except the event itself. The reason why I used an Object[] instead of varargs are listeners methods with varargs or arrays. When using a String[] for example by passing it to the JEvents raise method it would be casted to Object[]. So when looking for the right listeners method to call, we have a wrong signature. Thus to reduce errors I decided for using an Object[] directly so the I do not need to think about when I need to create a new Object[] or when using varargs is enough. A little akward syntax is the only trade-off here for reducing errors. Note you can still use varargs at the listeners methods as they get erased to arrays at compile time and JEvents can find the right method to call.

There are multiple raise methods at JEvents. I can use veto events (returning true if one listener returns true or throws an exception), synchronious events (like here), asychronious events and repeated events. The developer decides on what event he/she wants to use when implementing the Enumerations raise methods delegation to JEvents.

Finally adding and removing listeners are just static delegates to the JEvents instance and your done. This is far less code and far less changes for scaling than the classic approach:

– Adding a new event type is creating a new Enumeration (<30 lines of code)
– Adding a new event is just adding a new enum variable and no/little listeners changes involved
– No additional raise methods are needed if the listeners method can handle all the parameters
– No list handling for listeners as adding/removing is just a delegation
– JEvent does all the synchronizing for you
– completly decoupled

So how does JEvent works?

The JEvents instance manages a list of listers for the interface and lets you add/remove listeners at any time via the Enumeration itself via delegation. When a raise method is called, JEvents knows the signature of the listeners method, looks up the corresponding method and calls it for every listener. It can handle types that are assignable from a paramters type and looks for primitve types while checking the signature. Basicly that’s all. The fine-print involves errorhandling, asynchroniuos/delayed/repeated events via scheduled executors that can be canceled, synchronizing via ReentrantLocks for multi-threaded usage and veto events as mentioned above. I’ll just show the part actually checking if a method is the listener method for the event and the arguments:


private boolean isListener(Method m, E event, Object[] args) throws Exception {
   if (args == null) {
     args = new Object[0];
   }
   Class<?>[] parameterTypes = m.getParameterTypes();
   if (parameterTypes.length == args.length + 1) {
     if (parameterTypes[0].equals(event.getClass())) {
       for (int i = 0, max = args.length; i < max; i++) {
         Class<?> argsType = args[i].getClass();
         Class<?> parameterType = parameterTypes[i + 1];
         if (!argsType.equals(parameterType) && !parameterType.isAssignableFrom(argsType)) {
           if (Reflection.isPrimitveOrWrapper(argsType)) {
             argsType = Reflection.getPrimitiveClass(argsType);
             if (!argsType.equals(parameterType)) {
               return false;
             }
           } else {
             return false;
           }
         }
       }
       return true;
     }
   }
   return false;
 }

Note that a class Reflection is used, which is also a part of JBase but needs no further explanation here. We first check if the length of the methods parameters is correct, then if the first parameter is the events type. After that we check for every other parameter if the the parameters class matches the arguments class or is assignable from it. If not we try it once more for primitives, as the Object array contains only the wrapper classes to the primitives.

That concludes todays journey to my JBase API. I hope you enjoyed the dive and I’d like to get some feedback from you if you don’t bother to comment.

Thank you and greetz,
GHad

Written by ghads

September 2, 2010 at 12:16 pm