@Override
 public void publish(EventMessage... events) {
   final Channel channel = connectionFactory.createConnection().createChannel(isTransactional);
   try {
     for (EventMessage event : events) {
       doSendMessage(
           channel,
           routingKeyResolver.resolveRoutingKey(event),
           asByteArray(event),
           isDurable ? DURABLE : null);
     }
     if (CurrentUnitOfWork.isStarted()) {
       CurrentUnitOfWork.get().registerListener(new ChannelTransactionUnitOfWorkListener(channel));
     } else if (isTransactional) {
       channel.txCommit();
     }
   } catch (IOException e) {
     if (isTransactional) {
       tryRollback(channel);
     }
     throw new EventPublicationFailedException(
         "Failed to dispatch Events to the Message Broker.", e);
   } catch (ShutdownSignalException e) {
     throw new EventPublicationFailedException(
         "Failed to dispatch Events to the Message Broker.", e);
   } finally {
     if (!CurrentUnitOfWork.isStarted()) {
       tryClose(channel);
     }
   }
 }
 @After
 public void tearDown() throws Exception {
   scheduledThreadPool.shutdownNow();
   while (CurrentUnitOfWork.isStarted()) {
     CurrentUnitOfWork.get().rollback();
   }
 }
  @Test
  public void testLoadAndSaveAggregate() {
    UUID identifier = UUID.randomUUID();
    DomainEventMessage event1 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 1, "Mock contents", MetaData.emptyInstance());
    DomainEventMessage event2 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 2, "Mock contents", MetaData.emptyInstance());
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(new SimpleDomainEventStream(event1, event2));

    TestAggregate aggregate = testSubject.load(identifier, null);

    assertEquals(0, aggregate.getUncommittedEventCount());
    assertEquals(2, aggregate.getHandledEvents().size());
    assertSame(event1, aggregate.getHandledEvents().get(0));
    assertSame(event2, aggregate.getHandledEvents().get(1));

    // now the aggregate is loaded (and hopefully correctly locked)
    StubDomainEvent event3 = new StubDomainEvent();

    aggregate.apply(event3);

    CurrentUnitOfWork.commit();

    verify(mockEventBus).publish(isA(DomainEventMessage.class));
    verify(mockEventBus, never()).publish(event1);
    verify(mockEventBus, never()).publish(event2);
    verify(mockEventStore, times(1)).appendEvents(eq("test"), isA(DomainEventStream.class));
    assertEquals(0, aggregate.getUncommittedEventCount());
  }
  @Test
  public void testLoadAndSaveWithConflictingChanges() {
    ConflictResolver conflictResolver = mock(ConflictResolver.class);
    UUID identifier = UUID.randomUUID();
    DomainEventMessage event2 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 2, "Mock contents", MetaData.emptyInstance());
    DomainEventMessage event3 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 3, "Mock contents", MetaData.emptyInstance());
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 1, "Mock contents", MetaData.emptyInstance()),
                event2,
                event3));
    testSubject.setConflictResolver(conflictResolver);
    TestAggregate actual = testSubject.load(identifier, 1L);
    verify(conflictResolver, never())
        .resolveConflicts(anyListOf(DomainEventMessage.class), anyListOf(DomainEventMessage.class));
    final StubDomainEvent appliedEvent = new StubDomainEvent();
    actual.apply(appliedEvent);

    CurrentUnitOfWork.commit();

    verify(conflictResolver)
        .resolveConflicts(payloadsEqual(appliedEvent), eq(Arrays.asList(event2, event3)));
  }
 @Before
 public void setUp() {
   mockBus = mock(CommandBus.class);
   mockTarget = new MyCommandHandler();
   testSubject = new AnnotationCommandHandlerAdapter(mockTarget, mockBus);
   mockUnitOfWork = mock(UnitOfWork.class);
   CurrentUnitOfWork.set(mockUnitOfWork);
 }
 @Override
 public boolean hasNext() {
   boolean hasNext = super.hasNext();
   if (!hasNext) {
     CurrentUnitOfWork.get()
         .registerListener(
             new SnapshotTriggeringListener(aggregateType, aggregateIdentifier, getCounter()));
     if (clearCountersAfterAppend) {
       counters.remove(aggregateIdentifier, getCounter());
     }
   }
   return hasNext;
 }
  @Test
  public void testCommandHandlerLoadsSameAggregateTwice() {
    DefaultUnitOfWork.startAndGet();
    StubAggregate stubAggregate = new StubAggregate(aggregateIdentifier);
    stubAggregate.doSomething();
    repository.add(stubAggregate);
    CurrentUnitOfWork.commit();

    DefaultUnitOfWork.startAndGet();
    repository.load(aggregateIdentifier).doSomething();
    repository.load(aggregateIdentifier).doSomething();
    CurrentUnitOfWork.commit();

    DomainEventStream es = mockEventStore.readEvents("", aggregateIdentifier);
    assertTrue(es.hasNext());
    assertEquals((Object) 0L, es.next().getSequenceNumber());
    assertTrue(es.hasNext());
    assertEquals((Object) 1L, es.next().getSequenceNumber());
    assertTrue(es.hasNext());
    assertEquals((Object) 2L, es.next().getSequenceNumber());
    assertFalse(es.hasNext());
  }
  @Test
  public void testSaveEventsWithDecorators() {
    SpyEventPreprocessor decorator1 = new SpyEventPreprocessor();
    SpyEventPreprocessor decorator2 = new SpyEventPreprocessor();
    testSubject.setEventStreamDecorators(Arrays.asList(decorator1, decorator2));
    testSubject.setEventStore(
        new EventStore() {
          @Override
          public void appendEvents(String type, DomainEventStream events) {
            while (events.hasNext()) {
              events.next();
            }
          }

          @Override
          public DomainEventStream readEvents(String type, Object identifier) {
            return mockEventStore.readEvents(type, identifier);
          }
        });
    UUID identifier = UUID.randomUUID();
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 3, "Mock contents", MetaData.emptyInstance())));
    TestAggregate aggregate = testSubject.load(identifier);
    aggregate.apply(new StubDomainEvent());
    aggregate.apply(new StubDomainEvent());

    CurrentUnitOfWork.commit();

    InOrder inOrder = Mockito.inOrder(decorator1.lastSpy, decorator2.lastSpy);
    inOrder.verify(decorator1.lastSpy).next();
    inOrder.verify(decorator2.lastSpy).next();

    inOrder.verify(decorator1.lastSpy).next();
    inOrder.verify(decorator2.lastSpy).next();
  }
 @After
 public void tearDown() {
   CurrentUnitOfWork.clear(mockUnitOfWork);
 }