@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); }