Posts tagged ‘templates’

Observer patterns is one of the core design patterns that every developer should know and use. It let’s you create components with low coupling and adhere to Hollywood principle.

Some pseudo-code for adding new observer might look like this:

void addObserver(String ev, Observer ob);
producer.addObserver("myEventName", new Observer(){public void observe(Producer producer){}});

But there are at least 2 issues with this design:

  • You have to explicitly define event name
  • You can only pass reference to a producer object.
You could of course decide that a producer can only dispatch one type of events and we don’t need to explicitly name them, but usually that’s not the case.

So what if you wanted to define your events using some kind of interface, eg:


public interface MyEvent{}
producer.addListener("myEventName", new Observer<MyEvent>(){public void observe(MyEvent me){}});

So this is a little bit better but you still need to pass name of event as String.

So maybe we could use java generics to use power of type-safety at compile time and still have all the benefits of low-coupling. Something that could look like this:


public <T> void addListener(Class<T> e, Observer<T> o);
producer.addListener(MyEvent.class, new Observer<MyEvent>(){public void observe(MyEvent me){}});

Where first parameter could be used as EventType declaration.

This is very close but has still one flaw – it forces redundant code:

  • once event type is passed explicitly as event definition
  • second during observer creation – template parameter

So maybe it could be somehow simplified into something like this:

producer.addListener(new Observer<MyEvent>(){public void observe(MyEvent me){}});

Some of you might say that this is impossible in Java due to type-erasure. This is all true – but there’s second part of it – generic types are available at runtime through getGenericSuperClass/getGenericInterfaces methods.

You can see source code for my type-safe event system on github but I think it needs just some clarification – why do you need that ugly MethodProxy class.
So after writing DefaultImplementation of event dispatcher interface I found out that compiler would not allow call to Listener’s on method with passed event instance. So I decided to find proper method using reflection and only internally resign of type-safety.
MethodProxy class creates proxy upon instantiation so it will report any problems very close to their cause.

So here’s what you can find already in the repo:

  1. Dispatcher interface with default implementation
  2. Simple event interface used as entry point for all events
  3. Simple listener interface used as entry point for all listeners
I guess there might be sample usage scenario:
Declare your event:
</pre>
public class MyEvent implements ProcessorLifecycleEvent{}
Create event dispatcher and register your listener:
ProcessorLifecycleEventDispatcher eventDispatcher = new DefaultProcessorLifecycleEventDispatcher();
eventDispatcher.registerListener(new ProcessorLifecycleEventListener<MyEvent>(){
public void on(MyEvent e) {
// some logic here
}
});

Publish new event:

eventDispatcher.dispatch(new MyEvent(){});
In the sample above MyEvent is very simple but it could take some data through constructor and act as full-blown DTO which simplifies greatly interactions beacause listener code doesn’t have to do any runtime casts – see example.
The whole project is part of another thing – Liferay service without service builder, which I’m going to describe soon 🙂

So enjoy.

As you probably noticed there are few entries in my blog that deal with usage of cglib. There was one thing though that kept me a bit frustrated – why wasn’t it possible to use JDK 1.5 generics when creating eg. new Ehnancer.

So I decided to add generics which could also get me more familiar with this library. My first step was to download source code from sourceforge and import into cglib-jdk15 repository on my github account. Afterwards I found out that AbstractClassGenerator contains inner Source class which uses caching mechanism for generated classes but unfortunately it wasn’t possible to add generic WeakHashMap without altering the code. Luckily this didn’t seem that much complicated – I just split cache into two separate caches – one for classes and one for References.

After everything was in place I could update Junit Tests and my code snippets blog entries with no more explicit casts.

Than I had a look at ant build script- in order to put generics version into the repository I wanted to use maven’s classifier but to achieve this a build script needed some more attention. It looked like its task could be replaced with maven tasks/conventions. It all worked – I could even generate „nodep” package but in this case I think that project structure still needs some attention.

Finally in order to build the project you can issue following command:

mvn clean install javadoc:javadoc jxr:jxr jxr:jxr-test site

As usual modfied source code available on github.

Binaries in my repository.