Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Domain Event pattern implementation in Java?

I'm searching for a simple Java implementation of Udi Dahan's Domain Events pattern and infrastructure as detailed in this article.

It's pretty simple and I've implemented my own interpretation, however I'm a Java novice and don't want to be bitten by any mistakes due to inexperience with the language.

The only Java implementation I've found is in the Jdon Framework, but it's a little too heavyweight for my current in my project.

Thanks!

like image 971
HolySamosa Avatar asked Apr 18 '12 20:04

HolySamosa


2 Answers

I have been looking for a solution to the same problem in Java EE for a while now. I looked at Axon and jdon (the page doesn't really bode well either :)). Both involve Event Sourcing which I could not "sell" to my employers/customers. I wanted to have Domain Events though since I very much got used to them in .NET/C# projects. So I came up with the following...

I used a similar static DomainEvents object to give me access to a publishing mechanism without the actual implementation details leaking all over my domain model entities. So the calls something like this:

DomainEvents.fire(new MySampleEvent(...some params...));

A pattern and mechanism that is available in CDI spec are the Events with @Observes that allow you to respond to certain events in normal beans with all the service available. That is similar to what I was used to when using DI frameworks like Castle Windsor where I could register generic handlers by interface. So I've got the observers (handlers, listeners, whatever you want to call them) covered. Example:

@Stateless
public class MySampleEventObserver {

  public void listen(@Observes MySampleEvent event) {
    ...
    doSomethingWithEvent();
  }
}

Now for the publishing (firing in CDI) part. Since there is no way to access CDI in entities (with good reason!) I resolved to using JNDI and BeanManager. I used JNDI to get the BeanManager and use it's fireEvent method. To put bean manager resolving (as seen here) in code:

public class BeanHelper {
  public static BeanManager getBeanManager() {
    try {
        InitialContext initialContext = new InitialContext();
        return (BeanManager) initialContext.lookup("java:comp/BeanManager");
    } catch (NamingException e) {
        e.printStackTrace();
        return null;
    }
  }

}

The final step is the DomainEvents object itself:

public class DomainEvents {

  private static boolean mNopMode = false;

  public static void setNopMode() {
    mNopMode = true;
  }

  public static void reset() {
    mNopMode = false;
  }

  public static <TDomainEvent> void fire(TDomainEvent event) {
    if (mNopMode) {
        return;
    }
    BeanManager manager = BeanHelper.getBeanManager();

    manager.fireEvent(event);
  }

}

The setNopMode and reset parts are there for testing purposes when there is no context. Manual mocking basically. Set it into NOP operation mode before unit tests and reset after them.

Works fine as a POC. Don't know if there are any serious limitations to it's use though. I leave async bus interactions and similar to the listeners implementation.

Would love any comments.

like image 95
jl. Avatar answered Sep 20 '22 19:09

jl.


I'm currently looking at using Googles Guava EventBus to do something similar to the "Salvation" article you reference.

Using it similar to the "How to raise domain events" would look something like this, almost exactly the same as the article:

public class Customer
{
    public void DoSomething()
    {
        MyEventBus.post(new CustomerBecamePreferred() { Customer = this });
    }
}

I don't know whether or not you'd consider this as an "implementation of Udi Dahan's Domain Events pattern".

It doesn't require implementing any interfaces; event handlers are marked with annotations and the class is registered with the EventBus with MyEventBus.register(aListenerObject)

like image 1
Stephen P Avatar answered Sep 21 '22 19:09

Stephen P