Package org.axonframework.quickstart

Source Code of org.axonframework.quickstart.RunEventReplay$StubEventStore

/*
* Copyright (c) 2010-2014. Axon Framework
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.axonframework.quickstart;

import org.axonframework.domain.DomainEventMessage;
import org.axonframework.domain.DomainEventStream;
import org.axonframework.domain.EventMessage;
import org.axonframework.domain.GenericDomainEventMessage;
import org.axonframework.domain.SimpleDomainEventStream;
import org.axonframework.eventhandling.ClusteringEventBus;
import org.axonframework.eventhandling.DefaultClusterSelector;
import org.axonframework.eventhandling.EventBus;
import org.axonframework.eventhandling.SimpleCluster;
import org.axonframework.eventhandling.annotation.AnnotationEventListenerAdapter;
import org.axonframework.eventhandling.annotation.EventHandler;
import org.axonframework.eventhandling.replay.BackloggingIncomingMessageHandler;
import org.axonframework.eventhandling.replay.ReplayAware;
import org.axonframework.eventhandling.replay.ReplayingCluster;
import org.axonframework.eventstore.EventStore;
import org.axonframework.eventstore.EventVisitor;
import org.axonframework.eventstore.management.Criteria;
import org.axonframework.eventstore.management.CriteriaBuilder;
import org.axonframework.eventstore.management.EventStoreManagement;
import org.axonframework.quickstart.api.ToDoItemCompletedEvent;
import org.axonframework.quickstart.api.ToDoItemCreatedEvent;
import org.axonframework.quickstart.api.ToDoItemDeadlineExpiredEvent;
import org.axonframework.unitofwork.NoTransactionManager;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.axonframework.domain.GenericEventMessage.asEventMessage;

/**
* @author Allard Buijze
*/
public class RunEventReplay {

    public static void main(String[] args) throws InterruptedException, TimeoutException, ExecutionException {

        // we initialize an event store that is capable of doing replays. In this case, we create a Stub implementation.
        // In production, you would use an Event Store implementation such as the JpaEventStore or MongoEventStore.
        StubEventStore eventStore = new StubEventStore();

        //we create a ReplayingCluster, which wraps that actual cluster that listeners will be subscribed to
        // since we don't need transactions in this in-memory sample, we use a NoTransactionManager
        // the 0 means we do not need any "intermediate commit" during the replay.
        // The BackloggingIncomingMessageHandler will make sure any events published while replaying are backlogged
        // and postponed until the replay is done.
        ReplayingCluster replayingCluster = new ReplayingCluster(new SimpleCluster("simple"), eventStore,
                                                                 new NoTransactionManager(), 0,
                                                                 new BackloggingIncomingMessageHandler());

        // we initialize an event bus that contains our replaying cluster
        EventBus eventBus = new ClusteringEventBus(new DefaultClusterSelector(replayingCluster));

        // we subscribe our two listeners to the Event Bus
        AnnotationEventListenerAdapter.subscribe(new ThreadPrintingEventListener(), eventBus);
        AnnotationEventListenerAdapter.subscribe(new AnotherThreadPrintingEventListener(), eventBus);

        // we append some events to simulate a full event store
        final DomainEventMessage[] domainEventMessages = {
                new GenericDomainEventMessage<ToDoItemCreatedEvent>(
                        "todo1", 0, new ToDoItemCreatedEvent("todo1", "Need to do something")),
                new GenericDomainEventMessage<ToDoItemCreatedEvent>(
                        "todo2", 0, new ToDoItemCreatedEvent("todo2", "Another thing to do")),
                new GenericDomainEventMessage<ToDoItemCompletedEvent>("todo2", 0, new ToDoItemCompletedEvent("todo2"))
        };
        eventStore.appendEvents("mock", new SimpleDomainEventStream(domainEventMessages));

        // we create an executor service with a single thread and start the replay as an asynchronous process
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Void> future = replayingCluster.startReplay(executor);

        // we want to wait for the cluster to have switched to replay mode, so we can send some messages to it.
        // if we were to publish events right away, there is a big chance the Cluster didn't switch to replay mode, yet.
        waitForReplayToHaveStarted(replayingCluster);

        // this is a new event, so it should be backlogged and handled at the end of the replay
        eventBus.publish(asEventMessage(new ToDoItemCreatedEvent("todo3", "Came in just now...")));

        // this message is also part of the replay, and should therefore not be handled twice.
        eventBus.publish(domainEventMessages[2]);

        // we wait (at most 10 seconds) for the replay to complete.
        future.get(10, TimeUnit.SECONDS);

        // and we publish another event to show that it's handled in the calling thread
        eventBus.publish(asEventMessage(new ToDoItemDeadlineExpiredEvent("todo1")));

        // we want to shutdown the executor, to get a proper JVM shutdown
        executor.shutdown();
    }

    private static void waitForReplayToHaveStarted(ReplayingCluster replayingCluster) {
        while (!replayingCluster.isInReplayMode()) {
            Thread.yield();
        }
    }

    public static class ThreadPrintingEventListener {

        @EventHandler
        public void onEvent(EventMessage event) {
            System.out.println(
                    "Received " + event.getPayload().toString() + " in " + getClass().getSimpleName()
                            + " on thread named "
                            + Thread.currentThread().getName());
        }
    }

    public static class AnotherThreadPrintingEventListener extends ThreadPrintingEventListener
            implements ReplayAware {

        @Override
        public void beforeReplay() {
            System.out.println("Seems like we're starting a replay");
        }

        @Override
        public void afterReplay() {
            System.out.println("Seems like we've done replaying");
        }

        @Override
        public void onReplayFailed(Throwable cause) {
            System.err.println("The replay failed due to an exception.");
            cause.printStackTrace();
        }
    }

    public static class StubEventStore implements EventStoreManagement, EventStore {

        private final List<DomainEventMessage> eventMessages = new CopyOnWriteArrayList<DomainEventMessage>();

        @Override
        public void appendEvents(String type, DomainEventStream events) {
            while (events.hasNext()) {
                eventMessages.add(events.next());
            }
        }

        @Override
        public void visitEvents(EventVisitor visitor) {
            for (DomainEventMessage eventMessage : eventMessages) {
                visitor.doWithEvent(eventMessage);
            }
        }

        @Override
        public void visitEvents(Criteria criteria, EventVisitor visitor) {
            throw new UnsupportedOperationException("Not implemented yet");
        }

        @Override
        public CriteriaBuilder newCriteriaBuilder() {
            throw new UnsupportedOperationException("Not implemented yet");
        }

        @Override
        public DomainEventStream readEvents(String type, Object identifier) {
            throw new UnsupportedOperationException("Not implemented yet");
        }
    }
}
TOP

Related Classes of org.axonframework.quickstart.RunEventReplay$StubEventStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.