Я искал решение той же проблемы в Java EE какое-то время. Я посмотрел на Axon и jdon (страница на самом деле не очень хорошо написана :)). Оба включают Event Sourcing, которые я не мог «продать» своим работодателям/клиентам. Я хотел иметь доменные события, хотя я очень привык к ним в проектах .NET/C#. Итак, я придумал следующее ...
Я использовал аналогичный статический объект DomainEvents, чтобы предоставить мне доступ к механизму публикации без фактических данных реализации, протекающих по всем объектам модели домена. Таким образом, звонки что-то вроде этого:
DomainEvents.fire(new MySampleEvent(...some params...));
Узора и механизма, который доступен в КДИ спецификациях являются Events with @Observes, которые позволяют реагировать на определенные события в нормальных бобах со всеми доступными услугами. Это похоже на то, к чему я привык, когда я использую рамки DI, такие как Castle Windsor, где я мог регистрировать общие обработчики по интерфейсу. Итак, у меня есть наблюдатели (обработчики, слушатели, все, что вы хотите назвать их). Пример:
@Stateless
public class MySampleEventObserver {
public void listen(@Observes MySampleEvent event) {
...
doSomethingWithEvent();
}
}
Теперь для публикации (обжига в CDI). Поскольку нет доступа к CDI в сущности (с уважительной причиной!), Я решил использовать JNDI и BeanManager. Я использовал JNDI, чтобы получить BeanManager и использовать его метод fireEvent.Для того, чтобы поместить менеджер боба решения (как seen here) в коде:
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;
}
}
}
В последней стадией является DomainEvents сам объект:
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
и reset
частей существуют для целей тестирования, когда нет контекста. Ручное насмешливое в основном. Установите его в режим работы NOP перед модульными тестами и выполните сброс после них.
Работы отлично как POC. Не знаю, существуют ли какие-либо серьезные ограничения для его использования. Я оставляю асинхронные межсетевые взаимодействия и аналогично реализации слушателей.
Обожаю любые комментарии.
Спасибо, Стивен, это круто ... Я не знал о Гуаве. Я действительно стараюсь, чтобы мой домен не был осведомлен о деталях реализации, но я дам Guava EventBus подумать. Возможно, я могу обернуть EventBus, чтобы скрыть реализацию из моего домена ... – HolySamosa
Yeah @HolySamosa - я собираюсь обернуть его, когда я его вставляю, но сохраняю простой интерфейс 'register()' и 'post()' для Это. –
Я предполагаю, что вы собираетесь сохранить аннотацию Guava Subscribe в своей модели домена? Мне нравится идея использования аннотации для привязки подписки, но я бы предпочел не допустить, чтобы такая деталь реализации скользнула в мою красивую чистую модель домена. – HolySamosa