├── emon-vis ├── app │ ├── models │ │ └── .gitkeep │ ├── routes │ │ ├── .gitkeep │ │ └── dashboard.js │ ├── components │ │ ├── .gitkeep │ │ ├── visjs-child.js │ │ ├── visjs-edge.js │ │ └── visjs-node.js │ ├── controllers │ │ ├── .gitkeep │ │ ├── dashboard.js │ │ └── topology.js │ ├── helpers │ │ └── .gitkeep │ ├── templates │ │ ├── components │ │ │ ├── .gitkeep │ │ │ └── visjs-network.hbs │ │ ├── application.hbs │ │ ├── dashboard.hbs │ │ └── topology.hbs │ ├── resolver.js │ ├── styles │ │ └── app.scss │ ├── router.js │ ├── app.js │ ├── mixins │ │ ├── container.js │ │ └── child.js │ ├── index.html │ └── services │ │ └── operation.js ├── tests │ ├── unit │ │ ├── .gitkeep │ │ ├── routes │ │ │ └── topology-test.js │ │ ├── services │ │ │ └── operation-test.js │ │ └── controllers │ │ │ └── topology-test.js │ ├── integration │ │ └── .gitkeep │ ├── .eslintrc.js │ ├── helpers │ │ ├── destroy-app.js │ │ ├── resolver.js │ │ ├── start-app.js │ │ └── module-for-acceptance.js │ ├── test-helper.js │ └── index.html ├── vendor │ └── .gitkeep ├── .watchmanconfig ├── public │ ├── robots.txt │ └── crossdomain.xml ├── server │ ├── .eslintrc.js │ ├── index.js │ └── proxies │ │ └── operations.js ├── bower.json ├── config │ ├── targets.js │ └── environment.js ├── .eslintrc.js ├── .ember-cli ├── .travis.yml ├── .gitignore ├── .editorconfig ├── testem.js ├── ember-cli-build.js ├── README.md └── package.json ├── resources ├── eventapis.png ├── klunge_logo.png ├── checkstyle-suppression.xml └── findbugs-exclude.xml ├── demo-images ├── order_flow.png ├── stock_flow.png ├── payment_flow.png ├── demo_order_flow.png ├── demo_stock_event_flow.png └── demo_order_process_to_payment_flow.png ├── emon ├── docker-compose.yml ├── Dockerfile ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── kloia │ │ │ └── eventapis │ │ │ └── pojos │ │ │ └── OperationTest.java │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── kloia │ │ └── eventapis │ │ └── api │ │ └── emon │ │ ├── dto │ │ ├── ResponseDto.java │ │ └── TopicResponseDto.java │ │ ├── EmonApplication.java │ │ └── service │ │ └── OperationsBroadcaster.java └── README.md ├── emon-lib ├── docker-compose.yml ├── Dockerfile ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── kloia │ │ │ └── eventapis │ │ │ └── api │ │ │ └── emon │ │ │ ├── configuration │ │ │ ├── HazelcastConfigurer.java │ │ │ └── hazelcast │ │ │ │ ├── InMemoryFailedEvent.java │ │ │ │ ├── InMemoryRestoredEvent.java │ │ │ │ ├── QuorumListenerForApplicationEvents.java │ │ │ │ ├── UserCodeDeploymentConfig.java │ │ │ │ ├── NetworkInterfacesConfig.java │ │ │ │ └── MulticastConfig.java │ │ │ ├── domain │ │ │ ├── BaseEvent.java │ │ │ ├── SpanningService.java │ │ │ ├── IHandledEvent.java │ │ │ ├── IProducedEvent.java │ │ │ ├── Partition.java │ │ │ ├── NoneHandled.java │ │ │ ├── OperationEvents.java │ │ │ ├── OperationEvent.java │ │ │ └── ServiceData.java │ │ │ └── service │ │ │ ├── processor │ │ │ └── EndOffsetSetter.java │ │ │ └── EventMessageListener.java │ └── test │ │ └── java │ │ └── com │ │ └── kloia │ │ └── eventapis │ │ └── pojos │ │ └── OperationTest.java └── README.md ├── spec ├── samples │ ├── Sample Event Topology.png │ └── sample-topology-single.json ├── schema │ ├── command.request.json │ ├── event-key.json │ ├── published-event.json │ ├── published-event-wrapper.json │ ├── context.json │ ├── entity-event.json │ ├── operation.json │ └── command.response.json ├── spec-1.0.md └── eventstore.md ├── java-api ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── kloia │ │ │ └── eventapis │ │ │ ├── api │ │ │ ├── CommandDto.java │ │ │ ├── Views.java │ │ │ ├── IdCreationStrategy.java │ │ │ ├── CommandHandler.java │ │ │ ├── EventHandler.java │ │ │ ├── IUserContext.java │ │ │ ├── impl │ │ │ │ ├── UUIDCreationStrategy.java │ │ │ │ └── EmptyUserContext.java │ │ │ ├── Command.java │ │ │ ├── RollbackSpec.java │ │ │ └── ViewQuery.java │ │ │ ├── common │ │ │ ├── EventType.java │ │ │ ├── RecordedEvent.java │ │ │ ├── ReceivedEvent.java │ │ │ ├── EventKey.java │ │ │ ├── PublishedEvent.java │ │ │ ├── Context.java │ │ │ └── EventRecorder.java │ │ │ ├── pojos │ │ │ ├── IOperationEvents.java │ │ │ ├── TransactionState.java │ │ │ ├── EventState.java │ │ │ ├── IEventType.java │ │ │ ├── CommandRecord.java │ │ │ ├── Operation.java │ │ │ └── Event.java │ │ │ ├── TestMain.java │ │ │ ├── exception │ │ │ ├── EventContextException.java │ │ │ ├── EventStoreException.java │ │ │ └── EventPulisherException.java │ │ │ ├── cassandra │ │ │ ├── ConcurrentEventException.java │ │ │ ├── ConcurrentEventResolver.java │ │ │ ├── EntityEvent.java │ │ │ ├── DefaultConcurrencyResolver.java │ │ │ ├── CassandraViewQuery.java │ │ │ └── ConcurrencyResolver.java │ │ │ ├── kafka │ │ │ ├── SerializableConsumer.java │ │ │ ├── IOperationRepository.java │ │ │ ├── PublishedEventWrapper.java │ │ │ ├── KafkaOperationRepositoryFactory.java │ │ │ └── JsonSerializer.java │ │ │ └── view │ │ │ ├── EntityFunction.java │ │ │ ├── SnapshotRepository.java │ │ │ ├── Entity.java │ │ │ ├── BaseEntity.java │ │ │ ├── EntityEventWrapper.java │ │ │ └── EntityFunctionSpec.java │ └── test │ │ └── java │ │ └── com │ │ └── kloia │ │ └── eventapis │ │ ├── api │ │ └── impl │ │ │ ├── UUIDCreationStrategyTest.java │ │ │ └── EmptyUserContextTest.java │ │ └── cassandra │ │ └── DefaultConcurrencyResolverTest.java └── README.md ├── samples ├── 2-basic │ ├── stock-service │ │ ├── src │ │ │ └── main │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── kloia │ │ │ │ │ └── sample │ │ │ │ │ ├── model │ │ │ │ │ ├── StockState.java │ │ │ │ │ └── Stock.java │ │ │ │ │ ├── dto │ │ │ │ │ ├── StockNotEnoughException.java │ │ │ │ │ ├── event │ │ │ │ │ │ ├── ReserveStockEvent.java │ │ │ │ │ │ ├── StockCreatedEvent.java │ │ │ │ │ │ ├── StockNotEnoughEvent.java │ │ │ │ │ │ └── StockReservedEvent.java │ │ │ │ │ └── command │ │ │ │ │ │ ├── CreateStockCommandDto.java │ │ │ │ │ │ └── ReserveStockCommandDto.java │ │ │ │ │ ├── repository │ │ │ │ │ └── StockRepository.java │ │ │ │ │ └── TestStockServiceMain.java │ │ │ │ ├── static │ │ │ │ └── bootstrap.yml │ │ │ │ └── resources │ │ │ │ ├── create-eventdb.sql │ │ │ │ └── application.yml │ │ └── pom.xml │ ├── order-service │ │ ├── src │ │ │ └── main │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── kloia │ │ │ │ │ └── sample │ │ │ │ │ ├── model │ │ │ │ │ ├── OrderState.java │ │ │ │ │ ├── PaymentInformation.java │ │ │ │ │ └── Orders.java │ │ │ │ │ ├── dto │ │ │ │ │ ├── event │ │ │ │ │ │ ├── StockReservedEvent.java │ │ │ │ │ │ ├── PaymentSuccessEvent.java │ │ │ │ │ │ ├── OrderCreatedEvent.java │ │ │ │ │ │ ├── OrderPaidEvent.java │ │ │ │ │ │ ├── PaymentProcessEvent.java │ │ │ │ │ │ └── ReserveStockEvent.java │ │ │ │ │ └── command │ │ │ │ │ │ ├── ItemSoldDto.java │ │ │ │ │ │ ├── OrderPaidCommandDto.java │ │ │ │ │ │ ├── ProcessOrderPaymentCommandDto.java │ │ │ │ │ │ ├── CreateOrderCommandDto.java │ │ │ │ │ │ └── ProcessOrderCommandDto.java │ │ │ │ │ ├── repository │ │ │ │ │ └── OrderRepository.java │ │ │ │ │ ├── TestOrderServiceMain.java │ │ │ │ │ └── controller │ │ │ │ │ └── OrderRestController.java │ │ │ │ ├── static │ │ │ │ └── bootstrap.yml │ │ │ │ └── resources │ │ │ │ ├── create-eventdb.sql │ │ │ │ └── application.yml │ │ └── pom.xml │ └── payment-service │ │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── kloia │ │ │ │ └── sample │ │ │ │ ├── model │ │ │ │ ├── PaymentState.java │ │ │ │ ├── PaymentInformation.java │ │ │ │ └── Payment.java │ │ │ │ ├── dto │ │ │ │ └── event │ │ │ │ │ ├── PaymentProcessEvent.java │ │ │ │ │ ├── PaymentSuccessEvent.java │ │ │ │ │ └── PaymentFailedEvent.java │ │ │ │ ├── repository │ │ │ │ └── PaymentRepository.java │ │ │ │ ├── TestPaymentServiceMain.java │ │ │ │ └── controller │ │ │ │ └── PaymentRestController.java │ │ │ ├── static │ │ │ └── bootstrap.yml │ │ │ └── resources │ │ │ ├── create-eventdb.sql │ │ │ └── application.yml │ │ └── pom.xml └── 3-advanced │ ├── stock-service │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── kloia │ │ │ │ └── sample │ │ │ │ ├── model │ │ │ │ ├── StockState.java │ │ │ │ └── Stock.java │ │ │ │ ├── dto │ │ │ │ ├── StockNotEnoughException.java │ │ │ │ ├── event │ │ │ │ │ ├── ReserveStockEvent.java │ │ │ │ │ ├── WaitingStockReleaseEvent.java │ │ │ │ │ ├── StockCreatedEvent.java │ │ │ │ │ ├── StockNotEnoughEvent.java │ │ │ │ │ ├── StockAddedEvent.java │ │ │ │ │ ├── StockReservedEvent.java │ │ │ │ │ └── StockReleasedEvent.java │ │ │ │ └── command │ │ │ │ │ ├── AddStockCommandDto.java │ │ │ │ │ ├── CreateStockCommandDto.java │ │ │ │ │ └── ReserveStockCommandDto.java │ │ │ │ ├── repository │ │ │ │ └── StockRepository.java │ │ │ │ └── TestStockServiceMain.java │ │ │ ├── static │ │ │ └── bootstrap.yml │ │ │ └── resources │ │ │ ├── create-eventdb.sql │ │ │ └── application.yml │ └── pom.xml │ ├── order-service │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── kloia │ │ │ │ └── sample │ │ │ │ ├── model │ │ │ │ ├── OrderState.java │ │ │ │ ├── PaymentInformation.java │ │ │ │ └── Orders.java │ │ │ │ ├── dto │ │ │ │ ├── event │ │ │ │ │ ├── StockReservedEvent.java │ │ │ │ │ ├── StockReleasedEvent.java │ │ │ │ │ ├── PaymentSuccessEvent.java │ │ │ │ │ ├── OrderCancelledEvent.java │ │ │ │ │ ├── WaitingStockReleaseEvent.java │ │ │ │ │ ├── OrderPaidEvent.java │ │ │ │ │ ├── OrderCreatedEvent.java │ │ │ │ │ ├── PaymentProcessEvent.java │ │ │ │ │ └── ReserveStockEvent.java │ │ │ │ └── command │ │ │ │ │ ├── ItemSoldDto.java │ │ │ │ │ ├── CancelOrderCommandDto.java │ │ │ │ │ ├── OrderPaidCommandDto.java │ │ │ │ │ ├── ReturnPaymentCommandDto.java │ │ │ │ │ ├── ProcessOrderPaymentCommandDto.java │ │ │ │ │ ├── CreateOrderCommandDto.java │ │ │ │ │ └── ProcessOrderCommandDto.java │ │ │ │ ├── repository │ │ │ │ └── OrderRepository.java │ │ │ │ ├── TestOrderServiceMain.java │ │ │ │ └── client │ │ │ │ └── PaymentClient.java │ │ │ ├── static │ │ │ └── bootstrap.yml │ │ │ └── resources │ │ │ ├── create-eventdb.sql │ │ │ └── application.yml │ └── pom.xml │ ├── payment-service │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── kloia │ │ │ │ └── sample │ │ │ │ ├── model │ │ │ │ ├── PaymentState.java │ │ │ │ ├── PaymentInformation.java │ │ │ │ └── Payment.java │ │ │ │ ├── dto │ │ │ │ ├── command │ │ │ │ │ └── ReturnPaymentCommandDto.java │ │ │ │ └── event │ │ │ │ │ ├── PaymentProcessEvent.java │ │ │ │ │ ├── PaymentReturnedEvent.java │ │ │ │ │ ├── PaymentSuccessEvent.java │ │ │ │ │ └── PaymentFailedEvent.java │ │ │ │ ├── repository │ │ │ │ └── PaymentRepository.java │ │ │ │ └── TestPaymentServiceMain.java │ │ │ ├── static │ │ │ └── bootstrap.yml │ │ │ └── resources │ │ │ ├── create-eventdb.sql │ │ │ └── application.yml │ └── pom.xml │ └── docker │ └── docker-compose.yml ├── .gitignore ├── kafka-tester └── src │ └── main │ └── java │ ├── UtilTest.java │ ├── KafkaService.java │ └── Eventapis.java ├── evented-common ├── src │ └── main │ │ └── java │ │ └── com │ │ └── kloia │ │ └── evented │ │ └── IAggregateRepository.java └── pom.xml ├── spring-jpa-view └── src │ └── main │ └── java │ └── com │ └── kloia │ └── eventapis │ └── spring │ └── model │ └── JpaEntity.java ├── spring-integration └── src │ └── main │ └── java │ └── com │ └── kloia │ └── eventapis │ └── spring │ └── configuration │ ├── EventApisConfiguration.java │ ├── AggregateListenerService.java │ ├── SpringKafkaOpListener.java │ └── DataMigrationService.java └── travis └── settings.xml /emon-vis/app/models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/app/routes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/tests/unit/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/vendor/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/app/components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/app/controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/app/helpers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/tests/integration/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/app/templates/components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emon-vis/app/templates/application.hbs: -------------------------------------------------------------------------------- 1 | {{outlet}} -------------------------------------------------------------------------------- /emon-vis/.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /emon-vis/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /emon-vis/server/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /emon-vis/app/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from 'ember-resolver'; 2 | 3 | export default Resolver; 4 | -------------------------------------------------------------------------------- /emon-vis/tests/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | embertest: true 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /emon-vis/app/templates/components/visjs-network.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{yield}} 3 | -------------------------------------------------------------------------------- /resources/eventapis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/resources/eventapis.png -------------------------------------------------------------------------------- /resources/klunge_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/resources/klunge_logo.png -------------------------------------------------------------------------------- /demo-images/order_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/demo-images/order_flow.png -------------------------------------------------------------------------------- /demo-images/stock_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/demo-images/stock_flow.png -------------------------------------------------------------------------------- /emon/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | challenge: 4 | image: 'kloiasoft/eventapis:latest' -------------------------------------------------------------------------------- /demo-images/payment_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/demo-images/payment_flow.png -------------------------------------------------------------------------------- /emon-lib/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | challenge: 4 | image: 'kloiasoft/eventapis:latest' -------------------------------------------------------------------------------- /emon-vis/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emon-vis", 3 | "dependencies": { 4 | "vis": "^4.20.1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo-images/demo_order_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/demo-images/demo_order_flow.png -------------------------------------------------------------------------------- /demo-images/demo_stock_event_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/demo-images/demo_stock_event_flow.png -------------------------------------------------------------------------------- /spec/samples/Sample Event Topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/spec/samples/Sample Event Topology.png -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/CommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | public interface CommandDto { 4 | } 5 | -------------------------------------------------------------------------------- /emon/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | MAINTAINER maaydin 3 | EXPOSE 8080 4 | ADD target/eventapis.jar / 5 | CMD java -jar eventapis.jar -------------------------------------------------------------------------------- /demo-images/demo_order_process_to_payment_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klunge/KlungeFramework/HEAD/demo-images/demo_order_process_to_payment_flow.png -------------------------------------------------------------------------------- /emon-lib/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | MAINTAINER maaydin 3 | EXPOSE 8080 4 | ADD target/eventapis.jar / 5 | CMD java -jar eventapis.jar -------------------------------------------------------------------------------- /emon-vis/tests/helpers/destroy-app.js: -------------------------------------------------------------------------------- 1 | import {run} from '@ember/runloop'; 2 | 3 | export default function destroyApp(application) { 4 | run(application, 'destroy'); 5 | } 6 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/model/StockState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | public enum StockState { 4 | INUSE, OUT, HOLD, DELETED 5 | } 6 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/model/StockState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | public enum StockState { 4 | INUSE, OUT, HOLD, DELETED 5 | } 6 | -------------------------------------------------------------------------------- /emon-vis/app/controllers/dashboard.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | queryParams: ['statusMessage'], 5 | statusMessage: null, 6 | 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/EventType.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | public enum EventType { 4 | OP_SINGLE, OP_START, EVENT, OP_SUCCESS, OP_FAIL; 5 | } 6 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/Views.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | public interface Views { 4 | interface RecordedOnly { 5 | } 6 | 7 | interface PublishedOnly { 8 | } 9 | } -------------------------------------------------------------------------------- /emon-vis/config/targets.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | browsers: [ 4 | 'ie 9', 5 | 'last 1 Chrome versions', 6 | 'last 1 Firefox versions', 7 | 'last 1 Safari versions' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/IdCreationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | /** 4 | * Created by zeldal on 25/05/2017. 5 | */ 6 | public interface IdCreationStrategy { 7 | String nextId(); 8 | } 9 | -------------------------------------------------------------------------------- /emon-vis/tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import Application from '../app'; 2 | import {setApplication} from '@ember/test-helpers'; 3 | import {start} from 'ember-qunit'; 4 | 5 | setApplication(Application.create({autoboot: false})); 6 | 7 | start(); 8 | -------------------------------------------------------------------------------- /emon-vis/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | ecmaVersion: 2017, 5 | sourceType: 'module' 6 | }, 7 | extends: 'eslint:recommended', 8 | env: { 9 | browser: true 10 | }, 11 | rules: {} 12 | }; 13 | -------------------------------------------------------------------------------- /resources/checkstyle-suppression.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/model/OrderState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | public enum OrderState { 4 | INITIAL, RESERVING_STOCK, PAYMENT_READY, PAID, RELEASING_STOCK, PROCESSING_FAILED, CANCELLED, SHIPPED, RETURNED 5 | } 6 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/model/PaymentState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | /** 4 | * Created by zeldalozdemir on 31/01/2017. 5 | */ 6 | 7 | public enum PaymentState { 8 | INITIAL, PAID, FAILED, RETURN 9 | } 10 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/model/OrderState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | public enum OrderState { 4 | INITIAL, RESERVING_STOCK, PAYMENT_READY, PAID, RELEASING_STOCK, PROCESSING_FAILED, CANCELLED, SHIPPED, RETURNED 5 | } 6 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/model/PaymentState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | /** 4 | * Created by zeldalozdemir on 31/01/2017. 5 | */ 6 | 7 | public enum PaymentState { 8 | INITIAL, PAID, FAILED, RETURN 9 | } 10 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/IOperationEvents.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by zeldalozdemir on 20/04/2017. 7 | */ 8 | public interface IOperationEvents extends Serializable { 9 | } 10 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/TransactionState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | /** 4 | * Created by zeldalozdemir on 26/01/2017. 5 | */ 6 | public enum TransactionState { 7 | RUNNING, 8 | TXN_FAILED, 9 | TXN_SUCCEEDED; 10 | } 11 | -------------------------------------------------------------------------------- /emon-vis/app/routes/dashboard.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Route.extend({ 4 | model(params) { 5 | return { 6 | statusMessage: params.statusMessage 7 | } 8 | }, 9 | hasMessage: Ember.computed.notEmpty('model.statusMessage'), 10 | }); 11 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/HazelcastConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration; 2 | 3 | import com.hazelcast.config.Config; 4 | 5 | public interface HazelcastConfigurer { 6 | 7 | Config configure(Config existingConfig); 8 | } 9 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/EventState.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | /** 4 | * Created by zeldalozdemir on 26/01/2017. 5 | */ 6 | public enum EventState { 7 | CREATED, 8 | FAILED, 9 | SUCCEEDED, 10 | TXN_FAILED, 11 | TXN_SUCCEEDED; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /emon-vis/app/templates/dashboard.hbs: -------------------------------------------------------------------------------- 1 |

E-Mon Dashboard

2 | {{input type="text" value=opId class="form-control"}} 3 | 4 | 5 | 6 | {{#if hasMessage}} 7 |

{{{content.statusMessage}}}

8 | {{/if}} 9 | 10 | {{outlet}} -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/CommandHandler.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | /** 4 | * Created by zeldalozdemir on 21/04/2017. 5 | */ 6 | @SuppressWarnings("checkstyle:interfaceistype") 7 | public interface CommandHandler { 8 | long DEFAULT_COMMAND_TIMEOUT = 10000L; 9 | } 10 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/TestMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | /** 6 | * Created by zeldalozdemir on 30/01/2017. 7 | */ 8 | @Slf4j 9 | public class TestMain { 10 | public static void main(String[] args) { 11 | 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /emon-vis/app/styles/app.scss: -------------------------------------------------------------------------------- 1 | @import "ember-bootstrap/bootstrap"; 2 | 3 | .ember-cli-visjs-network .network-canvas { 4 | width: 100%; 5 | height: calc(100vh - 250px); 6 | border: 2px solid #999; 7 | } 8 | 9 | .top-panel { 10 | height: 250px; 11 | width: 100%; 12 | border: #0b2e13; 13 | } 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /emon-vis/.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /emon-vis/tests/helpers/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from '../../resolver'; 2 | import config from '../../config/environment'; 3 | 4 | const resolver = Resolver.create(); 5 | 6 | resolver.namespace = { 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix 9 | }; 10 | 11 | export default resolver; 12 | -------------------------------------------------------------------------------- /emon/src/test/java/com/kloia/eventapis/pojos/OperationTest.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by zeldalozdemir on 26/01/2017. 7 | */ 8 | public class OperationTest { 9 | @Test 10 | public void testReadWriteExternal() throws Exception { 11 | 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/RecordedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | public interface RecordedEvent { 6 | @JsonIgnore 7 | default String getEventName() { 8 | return this.getClass().getSimpleName(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | 5 | /** 6 | * Created by zeldalozdemir on 21/04/2017. 7 | */ 8 | public interface EventHandler { 9 | Object execute(D event) throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /emon/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | 7 | info: 8 | build: 9 | artifact: ${project.artifactId} 10 | name: ${project.name} 11 | description: ${project.description} 12 | version: ${project.version} -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/exception/EventContextException.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.exception; 2 | 3 | /** 4 | * Created by zeldalozdemir on 26/04/2017. 5 | */ 6 | public class EventContextException extends Exception { 7 | public EventContextException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/StockNotEnoughException.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto; 2 | 3 | public class StockNotEnoughException extends Exception { 4 | public StockNotEnoughException() { 5 | } 6 | 7 | public StockNotEnoughException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/StockNotEnoughException.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto; 2 | 3 | public class StockNotEnoughException extends Exception { 4 | public StockNotEnoughException() { 5 | } 6 | 7 | public StockNotEnoughException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/samples/sample-topology-single.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "598f430f-fe08-401c-8285-e26cf0258748", 3 | "handlerName": "OrderCreateCommand", 4 | "serviceName": "order-command-query-service", 5 | "snapshotStatus": "DONE", 6 | "completedTimeInMillis":500, 7 | "events": { 8 | "OrderCreated": { 9 | "type": "OP_SINGLE" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/cassandra/ConcurrentEventException.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | public class ConcurrentEventException extends Exception { 4 | 5 | public ConcurrentEventException() { 6 | } 7 | 8 | public ConcurrentEventException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /emon-vis/.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | - "6" 5 | 6 | sudo: false 7 | dist: trusty 8 | 9 | addons: 10 | chrome: stable 11 | 12 | cache: 13 | directories: 14 | - $HOME/.npm 15 | 16 | env: 17 | global: 18 | # See https://git.io/vdao3 for details. 19 | - JOBS=1 20 | 21 | before_install: 22 | - npm config set spin false 23 | -------------------------------------------------------------------------------- /emon/src/main/java/com/kloia/eventapis/api/emon/dto/ResponseDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.dto; 2 | 3 | import com.kloia.eventapis.api.emon.domain.Topology; 4 | import lombok.Data; 5 | 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | @Data 10 | public class ResponseDto { 11 | private Set> operations; 12 | } 13 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/IUserContext.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | import java.util.Map; 4 | 5 | public interface IUserContext { 6 | Map getUserContext(); 7 | 8 | void extractUserContext(Map userContext); 9 | 10 | void clearUserContext(); 11 | 12 | String getAuditInfo(); 13 | } 14 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/event/ReserveStockEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class ReserveStockEvent extends ReceivedEvent { 8 | private String stockId; 9 | private long numberOfItemsSold; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/ReserveStockEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class ReserveStockEvent extends ReceivedEvent { 8 | private String stockId; 9 | private long numberOfItemsSold; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /emon-vis/tests/unit/routes/topology-test.js: -------------------------------------------------------------------------------- 1 | import {moduleFor, test} from 'ember-qunit'; 2 | 3 | moduleFor('route:topology', 'Unit | Route | topology', { 4 | // Specify the other units that are required for this test. 5 | // needs: ['controller:foo'] 6 | }); 7 | 8 | test('it exists', function (assert) { 9 | let route = this.subject(); 10 | assert.ok(route); 11 | }); 12 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/kafka/SerializableConsumer.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.kafka; 2 | 3 | /** 4 | * Created by zeldalozdemir on 22/02/2017. 5 | */ 6 | 7 | import java.io.Serializable; 8 | import java.util.function.Consumer; 9 | 10 | @FunctionalInterface 11 | public interface SerializableConsumer extends Consumer, Serializable { 12 | 13 | } -------------------------------------------------------------------------------- /emon-vis/app/router.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import config from './config/environment'; 3 | 4 | const Router = Ember.Router.extend({ 5 | location: config.locationType, 6 | rootURL: config.rootURL 7 | }); 8 | 9 | Router.map(function () { 10 | this.route('topology', {path: '/topology/:opId'}); 11 | this.route('dashboard'); 12 | }); 13 | 14 | export default Router; 15 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/BaseEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.kloia.eventapis.common.ReceivedEvent; 5 | import lombok.Data; 6 | 7 | @Data 8 | @JsonIgnoreProperties(ignoreUnknown = true) 9 | public class BaseEvent extends ReceivedEvent { 10 | } 11 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/view/EntityFunction.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.view; 2 | 3 | import com.kloia.eventapis.exception.EventStoreException; 4 | 5 | /** 6 | * Created by zeldalozdemir on 21/02/2017. 7 | */ 8 | @FunctionalInterface 9 | public interface EntityFunction { 10 | E apply(E previous, EntityEventWrapper event) throws EventStoreException; 11 | } -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/IEventType.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | /** 4 | * Created by zeldalozdemir on 30/01/2017. 5 | */ 6 | public enum IEventType { 7 | EXECUTE, 8 | ROLLBACK; 9 | /* 10 | public static final IEventType EXECUTE = new IEventType() { }; 11 | public static final IEventType ROLLBACK = new IEventType() { };*/ 12 | } 13 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/event/StockReservedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class StockReservedEvent extends ReceivedEvent { 8 | private String stockId; 9 | private String orderId; 10 | private long numberOfItemsSold; 11 | } 12 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/StockReservedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class StockReservedEvent extends ReceivedEvent { 8 | private String stockId; 9 | private String orderId; 10 | private long numberOfItemsSold; 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/impl/UUIDCreationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.impl; 2 | 3 | import com.kloia.eventapis.api.IdCreationStrategy; 4 | 5 | import java.util.UUID; 6 | 7 | public class UUIDCreationStrategy implements IdCreationStrategy { 8 | 9 | @Override 10 | public String nextId() { 11 | return UUID.randomUUID().toString(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/static/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | eventapis: 7 | baseEventsPackage: com.kloia.sample.dto 8 | info: 9 | build: 10 | artifact: ${project.artifactId} 11 | name: ${project.name} 12 | description: ${project.description} 13 | version: ${project.version} -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/static/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | eventapis: 7 | baseEventsPackage: com.kloia.sample.dto 8 | info: 9 | build: 10 | artifact: ${project.artifactId} 11 | name: ${project.name} 12 | description: ${project.description} 13 | version: ${project.version} -------------------------------------------------------------------------------- /emon-vis/tests/unit/services/operation-test.js: -------------------------------------------------------------------------------- 1 | import {moduleFor, test} from 'ember-qunit'; 2 | 3 | moduleFor('service:operation', 'Unit | Service | operation', { 4 | // Specify the other units that are required for this test. 5 | // needs: ['service:foo'] 6 | }); 7 | 8 | // Replace this with your real tests. 9 | test('it exists', function (assert) { 10 | let service = this.subject(); 11 | assert.ok(service); 12 | }); 13 | -------------------------------------------------------------------------------- /kafka-tester/src/main/java/UtilTest.java: -------------------------------------------------------------------------------- 1 | import java.util.function.Function; 2 | 3 | public class UtilTest { 4 | public static void main(String[] args) { 5 | Function fn = new Function() { 6 | @Override 7 | public String apply(String s) { 8 | return "test"; 9 | } 10 | }; 11 | System.out.println(fn); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/static/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | eventapis: 7 | baseEventsPackage: com.kloia.sample.dto 8 | info: 9 | build: 10 | artifact: ${project.artifactId} 11 | name: ${project.name} 12 | description: ${project.description} 13 | version: ${project.version} -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/static/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | eventapis: 7 | baseEventsPackage: com.kloia.sample.dto 8 | info: 9 | build: 10 | artifact: ${project.artifactId} 11 | name: ${project.name} 12 | description: ${project.description} 13 | version: ${project.version} -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/static/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | eventapis: 7 | baseEventsPackage: com.kloia.sample.dto 8 | info: 9 | build: 10 | artifact: ${project.artifactId} 11 | name: ${project.name} 12 | description: ${project.description} 13 | version: ${project.version} -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/static/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ${project.artifactId} 4 | hateoas: 5 | use-hal-as-default-json-media-type: false 6 | eventapis: 7 | baseEventsPackage: com.kloia.sample.dto 8 | info: 9 | build: 10 | artifact: ${project.artifactId} 11 | name: ${project.name} 12 | description: ${project.description} 13 | version: ${project.version} -------------------------------------------------------------------------------- /emon-vis/tests/unit/controllers/topology-test.js: -------------------------------------------------------------------------------- 1 | import {moduleFor, test} from 'ember-qunit'; 2 | 3 | moduleFor('controller:topology', 'Unit | Controller | topology', { 4 | // Specify the other units that are required for this test. 5 | // needs: ['controller:foo'] 6 | }); 7 | 8 | // Replace this with your real tests. 9 | test('it exists', function (assert) { 10 | let controller = this.subject(); 11 | assert.ok(controller); 12 | }); 13 | -------------------------------------------------------------------------------- /emon-vis/app/app.js: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from './resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | const App = Application.extend({ 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix, 9 | Resolver 10 | }); 11 | 12 | loadInitializers(App, config.modulePrefix); 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /emon-vis/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # misc 12 | /.sass-cache 13 | /connect.lock 14 | /coverage/* 15 | /libpeerconnection.log 16 | npm-debug.log* 17 | yarn-error.log 18 | testem.log 19 | 20 | # ember-try 21 | .node_modules.ember-try/ 22 | bower.json.ember-try 23 | package.json.ember-try 24 | -------------------------------------------------------------------------------- /emon-vis/app/controllers/topology.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Controller.extend({ 4 | networkOptions: { 5 | nodes: { 6 | color: '#C7F110' 7 | } 8 | }, 9 | nodeColor: '#FF0000', 10 | operation: Ember.inject.service(), 11 | hasMessage: Ember.computed.notEmpty('model.statusMessage'), 12 | actions: { 13 | openTopology(opId) { 14 | this.transitionToRoute("topology", opId); 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/command/ItemSoldDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Created by zeldalozdemir on 31/01/2017. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class ItemSoldDto { 14 | private String stockId; 15 | private long numberOfItemsSold; 16 | } 17 | -------------------------------------------------------------------------------- /emon-vis/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.hbs] 17 | insert_final_newline = false 18 | 19 | [*.{diff,md}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/view/SnapshotRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.view; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | @SuppressWarnings("checkstyle:InterfaceTypeParameterName") 8 | public interface SnapshotRepository { 9 | List saveAll(Iterable entities); 10 | 11 | S save(S entity); 12 | 13 | void flush(); 14 | 15 | Optional findById(ID id); 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/ItemSoldDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Created by zeldalozdemir on 31/01/2017. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class ItemSoldDto { 14 | private String stockId; 15 | private long numberOfItemsSold; 16 | } 17 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/view/Entity.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.view; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by zeldalozdemir on 21/02/2017. 9 | */ 10 | public interface Entity extends Serializable { 11 | 12 | EventKey getEventKey(); 13 | 14 | String getId(); 15 | 16 | void setId(String id); 17 | 18 | int getVersion(); 19 | 20 | void setVersion(int version); 21 | } 22 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/StockReleasedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class StockReleasedEvent extends ReceivedEvent { 12 | private String orderId; 13 | private long numberOfItemsReleased; 14 | } 15 | -------------------------------------------------------------------------------- /emon-vis/testem.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | test_page: 'tests/index.html?hidepassed', 4 | disable_watching: true, 5 | launch_in_ci: [ 6 | 'Chrome' 7 | ], 8 | launch_in_dev: [ 9 | 'Chrome' 10 | ], 11 | browser_args: { 12 | Chrome: { 13 | mode: 'ci', 14 | args: [ 15 | '--disable-gpu', 16 | '--headless', 17 | '--remote-debugging-port=0', 18 | '--window-size=1440,900' 19 | ] 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/WaitingStockReleaseEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class WaitingStockReleaseEvent extends ReceivedEvent { 12 | private String stockId; 13 | private int reservedStockVersion; 14 | } 15 | -------------------------------------------------------------------------------- /spec/schema/command.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/command.request.json", 4 | "title": "EventApis Command Request", 5 | "description": "EventApis Command Request Schema", 6 | "type": "object", 7 | "properties": { 8 | "body": { 9 | "type": "object", 10 | "additionalProperties": true 11 | } 12 | }, 13 | "additionalProperties": true, 14 | "required": [] 15 | } -------------------------------------------------------------------------------- /resources/findbugs-exclude.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/model/PaymentInformation.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Created by zeldalozdemir on 31/01/2017. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class PaymentInformation { 14 | private String paymentAddress; 15 | private float amount; 16 | private String cardInformation; 17 | } 18 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/model/PaymentInformation.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Created by zeldalozdemir on 31/01/2017. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class PaymentInformation { 14 | private String paymentAddress; 15 | private float amount; 16 | private String cardInformation; 17 | } 18 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/command/OrderPaidCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class OrderPaidCommandDto implements CommandDto { 15 | private String paymentId; 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/model/PaymentInformation.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Created by zeldalozdemir on 31/01/2017. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class PaymentInformation { 14 | private String paymentAddress; 15 | private float amount; 16 | private String cardInformation; 17 | } 18 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/CancelOrderCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class CancelOrderCommandDto implements CommandDto { 15 | private String orderId; 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/OrderPaidCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class OrderPaidCommandDto implements CommandDto { 15 | private String paymentId; 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/PaymentSuccessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class PaymentSuccessEvent extends ReceivedEvent { 15 | private String orderId; 16 | } 17 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/kafka/IOperationRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.kafka; 2 | 3 | import com.kloia.eventapis.pojos.Event; 4 | 5 | /** 6 | * Created by zeldalozdemir on 20/04/2017. 7 | */ 8 | public interface IOperationRepository { 9 | 10 | void failOperation(String eventId, SerializableConsumer action); 11 | 12 | void successOperation(String eventId, SerializableConsumer action); 13 | 14 | void publishEvent(String topic, String event, long opDate); 15 | } 16 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/ReturnPaymentCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ReturnPaymentCommandDto implements CommandDto { 15 | private String orderId; 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/OrderCancelledEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class OrderCancelledEvent extends PublishedEvent { 11 | @Override 12 | public EventType getEventType() { 13 | return EventType.OP_SUCCESS; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/event/StockCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class StockCreatedEvent extends PublishedEvent { 9 | private String stockName; 10 | private long remainingStock; 11 | 12 | @Override 13 | public EventType getEventType() { 14 | return EventType.OP_SINGLE; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/event/StockNotEnoughEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class StockNotEnoughEvent extends PublishedEvent { 9 | private String orderId; 10 | private long numberOfItemsSold; 11 | 12 | @Override 13 | public EventType getEventType() { 14 | return EventType.OP_FAIL; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/model/PaymentInformation.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Created by zeldalozdemir on 31/01/2017. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class PaymentInformation { 14 | 15 | private String paymentAddress; 16 | 17 | private float amount; 18 | 19 | private String cardInformation; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/StockCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class StockCreatedEvent extends PublishedEvent { 9 | private String stockName; 10 | private long remainingStock; 11 | 12 | @Override 13 | public EventType getEventType() { 14 | return EventType.OP_SINGLE; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/StockNotEnoughEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class StockNotEnoughEvent extends PublishedEvent { 9 | private String orderId; 10 | private long numberOfItemsSold; 11 | 12 | @Override 13 | public EventType getEventType() { 14 | return EventType.OP_SUCCESS; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/command/ProcessOrderPaymentCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class ProcessOrderPaymentCommandDto implements CommandDto { 15 | 16 | private String orderId; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /evented-common/src/main/java/com/kloia/evented/IAggregateRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.evented; 2 | 3 | /** 4 | * Created by zeldalozdemir on 07/02/2017. 5 | */ 6 | /* 7 | @Repository 8 | public interface IAggregateRepository extends CrudRepository { 9 | 10 | @Query("Select * from customer where firstname=?0") 11 | public IAggregate getAggreagetById(UUID id); 12 | 13 | @Query("Select * from customer where lastname=?0") 14 | public List findByLastName(String lastName); 15 | 16 | }*/ 17 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/event/PaymentSuccessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class PaymentSuccessEvent extends ReceivedEvent { 15 | private String orderId; 16 | private String paymentId; 17 | } 18 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/ProcessOrderPaymentCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class ProcessOrderPaymentCommandDto implements CommandDto { 15 | 16 | private String orderId; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/command/AddStockCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class AddStockCommandDto implements CommandDto { 15 | private long stockToAdd; 16 | private String stockId; 17 | } 18 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/command/CreateStockCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class CreateStockCommandDto implements CommandDto { 15 | private String stockName; 16 | private long remainingStock; 17 | } 18 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/command/ReserveStockCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ReserveStockCommandDto implements CommandDto { 15 | private String orderId; 16 | private long numberOfItemsSold; 17 | } 18 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/command/CreateStockCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class CreateStockCommandDto implements CommandDto { 15 | private String stockName; 16 | private long remainingStock; 17 | } 18 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/hazelcast/InMemoryFailedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration.hazelcast; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | public class InMemoryFailedEvent extends ApplicationEvent { 6 | /** 7 | * Create a new ApplicationEvent. 8 | * 9 | * @param source the object on which the event initially occurred (never {@code null}) 10 | */ 11 | public InMemoryFailedEvent(Object source) { 12 | super(source); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/dto/command/ReturnPaymentCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ReturnPaymentCommandDto implements CommandDto { 15 | private String orderId; 16 | private String paymentId; 17 | } 18 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/command/ReserveStockCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ReserveStockCommandDto implements CommandDto { 15 | private String orderId; 16 | private long numberOfItemsSold; 17 | } 18 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/hazelcast/InMemoryRestoredEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration.hazelcast; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | public class InMemoryRestoredEvent extends ApplicationEvent { 6 | /** 7 | * Create a new ApplicationEvent. 8 | * 9 | * @param source the object on which the event initially occurred (never {@code null}) 10 | */ 11 | public InMemoryRestoredEvent(Object source) { 12 | super(source); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/ReceivedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 21/04/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public abstract class ReceivedEvent implements RecordedEvent { 15 | 16 | private EventKey sender; 17 | 18 | private EventType eventType; 19 | 20 | public EventType getEventType() { 21 | return eventType; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/command/CreateOrderCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class CreateOrderCommandDto implements CommandDto { 15 | private String stockId; 16 | private int orderAmount; 17 | private String description; 18 | } 19 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.kloia.test 8 | samples-basic 9 | 0.6.6 10 | 11 | payment-service 12 | 13 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.kloia.test 8 | samples-basic 9 | 0.6.6 10 | 11 | stock-service 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentProcessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import com.kloia.sample.model.PaymentInformation; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Created by zeldalozdemir on 31/01/2017. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class PaymentProcessEvent extends ReceivedEvent { 16 | private PaymentInformation paymentInformation; 17 | } 18 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/repository/StockRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.repository; 2 | 3 | import com.kloia.eventapis.view.SnapshotRepository; 4 | import com.kloia.sample.model.Stock; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.querydsl.QueryDslPredicateExecutor; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | public interface StockRepository extends JpaRepository, QueryDslPredicateExecutor, SnapshotRepository { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/CreateOrderCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class CreateOrderCommandDto implements CommandDto { 15 | private String stockId; 16 | private int orderAmount; 17 | private String description; 18 | } 19 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.kloia.test 8 | samples-advanced 9 | 0.6.6 10 | 11 | payment-service 12 | 13 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.kloia.test 8 | samples-basic 9 | 0.6.6 10 | 11 | 12 | order-service 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/model/Stock.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import com.kloia.eventapis.spring.model.JpaEntity; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 17/02/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @javax.persistence.Entity(name = "STOCK") 15 | public class Stock extends JpaEntity { 16 | private String stockName; 17 | private long remainingStock; 18 | private StockState state; 19 | } 20 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.kloia.test 8 | samples-advanced 9 | 0.6.6 10 | 11 | 12 | order-service 13 | 14 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentProcessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.ReceivedEvent; 4 | import com.kloia.sample.model.PaymentInformation; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Created by zeldalozdemir on 31/01/2017. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class PaymentProcessEvent extends ReceivedEvent { 16 | private PaymentInformation paymentInformation; 17 | } 18 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.kloia.test 8 | samples-advanced 9 | 0.6.6 10 | 11 | stock-service 12 | 13 | 14 | -------------------------------------------------------------------------------- /emon-vis/tests/helpers/start-app.js: -------------------------------------------------------------------------------- 1 | import Application from '../../app'; 2 | import config from '../../config/environment'; 3 | import {merge} from '@ember/polyfills'; 4 | import {run} from '@ember/runloop'; 5 | 6 | export default function startApp(attrs) { 7 | let attributes = merge({}, config.APP); 8 | attributes = merge(attributes, attrs); // use defaults, but you can override; 9 | 10 | return run(() => { 11 | let application = Application.create(attributes); 12 | application.setupForTesting(); 13 | application.injectTestHelpers(); 14 | return application; 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/repository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.repository; 2 | 3 | 4 | import com.kloia.eventapis.view.SnapshotRepository; 5 | import com.kloia.sample.model.Orders; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.querydsl.QueryDslPredicateExecutor; 8 | import org.springframework.stereotype.Repository; 9 | 10 | @Repository 11 | public interface OrderRepository extends JpaRepository, QueryDslPredicateExecutor, SnapshotRepository { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/repository/StockRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.repository; 2 | 3 | import com.kloia.eventapis.view.SnapshotRepository; 4 | import com.kloia.sample.model.Stock; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.querydsl.QuerydslPredicateExecutor; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | public interface StockRepository extends JpaRepository, QuerydslPredicateExecutor, SnapshotRepository { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /emon-vis/app/components/visjs-child.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import ChildMixin from '../mixins/child'; 3 | 4 | export default Ember.Component.extend(ChildMixin, { 5 | didCreateLayer: Ember.K, 6 | willDestroyLayer: Ember.K, 7 | 8 | layerSetup() { 9 | if (this.get('containerLayer')) { 10 | this.get('containerLayer')._layer.addLayer(this._layer); 11 | } 12 | }, 13 | 14 | layerTeardown() { 15 | if (this.get('containerLayer') && this._layer) { 16 | this.get('containerLayer')._layer.removeLayer(this._layer); 17 | } 18 | this._layer = null; 19 | } 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/repository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.repository; 2 | 3 | 4 | import com.kloia.eventapis.view.SnapshotRepository; 5 | import com.kloia.sample.model.Orders; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.querydsl.QuerydslPredicateExecutor; 8 | import org.springframework.stereotype.Repository; 9 | 10 | @Repository 11 | public interface OrderRepository extends JpaRepository, QuerydslPredicateExecutor, SnapshotRepository { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.repository; 2 | 3 | 4 | import com.kloia.eventapis.view.SnapshotRepository; 5 | import com.kloia.sample.model.Payment; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.querydsl.QueryDslPredicateExecutor; 8 | import org.springframework.stereotype.Repository; 9 | 10 | @Repository 11 | public interface PaymentRepository extends JpaRepository, QueryDslPredicateExecutor, SnapshotRepository { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/StockAddedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class StockAddedEvent extends PublishedEvent { 13 | private long addedStock; 14 | 15 | @Override 16 | public EventType getEventType() { 17 | return EventType.OP_SINGLE; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/view/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.view; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import lombok.Data; 5 | 6 | @Data 7 | public abstract class BaseEntity implements Entity { 8 | 9 | private String id; 10 | private int version; 11 | 12 | public BaseEntity() { 13 | } 14 | 15 | public BaseEntity(String id, int version) { 16 | this.id = id; 17 | this.version = version; 18 | } 19 | 20 | @Override 21 | public EventKey getEventKey() { 22 | return new EventKey(id, version); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.repository; 2 | 3 | 4 | import com.kloia.eventapis.view.SnapshotRepository; 5 | import com.kloia.sample.model.Payment; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.querydsl.QuerydslPredicateExecutor; 8 | import org.springframework.stereotype.Repository; 9 | 10 | @Repository 11 | public interface PaymentRepository extends JpaRepository, QuerydslPredicateExecutor, SnapshotRepository { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/cassandra/ConcurrentEventResolver.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import com.kloia.eventapis.common.RecordedEvent; 5 | import com.kloia.eventapis.exception.EventStoreException; 6 | import org.apache.commons.lang3.tuple.Pair; 7 | 8 | public interface ConcurrentEventResolver { 9 | 10 | void tryMore() throws T; 11 | 12 | Pair calculateNext(R failedEvent, EventKey failedEventKey, int lastVersion) throws T, EventStoreException; 13 | } 14 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/EventKey.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * Created by zeldalozdemir on 13/02/2017. 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Builder 17 | public class EventKey implements Serializable { 18 | 19 | private static final long serialVersionUID = -5751030991267102373L; 20 | 21 | private String entityId; 22 | 23 | private int version; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/command/ProcessOrderCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import com.kloia.sample.model.PaymentInformation; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Created by zeldalozdemir on 31/01/2017. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class ProcessOrderCommandDto implements CommandDto { 16 | private String orderId; 17 | private PaymentInformation paymentInformation; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/command/ProcessOrderCommandDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.command; 2 | 3 | import com.kloia.eventapis.api.CommandDto; 4 | import com.kloia.sample.model.PaymentInformation; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Created by zeldalozdemir on 31/01/2017. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class ProcessOrderCommandDto implements CommandDto { 16 | private String orderId; 17 | private PaymentInformation paymentInformation; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/PublishedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonView; 5 | import com.kloia.eventapis.api.Views; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * Created by zeldalozdemir on 21/04/2017. 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public abstract class PublishedEvent extends ReceivedEvent { 17 | 18 | @JsonView(Views.PublishedOnly.class) 19 | EventKey sender; 20 | 21 | public abstract EventType getEventType(); 22 | } 23 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/dto/event/StockReservedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class StockReservedEvent extends PublishedEvent { 13 | private String orderId; 14 | private long numberOfItemsSold; 15 | 16 | @Override 17 | public EventType getEventType() { 18 | return EventType.EVENT; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentReturnedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class PaymentReturnedEvent extends PublishedEvent { 13 | private String orderId; 14 | private float amount; 15 | 16 | @Override 17 | public EventType getEventType() { 18 | return EventType.OP_SINGLE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/StockReservedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class StockReservedEvent extends PublishedEvent { 13 | private String orderId; 14 | private long numberOfItemsSold; 15 | 16 | @Override 17 | public EventType getEventType() { 18 | return EventType.EVENT; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/dto/event/StockReleasedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class StockReleasedEvent extends PublishedEvent { 13 | private String orderId; 14 | private long numberOfItemsReleased; 15 | 16 | @Override 17 | public EventType getEventType() { 18 | return EventType.EVENT; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /emon/src/main/java/com/kloia/eventapis/api/emon/EmonApplication.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * Created by mali on 20/01/2017. 9 | */ 10 | @Slf4j 11 | @SpringBootApplication 12 | //@ComponentScan(basePackages = {"com.kloia.eventapis.api.store","com.kloia.eventbus"}) 13 | 14 | public class EmonApplication { 15 | 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(EmonApplication.class, args); 19 | 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /java-api/README.md: -------------------------------------------------------------------------------- 1 | * Aggregate Style (Transaction Definition) 2 | * Factory.command(Parameters,EventImplementation,[FailLogic]). 3 | * events(EventCommand,....). 4 | * after(). 5 | * events(EventCommand,....). 6 | * build() 7 | 8 | 9 | * Event Register (Microservice startups) 10 | * Eventstore.register(EventImplementation, [FailLogic]) 11 | 12 | * EventCommand 13 | * name (Microservice Name ?) 14 | * Parameters 15 | 16 | * EventImplementation 17 | * name 18 | * execute (Parameters) 19 | 20 | * FailLogic 21 | * Automatic 22 | * Custom 23 | * Execute (transaction, cause,) -------------------------------------------------------------------------------- /emon-vis/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/WaitingStockReleaseEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class WaitingStockReleaseEvent extends PublishedEvent { 13 | private String stockId; 14 | private int reservedStockVersion; 15 | 16 | @Override 17 | public EventType getEventType() { 18 | return EventType.OP_START; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/Command.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | import com.fasterxml.jackson.annotation.JacksonAnnotation; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * Command Entry Methods. 12 | */ 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @JacksonAnnotation 16 | public @interface Command { 17 | long commandTimeout() default CommandHandler.DEFAULT_COMMAND_TIMEOUT; 18 | 19 | String eventRepository() default "eventRepository"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/model/Payment.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import com.kloia.eventapis.spring.model.JpaEntity; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by zeldalozdemir on 31/01/2017. 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @javax.persistence.Entity(name = "PAYMENT") 15 | public class Payment extends JpaEntity { 16 | private String paymentAddress; 17 | private String orderId; 18 | private float amount; 19 | private String cardInformation; 20 | private PaymentState state; 21 | } 22 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/impl/EmptyUserContext.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.impl; 2 | 3 | import com.kloia.eventapis.api.IUserContext; 4 | 5 | import java.util.Map; 6 | 7 | public class EmptyUserContext implements IUserContext { 8 | 9 | @Override 10 | public Map getUserContext() { 11 | return null; 12 | } 13 | 14 | @Override 15 | public void extractUserContext(Map userContext) { 16 | 17 | } 18 | 19 | @Override 20 | public void clearUserContext() { 21 | 22 | } 23 | 24 | @Override 25 | public String getAuditInfo() { 26 | return null; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/event/OrderCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class OrderCreatedEvent extends PublishedEvent { 13 | private String stockId; 14 | private int orderAmount; 15 | private String description; 16 | 17 | @Override 18 | public EventType getEventType() { 19 | return EventType.OP_SINGLE; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/event/OrderPaidEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Created by zeldalozdemir on 31/01/2017. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class OrderPaidEvent extends PublishedEvent { 16 | private String paymentId; 17 | 18 | @Override 19 | public EventType getEventType() { 20 | return EventType.OP_SUCCESS; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/OrderPaidEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Created by zeldalozdemir on 31/01/2017. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class OrderPaidEvent extends PublishedEvent { 16 | private String paymentId; 17 | 18 | @Override 19 | public EventType getEventType() { 20 | return EventType.OP_SUCCESS; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/OrderCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class OrderCreatedEvent extends PublishedEvent { 13 | private String stockId; 14 | private int orderAmount; 15 | private String description; 16 | 17 | @Override 18 | public EventType getEventType() { 19 | return EventType.OP_SINGLE; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /emon-vis/tests/helpers/module-for-acceptance.js: -------------------------------------------------------------------------------- 1 | import {module} from 'qunit'; 2 | import {resolve} from 'rsvp'; 3 | import startApp from '../helpers/start-app'; 4 | import destroyApp from '../helpers/destroy-app'; 5 | 6 | export default function (name, options = {}) { 7 | module(name, { 8 | beforeEach() { 9 | this.application = startApp(); 10 | 11 | if (options.beforeEach) { 12 | return options.beforeEach.apply(this, arguments); 13 | } 14 | }, 15 | 16 | afterEach() { 17 | let afterEach = options.afterEach && options.afterEach.apply(this, arguments); 18 | return resolve(afterEach).then(() => destroyApp(this.application)); 19 | } 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/cassandra/EntityEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import com.kloia.eventapis.pojos.EventState; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Date; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class EntityEvent { 15 | 16 | private EventKey eventKey; 17 | 18 | private String opId; 19 | 20 | private Date opDate; 21 | 22 | private String eventType; 23 | 24 | private EventState status; 25 | 26 | private String auditInfo; 27 | 28 | private String eventData; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /emon-vis/app/mixins/container.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | const {A} = Ember; 4 | 5 | // From https://github.com/miguelcobain/ember-leaflet/blob/master/addon/mixins/container.js 6 | export default Ember.Mixin.create({ 7 | _childLayers: null, 8 | 9 | init() { 10 | this._super(...arguments); 11 | this.set('_childLayers', new A()); 12 | }, 13 | 14 | registerChild(childLayer) { 15 | this._childLayers.addObject(childLayer); 16 | 17 | if (this._layer) { 18 | childLayer.layerSetup(); 19 | } 20 | }, 21 | 22 | unregisterChild(childLayer) { 23 | this._childLayers.removeObject(childLayer); 24 | 25 | if (this._layer) { 26 | childLayer.layerTeardown(); 27 | } 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentSuccessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.fasterxml.jackson.annotation.JsonView; 4 | import com.kloia.eventapis.api.Views; 5 | import com.kloia.eventapis.common.EventType; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import lombok.Data; 8 | 9 | @Data 10 | public class PaymentSuccessEvent extends PublishedEvent { 11 | private String orderId; 12 | private String paymentAddress; 13 | private float amount; 14 | @JsonView(Views.RecordedOnly.class) 15 | private String cardInformation; 16 | 17 | @Override 18 | public EventType getEventType() { 19 | return EventType.EVENT; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/resources/create-eventdb.sql: -------------------------------------------------------------------------------- 1 | --drop table if exists test.StockEvents ; 2 | CREATE TABLE test.StockEvents ( 3 | entityId ASCII, 4 | version INT, 5 | eventType ASCII, 6 | opId ASCII, 7 | opDate TIMESTAMP, 8 | status ASCII, 9 | auditinfo ASCII, 10 | eventData VARCHAR, 11 | PRIMARY KEY (entityId, version) 12 | ); 13 | 14 | CREATE MATERIALIZED VIEW test.StockEvents_byOps AS 15 | SELECT 16 | opId, 17 | entityId, 18 | version, 19 | eventType, 20 | opDate, 21 | status, 22 | auditinfo, 23 | eventData 24 | FROM test.StockEvents 25 | WHERE opId IS NOT NULL AND entityId IS NOT NULL AND version IS NOT NULL 26 | PRIMARY KEY (opid, entityId, VERSION ); -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/resources/create-eventdb.sql: -------------------------------------------------------------------------------- 1 | --drop table if exists test.StockEvents ; 2 | CREATE TABLE test.StockEvents ( 3 | entityId ASCII, 4 | version INT, 5 | eventType ASCII, 6 | opId ASCII, 7 | opDate TIMESTAMP, 8 | status ASCII, 9 | auditinfo ASCII, 10 | eventData VARCHAR, 11 | PRIMARY KEY (entityId, version) 12 | ); 13 | 14 | CREATE MATERIALIZED VIEW test.StockEvents_byOps AS 15 | SELECT 16 | opId, 17 | entityId, 18 | version, 19 | eventType, 20 | opDate, 21 | status, 22 | auditinfo, 23 | eventData 24 | FROM test.StockEvents 25 | WHERE opId IS NOT NULL AND entityId IS NOT NULL AND version IS NOT NULL 26 | PRIMARY KEY (opid, entityId, VERSION ); -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentSuccessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.fasterxml.jackson.annotation.JsonView; 4 | import com.kloia.eventapis.api.Views; 5 | import com.kloia.eventapis.common.EventType; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import lombok.Data; 8 | 9 | @Data 10 | public class PaymentSuccessEvent extends PublishedEvent { 11 | private String orderId; 12 | private String paymentAddress; 13 | private float amount; 14 | @JsonView(Views.RecordedOnly.class) 15 | private String cardInformation; 16 | 17 | @Override 18 | public EventType getEventType() { 19 | return EventType.EVENT; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/model/Stock.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import com.kloia.eventapis.spring.model.JpaEntity; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.persistence.EnumType; 9 | import javax.persistence.Enumerated; 10 | 11 | /** 12 | * Created by zeldalozdemir on 17/02/2017. 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @javax.persistence.Entity(name = "STOCK") 18 | public class Stock extends JpaEntity { 19 | 20 | private String stockName; 21 | 22 | private long remainingStock; 23 | 24 | @Enumerated(EnumType.STRING) 25 | private StockState state; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/TestOrderServiceMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | /** 8 | * Created by zeldalozdemir on 30/01/2017. 9 | */ 10 | @SpringBootApplication 11 | @ComponentScan(basePackages = {"com.kloia.sample", "com.kloia.eventapis"}) 12 | public class TestOrderServiceMain { 13 | 14 | public static void main(String[] args) { 15 | System.setProperty("spring.devtools.restart.enabled", "false"); 16 | 17 | SpringApplication.run(TestOrderServiceMain.class, args); 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/resources/create-eventdb.sql: -------------------------------------------------------------------------------- 1 | --drop table if exists test.OrderEvents ; 2 | CREATE TABLE test.OrderEvents ( 3 | entityId ASCII, 4 | version INT, 5 | eventType ASCII, 6 | opId ASCII, 7 | opDate TIMESTAMP, 8 | status ASCII, 9 | auditinfo ASCII, 10 | eventData VARCHAR, 11 | PRIMARY KEY (entityId, version) 12 | ); 13 | 14 | 15 | CREATE MATERIALIZED VIEW test.orderevents_byOps AS 16 | SELECT 17 | opId, 18 | entityId, 19 | version, 20 | eventType, 21 | opDate, 22 | status, 23 | auditinfo, 24 | eventData 25 | FROM test.orderevents 26 | WHERE opId IS NOT NULL AND entityId IS NOT NULL AND version IS NOT NULL 27 | PRIMARY KEY (opid, entityId, VERSION ); 28 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/resources/create-eventdb.sql: -------------------------------------------------------------------------------- 1 | --drop table if exists test.OrderEvents ; 2 | CREATE TABLE test.OrderEvents ( 3 | entityId ASCII, 4 | version INT, 5 | eventType ASCII, 6 | opId ASCII, 7 | opDate TIMESTAMP, 8 | status ASCII, 9 | auditinfo ASCII, 10 | eventData VARCHAR, 11 | PRIMARY KEY (entityId, version) 12 | ); 13 | 14 | CREATE MATERIALIZED VIEW test.orderevents_byOps AS 15 | SELECT 16 | opId, 17 | entityId, 18 | version, 19 | eventType, 20 | opDate, 21 | status, 22 | auditinfo, 23 | eventData 24 | FROM test.orderevents 25 | WHERE opId IS NOT NULL AND entityId IS NOT NULL AND version IS NOT NULL 26 | PRIMARY KEY (opid, entityId, VERSION ); 27 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/cassandra/DefaultConcurrencyResolver.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import com.kloia.eventapis.exception.EventStoreException; 5 | 6 | public class DefaultConcurrencyResolver implements ConcurrencyResolver { 7 | @Override 8 | public void tryMore() throws ConcurrentEventException { 9 | throw new ConcurrentEventException("Concurrent Events"); 10 | } 11 | 12 | @Override 13 | public EventKey calculateNext(EventKey eventKey, int lastVersion) throws EventStoreException, ConcurrentEventException { 14 | throw new ConcurrentEventException("Concurrent Events for:" + eventKey); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/resources/create-eventdb.sql: -------------------------------------------------------------------------------- 1 | --drop table if exists test.PaymentEvents ; 2 | CREATE TABLE test.PaymentEvents ( 3 | entityId ASCII, 4 | version INT, 5 | eventType ASCII, 6 | opId ASCII, 7 | opDate TIMESTAMP, 8 | status ASCII, 9 | auditinfo ASCII, 10 | eventData VARCHAR, 11 | PRIMARY KEY (entityId, version) 12 | ); 13 | 14 | 15 | CREATE MATERIALIZED VIEW test.PaymentEvents_byOps AS 16 | SELECT 17 | opId, 18 | entityId, 19 | version, 20 | eventType, 21 | opDate, 22 | status, 23 | auditinfo, 24 | eventData 25 | FROM test.PaymentEvents 26 | WHERE opId IS NOT NULL AND entityId IS NOT NULL AND version IS NOT NULL 27 | PRIMARY KEY (opid, entityId, VERSION ); -------------------------------------------------------------------------------- /spec/schema/event-key.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/event-key.json", 4 | "title": "EventApis Event Key", 5 | "description": "EventApis Event Key Schema", 6 | "type": "object", 7 | "properties": { 8 | "entityId": { 9 | "type": "string", 10 | "description": "Aggregation Id of related Default Entity, UUIDs can be used but not mandatory" 11 | }, 12 | "version": { 13 | "type": "integer", 14 | "minimum": 0, 15 | "description": "Aggregation Version of related Default Entity" 16 | } 17 | }, 18 | "additionalProperties": false, 19 | "required": [ 20 | "entityId", 21 | "version" 22 | ] 23 | } -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/java/com/kloia/sample/TestStockServiceMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | /** 8 | * Created by zeldalozdemir on 30/01/2017. 9 | */ 10 | @SpringBootApplication 11 | @ComponentScan(basePackages = {"com.kloia.sample", "com.kloia.eventapis"}) 12 | public class TestStockServiceMain { 13 | 14 | public static void main(String[] args) { 15 | 16 | System.setProperty("spring.devtools.restart.enabled", "false"); 17 | 18 | SpringApplication.run(TestStockServiceMain.class, args); 19 | 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/resources/create-eventdb.sql: -------------------------------------------------------------------------------- 1 | --drop table if exists test.PaymentEvents ; 2 | CREATE TABLE test.PaymentEvents ( 3 | entityId ASCII, 4 | version INT, 5 | eventType ASCII, 6 | opId ASCII, 7 | opDate TIMESTAMP, 8 | status ASCII, 9 | auditinfo ASCII, 10 | eventData VARCHAR, 11 | PRIMARY KEY (entityId, version) 12 | ); 13 | 14 | 15 | CREATE MATERIALIZED VIEW test.PaymentEvents_byOps AS 16 | SELECT 17 | opId, 18 | entityId, 19 | version, 20 | eventType, 21 | opDate, 22 | status, 23 | auditinfo, 24 | eventData 25 | FROM test.PaymentEvents 26 | WHERE opId IS NOT NULL AND entityId IS NOT NULL AND version IS NOT NULL 27 | PRIMARY KEY (opid, entityId, VERSION ); -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/java/com/kloia/sample/TestStockServiceMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | /** 8 | * Created by zeldalozdemir on 30/01/2017. 9 | */ 10 | @SpringBootApplication 11 | @ComponentScan(basePackages = {"com.kloia.sample", "com.kloia.eventapis"}) 12 | public class TestStockServiceMain { 13 | 14 | public static void main(String[] args) { 15 | 16 | System.setProperty("spring.devtools.restart.enabled", "false"); 17 | 18 | SpringApplication.run(TestStockServiceMain.class, args); 19 | 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/TestPaymentServiceMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | /** 8 | * Created by zeldalozdemir on 30/01/2017. 9 | */ 10 | @SpringBootApplication 11 | @ComponentScan(basePackages = {"com.kloia.sample", "com.kloia.eventapis"}) 12 | public class TestPaymentServiceMain { 13 | 14 | public static void main(String[] args) { 15 | 16 | System.setProperty("spring.devtools.restart.enabled", "false"); 17 | 18 | SpringApplication.run(TestPaymentServiceMain.class, args); 19 | 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/TestPaymentServiceMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | /** 8 | * Created by zeldalozdemir on 30/01/2017. 9 | */ 10 | @SpringBootApplication 11 | @ComponentScan(basePackages = {"com.kloia.sample", "com.kloia.eventapis"}) 12 | public class TestPaymentServiceMain { 13 | 14 | public static void main(String[] args) { 15 | 16 | System.setProperty("spring.devtools.restart.enabled", "false"); 17 | 18 | SpringApplication.run(TestPaymentServiceMain.class, args); 19 | 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /emon-vis/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EmonVis 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | 12 | 13 | 14 | 15 | {{content-for "head-footer"}} 16 | 17 | 18 | {{content-for "body"}} 19 | 20 | 21 | 22 | 23 | {{content-for "body-footer"}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /emon-vis/server/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | // To use it create some files under `mocks/` 5 | // e.g. `server/mocks/ember-hamsters.js` 6 | // 7 | // module.exports = function(app) { 8 | // app.get('/ember-hamsters', function(req, res) { 9 | // res.send('hello'); 10 | // }); 11 | // }; 12 | 13 | module.exports = function (app) { 14 | const globSync = require('glob').sync; 15 | const mocks = globSync('./mocks/**/*.js', {cwd: __dirname}).map(require); 16 | const proxies = globSync('./proxies/**/*.js', {cwd: __dirname}).map(require); 17 | 18 | // Log proxy requests 19 | const morgan = require('morgan'); 20 | app.use(morgan('dev')); 21 | 22 | mocks.forEach(route => route(app)); 23 | proxies.forEach(route => route(app)); 24 | }; 25 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/cassandra/CassandraViewQuery.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.kloia.eventapis.view.Entity; 5 | import com.kloia.eventapis.view.EntityFunctionSpec; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by zeldalozdemir on 12/02/2017. 12 | */ 13 | @Slf4j 14 | public class CassandraViewQuery extends BaseCassandraViewQuery { 15 | 16 | public CassandraViewQuery(String tableName, CassandraSession cassandraSession, ObjectMapper objectMapper, List> commandSpecs) { 17 | super(tableName, cassandraSession, objectMapper, commandSpecs); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /samples/3-advanced/stock-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eventapis: 2 | storeConfig: 3 | contactPoints: localhost:9042 4 | keyspaceName: test 5 | username: cassandra 6 | password: cassandra 7 | eventRecords: 8 | stock: stockevents 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | consumer: 12 | groupId: ${info.build.artifact} 13 | spring: 14 | datasource: 15 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgres} 16 | username: ${DB_USERNAME:postgres} 17 | password: ${DB_PASSWORD:postgres} 18 | type: com.zaxxer.hikari.HikariDataSource 19 | driver-class-name: org.postgresql.Driver 20 | jpa: 21 | hibernate: 22 | ddl-auto: create 23 | show-sql: true 24 | 25 | server: 26 | port: 8162 -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eventapis: 2 | storeConfig: 3 | contactPoints: localhost:9042 4 | keyspaceName: test 5 | username: cassandra 6 | password: cassandra 7 | eventRecords: 8 | payment: paymentevents 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | consumer: 12 | groupId: ${info.build.artifact} 13 | 14 | spring: 15 | datasource: 16 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgres} 17 | username: ${DB_USERNAME:postgres} 18 | password: ${DB_PASSWORD:postgres} 19 | type: com.zaxxer.hikari.HikariDataSource 20 | driver-class-name: org.postgresql.Driver 21 | jpa: 22 | hibernate: 23 | ddl-auto: create 24 | show-sql: true 25 | 26 | server: 27 | port: 8164 -------------------------------------------------------------------------------- /spring-jpa-view/src/main/java/com/kloia/eventapis/spring/model/JpaEntity.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.spring.model; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import com.kloia.eventapis.view.Entity; 5 | import lombok.Data; 6 | 7 | import javax.persistence.Id; 8 | import javax.persistence.MappedSuperclass; 9 | 10 | @Data 11 | @MappedSuperclass 12 | public abstract class JpaEntity implements Entity { 13 | 14 | @Id 15 | private String id; 16 | private int version; 17 | 18 | public JpaEntity() { 19 | } 20 | 21 | public JpaEntity(String id, int version) { 22 | this.id = id; 23 | this.version = version; 24 | } 25 | 26 | @Override 27 | public EventKey getEventKey() { 28 | return new EventKey(id, version); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/SpanningService.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotNull; 8 | import java.io.Serializable; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class SpanningService implements Comparable, Serializable { 14 | 15 | private static final long serialVersionUID = 7156177214906375549L; 16 | 17 | private String serviceName; 18 | private boolean isConsumed; 19 | 20 | @Override 21 | public int compareTo(@NotNull SpanningService spanningService) { 22 | return serviceName.compareTo(spanningService.getServiceName()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/IHandledEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonSubTypes; 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 | 6 | import java.io.Serializable; 7 | 8 | 9 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 10 | include = JsonTypeInfo.As.PROPERTY, 11 | property = "type") 12 | @JsonSubTypes({ 13 | @JsonSubTypes.Type(value = HandledEvent.class, name = "handled"), 14 | @JsonSubTypes.Type(value = NoneHandled.class, name = "none") 15 | }) 16 | public interface IHandledEvent extends Serializable { 17 | boolean isFinished(); 18 | 19 | void setOperation(OperationEvent operation); 20 | 21 | boolean attachOperation(OperationEvent operationToAttach); 22 | } 23 | -------------------------------------------------------------------------------- /emon-lib/README.md: -------------------------------------------------------------------------------- 1 | # Eventapis Store 2 | An event database to enable event sourcing and distributed transactions for applications that use the microservice architecture. 3 | 4 | # Queues 5 | * Queue1 (id-QueueName: AGGREGATE_PARENT, Example: ORDER, ) 6 | * Events: 7 | * id: UUID 8 | * EventName: ORDER_CREATED (Ex: Order Created) 9 | * EventType: EXECUTE|FAIL 10 | * Params (Event Specific Data) 11 | * Transaction Ref (?) 12 | 13 | 14 | 15 | # Aggregate 16 | * Name: AGGREGATE_NAME (ex: SEND_PAYMENT) 17 | * Related Events 18 | * Execute Events (Ex: ORDER_CREATED|EXECUTE) 19 | * Fail Events (Ex: ORDER_CREATED|FAIL) 20 | 21 | 22 | # Transaction 23 | * id: UUID 24 | * StarterAggregate: Aggregate 25 | * Events 26 | * Event1 27 | * Event2 ... 28 | * State -------------------------------------------------------------------------------- /emon/README.md: -------------------------------------------------------------------------------- 1 | # Eventapis Store 2 | An event database to enable event sourcing and distributed transactions for applications that use the microservice architecture. 3 | 4 | # Queues 5 | * Queue1 (id-QueueName: AGGREGATE_PARENT, Example: ORDER, ) 6 | * Events: 7 | * id: UUID 8 | * EventName: ORDER_CREATED (Ex: Order Created) 9 | * EventType: EXECUTE|FAIL 10 | * Params (Event Specific Data) 11 | * Transaction Ref (?) 12 | 13 | 14 | 15 | # Aggregate 16 | * Name: AGGREGATE_NAME (ex: SEND_PAYMENT) 17 | * Related Events 18 | * Execute Events (Ex: ORDER_CREATED|EXECUTE) 19 | * Fail Events (Ex: ORDER_CREATED|FAIL) 20 | 21 | 22 | # Transaction 23 | * id: UUID 24 | * StarterAggregate: Aggregate 25 | * Events 26 | * Event1 27 | * Event2 ... 28 | * State -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/exception/EventStoreException.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.exception; 2 | 3 | /** 4 | * Created by zeldalozdemir on 21/02/2017. 5 | */ 6 | public class EventStoreException extends Exception { 7 | public EventStoreException() { 8 | } 9 | 10 | public EventStoreException(String message) { 11 | super(message); 12 | } 13 | 14 | public EventStoreException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public EventStoreException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | public EventStoreException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 23 | super(message, cause, enableSuppression, writableStackTrace); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/event/PaymentProcessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import com.kloia.sample.model.PaymentInformation; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * Created by zeldalozdemir on 31/01/2017. 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class PaymentProcessEvent extends PublishedEvent { 17 | private String orderId; 18 | private int reservedStockVersion; 19 | private PaymentInformation paymentInformation; 20 | 21 | @Override 22 | public EventType getEventType() { 23 | return EventType.EVENT; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/PaymentProcessEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.kloia.eventapis.common.EventType; 4 | import com.kloia.eventapis.common.PublishedEvent; 5 | import com.kloia.sample.model.PaymentInformation; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * Created by zeldalozdemir on 31/01/2017. 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class PaymentProcessEvent extends PublishedEvent { 17 | private String orderId; 18 | private int reservedStockVersion; 19 | private PaymentInformation paymentInformation; 20 | 21 | @Override 22 | public EventType getEventType() { 23 | return EventType.EVENT; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/model/Payment.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import com.kloia.eventapis.spring.model.JpaEntity; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.persistence.EnumType; 9 | import javax.persistence.Enumerated; 10 | 11 | /** 12 | * Created by zeldalozdemir on 31/01/2017. 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @javax.persistence.Entity(name = "PAYMENT") 18 | public class Payment extends JpaEntity { 19 | 20 | @Enumerated(EnumType.STRING) 21 | private PaymentState state; 22 | 23 | private String paymentAddress; 24 | 25 | private String orderId; 26 | 27 | private float amount; 28 | 29 | private String cardInformation; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/exception/EventPulisherException.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.exception; 2 | 3 | /** 4 | * Created by zeldalozdemir on 21/02/2017. 5 | */ 6 | public class EventPulisherException extends Exception { 7 | public EventPulisherException() { 8 | } 9 | 10 | public EventPulisherException(String message) { 11 | super(message); 12 | } 13 | 14 | public EventPulisherException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public EventPulisherException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | public EventPulisherException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 23 | super(message, cause, enableSuppression, writableStackTrace); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/TestOrderServiceMain.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.openfeign.EnableFeignClients; 6 | import org.springframework.context.annotation.ComponentScan; 7 | 8 | /** 9 | * Created by zeldalozdemir on 30/01/2017. 10 | */ 11 | @SpringBootApplication 12 | @ComponentScan(basePackages = {"com.kloia.sample", "com.kloia.eventapis"}) 13 | @EnableFeignClients 14 | public class TestOrderServiceMain { 15 | 16 | public static void main(String[] args) { 17 | System.setProperty("spring.devtools.restart.enabled", "false"); 18 | 19 | SpringApplication.run(TestOrderServiceMain.class, args); 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/IProducedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonSubTypes; 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 | 6 | import java.io.Serializable; 7 | 8 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 9 | include = JsonTypeInfo.As.PROPERTY, 10 | property = "type") 11 | @JsonSubTypes({ 12 | @JsonSubTypes.Type(value = ProducedEvent.class, name = "event") 13 | }) 14 | public interface IProducedEvent extends Serializable { 15 | 16 | boolean attachHandler(ProducedEvent eventHandler); 17 | 18 | void incrementNumberOfVisit(); 19 | 20 | boolean isFinished(); 21 | 22 | boolean attachOperation(OperationEvent operation); 23 | 24 | void setOperation(OperationEvent operation); 25 | } 26 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eventapis: 2 | storeConfig: 3 | contactPoints: localhost:9042 4 | keyspaceName: test 5 | username: cassandra 6 | password: cassandra 7 | eventRecords: 8 | order: orderevents 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | consumer: 12 | groupId: ${info.build.artifact} 13 | 14 | server: 15 | port: 8160 16 | 17 | spring: 18 | datasource: 19 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgres} 20 | username: ${DB_USERNAME:postgres} 21 | password: ${DB_PASSWORD:postgres} 22 | type: com.zaxxer.hikari.HikariDataSource 23 | driver-class-name: org.postgresql.Driver 24 | jpa: 25 | hibernate: 26 | ddl-auto: create 27 | show-sql: true 28 | 29 | payment-client-url: http://localhost:8164 30 | -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentFailedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.fasterxml.jackson.annotation.JsonView; 4 | import com.kloia.eventapis.api.Views; 5 | import com.kloia.eventapis.common.EventType; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class PaymentFailedEvent extends PublishedEvent { 15 | private String orderId; 16 | private String paymentAddress; 17 | private float amount; 18 | @JsonView(Views.RecordedOnly.class) 19 | private String cardInformation; 20 | 21 | @Override 22 | public EventType getEventType() { 23 | return EventType.OP_FAIL; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/3-advanced/payment-service/src/main/java/com/kloia/sample/dto/event/PaymentFailedEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.fasterxml.jackson.annotation.JsonView; 4 | import com.kloia.eventapis.api.Views; 5 | import com.kloia.eventapis.common.EventType; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class PaymentFailedEvent extends PublishedEvent { 15 | private String orderId; 16 | private String paymentAddress; 17 | private float amount; 18 | @JsonView(Views.RecordedOnly.class) 19 | private String cardInformation; 20 | 21 | @Override 22 | public EventType getEventType() { 23 | return EventType.OP_FAIL; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /evented-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.kloia.eventapis 9 | eventapis-parent 10 | 0.3.0-SNAPSHOT 11 | 12 | 13 | evented-common 14 | 15 | 16 | 17 | 18 | com.kloia.eventapis 19 | java-api 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/dto/event/ReserveStockEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.fasterxml.jackson.annotation.JsonView; 4 | import com.kloia.eventapis.api.Views; 5 | import com.kloia.eventapis.common.EventType; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import com.kloia.sample.model.PaymentInformation; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class ReserveStockEvent extends PublishedEvent { 16 | private String stockId; 17 | private long numberOfItemsSold; 18 | @JsonView(Views.RecordedOnly.class) 19 | private PaymentInformation paymentInformation; 20 | 21 | @Override 22 | public EventType getEventType() { 23 | return EventType.OP_START; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/dto/event/ReserveStockEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.dto.event; 2 | 3 | import com.fasterxml.jackson.annotation.JsonView; 4 | import com.kloia.eventapis.api.Views; 5 | import com.kloia.eventapis.common.EventType; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import com.kloia.sample.model.PaymentInformation; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class ReserveStockEvent extends PublishedEvent { 16 | private String stockId; 17 | private long numberOfItemsSold; 18 | @JsonView(Views.RecordedOnly.class) 19 | private PaymentInformation paymentInformation; 20 | 21 | @Override 22 | public EventType getEventType() { 23 | return EventType.OP_START; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/CommandRecord.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | import com.fasterxml.jackson.annotation.JsonGetter; 4 | import com.fasterxml.jackson.annotation.JsonSetter; 5 | import com.fasterxml.jackson.databind.JsonNode; 6 | import com.kloia.eventapis.common.RecordedEvent; 7 | import lombok.Data; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | @Data 13 | public class CommandRecord implements RecordedEvent { 14 | private Map parameters = new HashMap<>(); 15 | private String eventName; 16 | 17 | @JsonGetter("parameters") 18 | public Map getParameters() { 19 | return (Map) parameters; 20 | } 21 | 22 | @JsonSetter("parameters") 23 | public void setParameters(Map parameters) { 24 | this.parameters = parameters; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/model/Orders.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import com.kloia.eventapis.spring.model.JpaEntity; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | 9 | /** 10 | * Created by zeldalozdemir on 17/02/2017. 11 | */ 12 | @Getter 13 | @Setter 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @javax.persistence.Entity(name = "ORDERS") 17 | public class Orders extends JpaEntity { 18 | private long price; 19 | private String stockId; 20 | private int reservedStockVersion; 21 | private int orderAmount; 22 | private String paymentAddress; 23 | private float amount; 24 | private String cardInformation; 25 | private String paymentId; 26 | private String address; 27 | private String description; 28 | private OrderState state; 29 | } 30 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/cassandra/ConcurrencyResolver.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import com.kloia.eventapis.common.RecordedEvent; 5 | import com.kloia.eventapis.exception.EventStoreException; 6 | import org.apache.commons.lang3.tuple.ImmutablePair; 7 | import org.apache.commons.lang3.tuple.Pair; 8 | 9 | public interface ConcurrencyResolver extends ConcurrentEventResolver { 10 | 11 | void tryMore() throws T; 12 | 13 | EventKey calculateNext(EventKey failedEventKey, int lastVersion) throws T, EventStoreException; 14 | 15 | default Pair calculateNext(RecordedEvent failedEvent, EventKey failedEventKey, int lastVersion) throws T, EventStoreException { 16 | return new ImmutablePair<>(calculateNext(failedEventKey, lastVersion), failedEvent); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /emon-vis/app/services/operation.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Service.extend({ 4 | 5 | latestOperations: {statusMessage: null, operations: []}, 6 | 7 | init() { 8 | this._super(...arguments); 9 | 10 | /* if (!this.get('latestOperations')) { 11 | this.set('latestOperations', []); 12 | }*/ 13 | 14 | }, 15 | initLoadLatestOperations: Ember.on('init', function () { 16 | this.loadLatestOperations(); 17 | Ember.run.later(this, () => { 18 | this.loadLatestOperations(); 19 | this.initLoadLatestOperations(); 20 | }, 1000); 21 | }), 22 | 23 | loadLatestOperations() { 24 | Ember.$.getJSON('/api/operations/v1/').then((data) => { 25 | this.set('latestOperations', {operations: data}); 26 | }, (status) => { 27 | this.set('latestOperations', {statusMessage: "Error while querying Latest Operations"}); 28 | }); 29 | }, 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /emon/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7800 3 | jetty: 4 | acceptors: 2 5 | service: 6 | name: Eventapis Operation Center 7 | 8 | eventapis: 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | zookeeperServers: localhost:2181 12 | consumer: 13 | groupId: ${info.build.artifact} 14 | consumerGroupRegex: "^(.+-service)$" 15 | 16 | emon: 17 | hazelcast: 18 | discovery: 19 | type: multicast 20 | multicast: 21 | multicastGroup: 224.0.0.1 22 | multicastPort: 54327 23 | multicastTimeToLive: 15 24 | multicastTimeoutSeconds: 5 25 | # trustedInterfaces: localhost,127.0.0.1 26 | loopbackModeEnabled: true 27 | interfaces: 28 | enabled: true 29 | interfaces: 127.0.0.1 30 | group: 31 | name: emon 32 | password: emon123 33 | listenTopology: 34 | enabled: true 35 | offsetScheduler: 36 | enabled: true 37 | 38 | -------------------------------------------------------------------------------- /java-api/src/test/java/com/kloia/eventapis/api/impl/UUIDCreationStrategyTest.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.impl; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.mockito.InjectMocks; 6 | import org.mockito.runners.MockitoJUnitRunner; 7 | 8 | import java.util.UUID; 9 | 10 | import static org.hamcrest.Matchers.equalTo; 11 | import static org.junit.Assert.assertThat; 12 | 13 | @RunWith(MockitoJUnitRunner.class) 14 | public class UUIDCreationStrategyTest { 15 | 16 | @InjectMocks 17 | private UUIDCreationStrategy uUIDCreationStrategy; 18 | 19 | @Test 20 | public void shouldGetNextId() throws Exception { 21 | // Given 22 | 23 | // When 24 | String actual = uUIDCreationStrategy.nextId(); 25 | 26 | // Then 27 | UUID uuid = UUID.fromString(actual); 28 | String stringValue = uuid.toString(); 29 | assertThat(actual, equalTo(stringValue)); 30 | } 31 | } -------------------------------------------------------------------------------- /spring-integration/src/main/java/com/kloia/eventapis/spring/configuration/EventApisConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.spring.configuration; 2 | 3 | import com.kloia.eventapis.cassandra.EventStoreConfig; 4 | import com.kloia.eventapis.kafka.KafkaProperties; 5 | import lombok.Data; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Map; 11 | 12 | @ConfigurationProperties("eventapis") 13 | @Component 14 | @Slf4j 15 | @Data 16 | public class EventApisConfiguration { 17 | private EventStoreConfig storeConfig; 18 | private KafkaProperties eventBus; 19 | private Map eventRecords; 20 | private String baseEventsPackage; 21 | 22 | public String getTableNameForEvents(String eventName) { 23 | return getEventRecords().getOrDefault(eventName, eventName); 24 | } 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /emon-vis/server/proxies/operations.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | const proxyPath = '/api/operations/v1/:opId'; 5 | const proxyPathAll = '/api/operations/v1/'; 6 | 7 | module.exports = function (app) { 8 | // For options, see: 9 | // https://github.com/nodejitsu/node-http-proxy 10 | let proxy = require('http-proxy').createProxyServer({}); 11 | 12 | proxy.on('error', function (err, req) { 13 | console.error(err, req.url); 14 | }); 15 | 16 | app.use(proxyPath, function (req, res, next) { 17 | // include root path in proxied request 18 | req.url = proxyPath + '/' + req.url; 19 | proxy.web(req, res, {target: 'http://localhost:7800/operations/v1/' + req.params.opId, ignorePath: true}); 20 | }); 21 | app.use(proxyPathAll, function (req, res, next) { 22 | // include root path in proxied request 23 | req.url = proxyPath + '/' + req.url; 24 | proxy.web(req, res, {target: 'http://localhost:7800/operations/v1/', ignorePath: true}); 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /kafka-tester/src/main/java/KafkaService.java: -------------------------------------------------------------------------------- 1 | import com.fasterxml.jackson.databind.JsonNode; 2 | import lombok.extern.slf4j.Slf4j; 3 | import org.apache.kafka.clients.producer.KafkaProducer; 4 | import org.springframework.kafka.annotation.KafkaListener; 5 | import org.springframework.kafka.core.KafkaTemplate; 6 | import org.springframework.kafka.support.KafkaHeaders; 7 | import org.springframework.messaging.handler.annotation.Header; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @Slf4j 12 | public class KafkaService { 13 | 14 | private KafkaTemplate kafkaTemplate; 15 | private KafkaProducer kafkaProducer; 16 | 17 | @KafkaListener(topics = "test", containerFactory = "eventsKafkaListenerContainerFactory") 18 | public void handleMessage(JsonNode event, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { 19 | kafkaTemplate.send("top", "id", "data"); 20 | 21 | log.warn(topic + " key: " + topic + " EventData: " + event.toString()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/hazelcast/QuorumListenerForApplicationEvents.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration.hazelcast; 2 | 3 | import com.hazelcast.quorum.QuorumEvent; 4 | import com.hazelcast.quorum.QuorumListener; 5 | import org.springframework.context.ApplicationEventPublisher; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class QuorumListenerForApplicationEvents implements QuorumListener { 10 | private final ApplicationEventPublisher publisher; 11 | 12 | public QuorumListenerForApplicationEvents(ApplicationEventPublisher publisher) { 13 | this.publisher = publisher; 14 | } 15 | 16 | @Override 17 | public void onChange(QuorumEvent quorumEvent) { 18 | if(quorumEvent.isPresent()) 19 | publisher.publishEvent(new InMemoryRestoredEvent(quorumEvent)); 20 | else 21 | publisher.publishEvent(new InMemoryFailedEvent(quorumEvent)); 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/view/EntityEventWrapper.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.view; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.kloia.eventapis.cassandra.EntityEvent; 5 | import com.kloia.eventapis.exception.EventStoreException; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * Created by zeldalozdemir on 07/02/2017. 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class EntityEventWrapper { 19 | 20 | private Class type; 21 | private ObjectMapper objectMapper; 22 | private EntityEvent entityEvent; 23 | 24 | public E getEventData() throws EventStoreException { 25 | try { 26 | return objectMapper.readValue(entityEvent.getEventData(), type); 27 | } catch (IOException e) { 28 | throw new EventStoreException(e.getMessage(), e); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /spec/schema/published-event.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/published-event.json", 4 | "title": "EventApis Published Event", 5 | "description": "EventApis Published Event Content Schema", 6 | "type": "object", 7 | "properties": { 8 | "sender": { 9 | "$ref": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/published-event.json" 10 | }, 11 | "eventType": { 12 | "type": "string", 13 | "description": "State Change of the event for Operation", 14 | "enum": [ 15 | "OP_SINGLE", 16 | "OP_START", 17 | "EVENT", 18 | "OP_SUCCESS", 19 | "OP_FAIL" 20 | ] 21 | }, 22 | "eventName": { 23 | "type": "string", 24 | "description": "Name of the Event" 25 | } 26 | }, 27 | "additionalProperties": true, 28 | "required": [ 29 | "sender", 30 | "eventType", 31 | "eventName" 32 | ] 33 | } -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/client/PaymentClient.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.client; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import com.kloia.sample.dto.command.ReturnPaymentCommandDto; 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | 12 | @Component 13 | @FeignClient(name = "paymentClient", url = "${payment-client-url}") 14 | public interface PaymentClient { 15 | 16 | @PostMapping(value = "/payment/{paymentId}/return", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 17 | EventKey returnPaymentCommand(@PathVariable("paymentId") String paymentId, @RequestBody ReturnPaymentCommandDto returnPaymentCommandDto); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/hazelcast/UserCodeDeploymentConfig.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration.hazelcast; 2 | 3 | import com.hazelcast.config.Config; 4 | import com.kloia.eventapis.api.emon.configuration.HazelcastConfigurer; 5 | import lombok.Data; 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Data 11 | @Configuration 12 | @ConditionalOnProperty(value = "emon.hazelcast.user-code-deployment.enabled", havingValue = "true") 13 | @ConfigurationProperties(prefix = "emon.hazelcast.user-code-deployment") 14 | public class UserCodeDeploymentConfig extends com.hazelcast.config.UserCodeDeploymentConfig implements HazelcastConfigurer { 15 | 16 | @Override 17 | public Config configure(Config config) { 18 | config.setUserCodeDeploymentConfig(this); 19 | return config; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/hazelcast/NetworkInterfacesConfig.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration.hazelcast; 2 | 3 | import com.hazelcast.config.Config; 4 | import com.hazelcast.config.InterfacesConfig; 5 | import com.kloia.eventapis.api.emon.configuration.HazelcastConfigurer; 6 | import lombok.Data; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | @Data 12 | @Configuration 13 | @ConditionalOnProperty(value = "emon.hazelcast.interfaces.enabled", havingValue = "true") 14 | @ConfigurationProperties(prefix = "emon.hazelcast.interfaces") 15 | public class NetworkInterfacesConfig extends InterfacesConfig implements HazelcastConfigurer { 16 | 17 | @Override 18 | public Config configure(Config config) { 19 | config.getNetworkConfig().setInterfaces(this); 20 | return config; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /emon-vis/app/mixins/child.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import ContainerMixin from '../mixins/container'; 3 | 4 | const {computed, assert} = Ember; 5 | 6 | // From https://github.com/miguelcobain/ember-leaflet/blob/master/addon/mixins/child.js 7 | export default Ember.Mixin.create({ 8 | 9 | containerLayer: computed(function () { 10 | return this.nearestOfType(ContainerMixin); 11 | }), 12 | 13 | didInsertElement() { 14 | this._super(...arguments); 15 | this.registerWithParent(); 16 | }, 17 | 18 | willDestroyElement() { 19 | this._super(...arguments); 20 | this.unregisterWithParent(); 21 | }, 22 | 23 | registerWithParent() { 24 | let container = this.get('containerLayer'); 25 | assert(`Tried to use ${this} outside the context of a container layer.`, container); 26 | container.registerChild(this); 27 | }, 28 | 29 | unregisterWithParent() { 30 | let container = this.get('containerLayer'); 31 | if (container) { 32 | container.unregisterChild(this); 33 | } 34 | } 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eventapis: 2 | storeConfig: 3 | contactPoints: test-api:9042 4 | keyspaceName: test 5 | username: test_order 6 | password: qwe123 7 | eventRecords: 8 | order: orderevents 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | consumer: 12 | groupId: ${info.build.artifact} 13 | 14 | server: 15 | port: 8160 16 | 17 | spring: 18 | datasource: 19 | url: jdbc:oracle:thin:@test-api:1521:xe 20 | username: TEST_ORDER 21 | password: qwe123 22 | platform: ORACLE 23 | tomcat: 24 | validation-query-timeout: 1 25 | test-while-idle: true 26 | test-on-borrow: true 27 | test-on-return: true 28 | initial-size: 2 29 | min-idle: 1 30 | max-idle: 4 31 | max-active: 8 32 | max-wait: 3000 33 | min-evictable-idle-time-millis: 60000 34 | log-abondoned: true 35 | log-validation-errors: true 36 | jpa: 37 | hibernate: 38 | ddl-auto: create 39 | show-sql: true 40 | 41 | -------------------------------------------------------------------------------- /samples/2-basic/stock-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eventapis: 2 | storeConfig: 3 | contactPoints: test-api:9042 4 | keyspaceName: test 5 | username: test_order 6 | password: qwe123 7 | eventRecords: 8 | stock: stockevents 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | consumer: 12 | groupId: ${info.build.artifact} 13 | spring: 14 | datasource: 15 | url: jdbc:oracle:thin:@test-api:1521:xe 16 | username: TEST_ORDER 17 | password: qwe123 18 | platform: ORACLE 19 | tomcat: 20 | validation-query-timeout: 1 21 | test-while-idle: true 22 | test-on-borrow: true 23 | test-on-return: true 24 | initial-size: 2 25 | min-idle: 1 26 | max-idle: 4 27 | max-active: 8 28 | max-wait: 3000 29 | min-evictable-idle-time-millis: 60000 30 | log-abondoned: true 31 | log-validation-errors: true 32 | jpa: 33 | hibernate: 34 | ddl-auto: update 35 | show-sql: true 36 | 37 | server: 38 | port: 8162 39 | 40 | 41 | -------------------------------------------------------------------------------- /spec/schema/published-event-wrapper.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/published-event-wrapper.json", 4 | "title": "EventApis Published Event Wrapper", 5 | "description": "EventApis Published Event Wrapper Schema", 6 | "type": "object", 7 | "properties": { 8 | "event": { 9 | "type": "string", 10 | "description": "Encapsulated Published Event see event.json" 11 | }, 12 | "context": { 13 | "$ref": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/context.json" 14 | }, 15 | "sender": { 16 | "type": "string", 17 | "description": "Sender of Event - Service Name" 18 | }, 19 | "opDate": { 20 | "type": "integer", 21 | "description": "Event Send Epoch" 22 | }, 23 | "userContext": { 24 | "type": "object", 25 | "description": "User Context extension to carry with events", 26 | "additionalProperties": true 27 | } 28 | }, 29 | "required": [] 30 | } -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/Partition.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @JsonInclude(JsonInclude.Include.NON_NULL) 14 | public class Partition implements Serializable { 15 | private static final long serialVersionUID = -4771113118830062688L; 16 | 17 | private int number; 18 | private Long offset = 0L; 19 | private Long lag; 20 | 21 | public Partition(int number) { 22 | this.number = number; 23 | } 24 | 25 | public Partition(int number, Long offset) { 26 | this.number = number; 27 | this.offset = offset; 28 | } 29 | 30 | public void calculateLag(long endOffset) { 31 | if (endOffset > offset) 32 | lag = endOffset - offset; 33 | else lag = null; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/configuration/hazelcast/MulticastConfig.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.configuration.hazelcast; 2 | 3 | import com.hazelcast.config.Config; 4 | import com.kloia.eventapis.api.emon.configuration.HazelcastConfigurer; 5 | import lombok.Data; 6 | import lombok.ToString; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | @Data 12 | @Configuration 13 | @ConditionalOnProperty(value = "emon.hazelcast.discovery.type", havingValue = "multicast") 14 | @ConfigurationProperties(prefix = "emon.hazelcast.discovery.multicast") 15 | @ToString(callSuper = true) 16 | public class MulticastConfig extends com.hazelcast.config.MulticastConfig implements HazelcastConfigurer { 17 | @Override 18 | public Config configure(Config config) { 19 | config.getNetworkConfig().getJoin().setMulticastConfig(this); 20 | return config; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/RollbackSpec.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | import com.google.common.reflect.TypeToken; 4 | import com.kloia.eventapis.common.RecordedEvent; 5 | 6 | import java.lang.reflect.ParameterizedType; 7 | import java.util.AbstractMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * Created by zeldalozdemir on 21/02/2017. 12 | */ 13 | public interface RollbackSpec

{ 14 | void rollback(P event); 15 | 16 | default Map.Entry> getNameAndClass() { 17 | ParameterizedType type = (ParameterizedType) TypeToken.of(this.getClass()).getSupertype(RollbackSpec.class).getType(); 18 | try { 19 | Class publishedEventClass = (Class) Class.forName(type.getActualTypeArguments()[0].getTypeName()); 20 | return new AbstractMap.SimpleEntry<>(publishedEventClass.getSimpleName(), publishedEventClass); 21 | } catch (ClassNotFoundException e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eventapis: 2 | storeConfig: 3 | contactPoints: test-api:9042 4 | keyspaceName: test 5 | username: test_order 6 | password: qwe123 7 | eventRecords: 8 | payment: paymentevents 9 | eventBus: 10 | bootstrapServers: localhost:9092 11 | # clientId: ${project.artifactId} 12 | consumer: 13 | groupId: ${info.build.artifact} 14 | 15 | spring: 16 | datasource: 17 | url: jdbc:oracle:thin:@test-api:1521:xe 18 | username: TEST_ORDER 19 | password: qwe123 20 | platform: ORACLE 21 | tomcat: 22 | validation-query-timeout: 1 23 | test-while-idle: true 24 | test-on-borrow: true 25 | test-on-return: true 26 | initial-size: 2 27 | min-idle: 1 28 | max-idle: 4 29 | max-active: 8 30 | max-wait: 3000 31 | min-evictable-idle-time-millis: 60000 32 | log-abondoned: true 33 | log-validation-errors: true 34 | jpa: 35 | hibernate: 36 | ddl-auto: create 37 | show-sql: true 38 | 39 | server: 40 | port: 8164 41 | 42 | 43 | -------------------------------------------------------------------------------- /samples/3-advanced/order-service/src/main/java/com/kloia/sample/model/Orders.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.model; 2 | 3 | import com.kloia.eventapis.spring.model.JpaEntity; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | 9 | import javax.persistence.EnumType; 10 | import javax.persistence.Enumerated; 11 | 12 | /** 13 | * Created by zeldalozdemir on 17/02/2017. 14 | */ 15 | @Getter 16 | @Setter 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @javax.persistence.Entity(name = "ORDERS") 20 | public class Orders extends JpaEntity { 21 | 22 | @Enumerated(EnumType.STRING) 23 | private OrderState state; 24 | 25 | private long price; 26 | 27 | private String stockId; 28 | 29 | private int reservedStockVersion; 30 | 31 | private int orderAmount; 32 | 33 | private String paymentAddress; 34 | 35 | private float amount; 36 | 37 | private String cardInformation; 38 | 39 | private String paymentId; 40 | 41 | private String address; 42 | 43 | private String description; 44 | } 45 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/NoneHandled.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonTypeName; 5 | import com.kloia.eventapis.pojos.TransactionState; 6 | import lombok.Data; 7 | 8 | @Data 9 | @JsonTypeName("none") 10 | @JsonInclude(JsonInclude.Include.NON_NULL) 11 | public class NoneHandled implements IHandledEvent { 12 | 13 | private OperationEvent operation; 14 | private boolean finishedAsLeaf = false; 15 | 16 | NoneHandled() { 17 | } 18 | 19 | @Override 20 | public boolean isFinished() { 21 | if (operation != null) 22 | return operation.getTransactionState() == TransactionState.TXN_FAILED; 23 | else return finishedAsLeaf; 24 | } 25 | 26 | @Override 27 | public boolean attachOperation(OperationEvent operationToAttach) { 28 | return false; 29 | } 30 | 31 | @Override 32 | public void setOperation(OperationEvent operation) { 33 | this.operation = operation; 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /emon-vis/ember-cli-build.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 5 | 6 | module.exports = function (defaults) { 7 | let app = new EmberApp(defaults, { 8 | 'ember-bootstrap': { 9 | 'bootstrapVersion': 4, 10 | 'importBootstrapFont': false, 11 | 'importBootstrapCSS': false 12 | } 13 | }); 14 | 15 | // Use `app.import` to add additional libraries to the generated 16 | // output files. 17 | // 18 | // If you need to use different assets in different 19 | // environments, specify an object as the first parameter. That 20 | // object's keys should be the environment name and the values 21 | // should be the asset to use in that environment. 22 | // 23 | // If the library that you are including contains AMD or ES6 24 | // modules that you would like to import into your application 25 | // please specify an object with the list of modules as keys 26 | // along with the exports of each module as its value. 27 | app.import('node_modules/vis/dist/vis.js'); 28 | 29 | 30 | return app.toTree(); 31 | }; 32 | -------------------------------------------------------------------------------- /spring-integration/src/main/java/com/kloia/eventapis/spring/configuration/AggregateListenerService.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.spring.configuration; 2 | 3 | import com.kloia.eventapis.exception.EventStoreException; 4 | import com.kloia.eventapis.pojos.Operation; 5 | import com.kloia.eventapis.view.AggregateListener; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.kafka.clients.consumer.ConsumerRecord; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import java.util.List; 13 | 14 | @Service 15 | @Slf4j 16 | public class AggregateListenerService { 17 | @Autowired(required = false) 18 | List aggregateListeners; 19 | 20 | 21 | @Transactional(rollbackFor = Exception.class) 22 | public void listenOperations(ConsumerRecord record) throws EventStoreException { 23 | for (AggregateListener snapshotRecorder : aggregateListeners) { 24 | snapshotRecorder.listenOperations(record); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /emon-vis/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EmonVis Tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "head-footer"}} 18 | {{content-for "test-head-footer"}} 19 | 20 | 21 | {{content-for "body"}} 22 | {{content-for "test-body"}} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{content-for "body-footer"}} 31 | {{content-for "test-body-footer"}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /spec/schema/context.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/context.json", 4 | "title": "EventApis Event Context", 5 | "description": "EventApis Event Context Schema", 6 | "type": "object", 7 | "properties": { 8 | "opId": { 9 | "type": "string", 10 | "description": "Operation Id initially given while invoking command" 11 | }, 12 | "parentOpId": { 13 | "type": "string", 14 | "description": "Parent Operation Id for nested invocations" 15 | }, 16 | "commandContext": { 17 | "type": "string", 18 | "description": "Name of Initial Command" 19 | }, 20 | "commandTimeout": { 21 | "type": "integer", 22 | "description": "Timeout in Milliseconds, After this timeout Operation will be assumed as finalized" 23 | }, 24 | "startTime": { 25 | "type": "integer", 26 | "description": "Reference starting time of Operation" 27 | } 28 | }, 29 | "required": [ 30 | "opId", 31 | "commandContext", 32 | "commandTimeout", 33 | "startTime" 34 | ] 35 | } -------------------------------------------------------------------------------- /emon-vis/app/components/visjs-edge.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import VisJsChild from '../components/visjs-child'; 3 | 4 | export default VisJsChild.extend({ 5 | type: 'edge', 6 | 7 | /** 8 | * @public 9 | * 10 | * Node-ID for the starting-point of this edge. 11 | * @type {String} 12 | */ 13 | from: '', 14 | 15 | /** 16 | * @public 17 | * 18 | * Node-ID for the target-point of this edge. 19 | * @type {String} 20 | */ 21 | to: '', 22 | 23 | eId: Ember.computed('from', 'to', function () { 24 | return `${this.get('from')}-${this.get('to')}`; 25 | }), 26 | 27 | arrowChanged: Ember.observer('arrows', function () { 28 | let container = this.get('containerLayer'); 29 | container.updateEdgeArrow(this.get('eId'), this.get('arrows')); 30 | }), 31 | 32 | /** 33 | * @public 34 | * 35 | * If set this displays a label under/in the node, depending on 36 | * whether an image is shown or not. 37 | * @type {String} 38 | */ 39 | label: undefined, 40 | 41 | labelChanged: Ember.observer('label', function () { 42 | let container = this.get('containerLayer'); 43 | container.updateEdgeLabel(this.get('eId'), this.get('label')); 44 | }), 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/OperationEvents.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import com.kloia.eventapis.pojos.TransactionState; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @JsonFormat(shape = JsonFormat.Shape.OBJECT) 19 | public class OperationEvents { 20 | 21 | private static final long serialVersionUID = -2419694872838243026L; 22 | 23 | @JsonProperty 24 | private TransactionState transactionState = TransactionState.RUNNING; 25 | 26 | @JsonProperty 27 | private boolean finished; 28 | 29 | @JsonProperty 30 | private List spanningServices = new ArrayList<>(); 31 | 32 | 33 | @JsonIgnore 34 | private Map userContext; 35 | 36 | public OperationEvents(Map userContext) { 37 | this.userContext = userContext; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/Operation.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | import com.kloia.eventapis.common.Context; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by zeldalozdemir on 25/01/2017. 14 | */ 15 | @Data 16 | @ToString(exclude = "userContext") 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class Operation implements Serializable { 20 | public static final String OPERATION_EVENTS = "operation-events"; 21 | private static final long serialVersionUID = -2003849346218727591L; 22 | 23 | private TransactionState transactionState; 24 | private String aggregateId; 25 | private String sender; 26 | private String parentId; // alias for as context.getParentOpId() 27 | private Context context; 28 | private long opDate; 29 | private Map userContext; 30 | 31 | /** 32 | * Backward compatible. 33 | * 34 | * @return 35 | */ 36 | public String getParentId() { 37 | return parentId != null ? parentId : (context != null ? context.getParentOpId() : null); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/OperationEvent.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.kloia.eventapis.common.Context; 4 | import com.kloia.eventapis.pojos.Operation; 5 | import com.kloia.eventapis.pojos.TransactionState; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.io.Serializable; 11 | 12 | /** 13 | * Created by zeldalozdemir on 25/01/2017. 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class OperationEvent implements Serializable { 19 | 20 | 21 | private static final long serialVersionUID = 3269757297830153667L; 22 | private TransactionState transactionState; 23 | private String aggregateId; 24 | private String sender; 25 | private long opDate; 26 | private Context context; 27 | 28 | public OperationEvent(Operation operation) { 29 | this.transactionState = operation.getTransactionState(); 30 | this.aggregateId = operation.getAggregateId(); 31 | this.sender = operation.getSender(); 32 | this.context = operation.getContext(); 33 | this.opDate = operation.getOpDate() != 0L ? operation.getOpDate() : System.currentTimeMillis(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /spec/spec-1.0.md: -------------------------------------------------------------------------------- 1 | service: Microservices in general, 2 types in general. BPM: Service 2 | command-service: Handler for Command/Events. (BPM Process) 3 | query-service: Query and Snapshot Handler. (BPM Process, Listener) 4 | 5 | event: Events Sourcing. fired by command-service, can be listened my zero or more command-service 6 | OP_EVENT: Ordinary Event 7 | TX_FAIL: Failure events 8 | TX_SUCCESS: Successful events 9 | OP_SINGLE: OP_EVENT+TX_SUCCESS together 10 | 11 | Snapshot: 12 | status: NOT_STARTED/IN_PROGRESS/DONE/ERROR 13 | 14 | ``` 15 | Operation 16 | id: operation-id (transaction-id -> uuid) 17 | handler-name: (command-service) (BPM Process) 18 | service-name: 19 | events: 20 | Event1: 21 | listeners: 22 | EventListener1: (command-service) (BPM Process) 23 | EventListener2: (command-service) (BPM Process) 24 | ... 25 | Event2: 26 | listeners: 27 | EventListener3: (command-service) (BPM Process) 28 | Event3: 29 | ... 30 | Event4: 31 | ... 32 | ... 33 | 34 | ``` -------------------------------------------------------------------------------- /samples/3-advanced/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | postgres: 5 | image: postgres 6 | container_name: postgresdb 7 | ports: 8 | - "5432:5432" 9 | environment: 10 | - POSTGRES_DB=postgres 11 | - POSTGRES_USER=postgres 12 | - POSTGRES_PASSWORD=postgres 13 | networks: 14 | - postgres 15 | zookeeper: 16 | image: wurstmeister/zookeeper 17 | ports: 18 | - "2181:2181" 19 | environment: 20 | - KAFKA_ADVERTISED_HOST_NAME=zookeeper 21 | kafka: 22 | image: wurstmeister/kafka 23 | ports: 24 | - "9092:9092" 25 | environment: 26 | - KAFKA_ADVERTISED_PORT=9092 27 | - KAFKA_ADVERTISED_HOST_NAME=127.0.0.1 28 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 29 | - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true 30 | links: 31 | - zookeeper 32 | cassandra: 33 | image: 'bitnami/cassandra:3' 34 | ports: 35 | - '7000:7000' 36 | - '9042:9042' 37 | volumes: 38 | - 'cassandra_data:/bitnami' 39 | environment: 40 | - CASSANDRA_SEEDS=cassandra 41 | - CASSANDRA_PASSWORD_SEEDER=yes 42 | - CASSANDRA_PASSWORD=cassandra 43 | volumes: 44 | cassandra_data: 45 | driver: local 46 | networks: 47 | postgres: 48 | driver: bridge -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/pojos/Event.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Externalizable; 8 | import java.io.IOException; 9 | import java.io.ObjectInput; 10 | import java.io.ObjectOutput; 11 | import java.util.UUID; 12 | 13 | /** 14 | * Created by zeldalozdemir on 26/01/2017. 15 | */ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class Event implements Externalizable, Cloneable { 20 | private UUID eventId; 21 | private IEventType eventType; 22 | private EventState eventState; 23 | private String[] params; 24 | 25 | public void writeExternal(ObjectOutput out) throws IOException { 26 | out.writeUTF(eventId.toString()); 27 | out.writeUTF(eventState.name()); 28 | } 29 | 30 | public void readExternal(ObjectInput in) throws IOException { 31 | eventId = UUID.fromString(in.readUTF()); 32 | eventState = EventState.valueOf(EventState.class, in.readUTF()); 33 | 34 | } 35 | 36 | @Override 37 | public Object clone() { 38 | try { 39 | return super.clone(); 40 | } catch (CloneNotSupportedException e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /emon-vis/app/templates/topology.hbs: -------------------------------------------------------------------------------- 1 | {{outlet}} 2 |

3 |
4 |
5 |
6 | {{input type="text" value=opId class="form-control"}} 7 | 8 | {{#if hasMessage}} 9 |

{{{model.statusMessage}}}

10 | {{/if}} 11 |
12 |
13 |

Latest Operations

14 | {{#each operation.latestOperations.operations as |operation|}} 15 |
  • 16 | {{#link-to "topology" operation.opId preventDefault=false}} 17 | {{operation.initiatorCommand}}@{{operation.initiatorService}}/{{operation.opId}} 18 | {{/link-to}} 19 |
  • 20 | {{/each}} 21 |
    22 |
    23 | 24 | 25 |
    26 |
    27 | {{#visjs-network}} 28 | {{#each model.nodes as |x|}} 29 | {{visjs-node nId=x.nId label=x.label color=x.color shape=x.shape}} 30 | {{/each}} 31 | {{#each model.edges as |x|}} 32 | {{visjs-edge from=x.from to=x.to label=x.label arrows='to'}} 33 | {{/each}} 34 | {{/visjs-network}} 35 |
    36 | 37 |
    38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /spec/schema/entity-event.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/entity-event.json", 4 | "title": "EventApis Published Event Wrapper", 5 | "description": "EventApis Published Event Wrapper Schema", 6 | "type": "object", 7 | "properties": { 8 | "eventKey": { 9 | "$ref": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/event.key.json" 10 | }, 11 | "opId": { 12 | "type": "string", 13 | "description": "Operation Id initially given while invoking command" 14 | }, 15 | "opDate": { 16 | "type": "integer", 17 | "description": "Event Recorded Epoch" 18 | }, 19 | "eventType": { 20 | "type": "string", 21 | "description": "Type/Name of Event" 22 | }, 23 | "status": { 24 | "type": "string", 25 | "enum": [ 26 | "CREATED", 27 | "TXN_FAILED" 28 | ] 29 | }, 30 | "auditInfo": { 31 | "type": "string", 32 | "description": "Custom Audit Info for User Extension" 33 | }, 34 | "eventData": { 35 | "type": "string", 36 | "description": "Event Data as Json" 37 | } 38 | }, 39 | "required": [ 40 | "eventKey", 41 | "opId", 42 | "opDate", 43 | "eventType", 44 | "status", 45 | "eventData" 46 | ] 47 | } -------------------------------------------------------------------------------- /spec/eventstore.md: -------------------------------------------------------------------------------- 1 | # Eventstore Specification 2 | 3 | This specification defines an Eventstore, consisting of a event pub/sub layer, event processing layer and a persistence layer. 4 | 5 | The goal of this specification is to enable the creation of interoperable tools for building an Eventstore. 6 | 7 | ## Table of Contents 8 | - [Introduction](#eventstore-specification) 9 | - [Overview](#overview) 10 | - [Events](#events) 11 | - [Event States](#event-states) 12 | - [Eventstore](#eventstore) 13 | 14 | # Overview 15 | At a high level the eventstore provides a channel to publish events and subscribe to event streams. 16 | 17 | # Events 18 | - Transaction Id 19 | - Event Id 20 | - Type 21 | - Status (New states should be handled as new events) 22 | - TTL 23 | - Data 24 | - Datetime 25 | - Initiator 26 | 27 | # Event States 28 | - Created 29 | - Failed 30 | - Succeeded 31 | - TXN Failed 32 | - TXN Succeeded 33 | 34 | # Eventstore 35 | - Publish to multi-instance of a service is optinal 36 | - Event store should handle timeouts and failures and create events automatically to trigger compansating transactions. 37 | - Transaction locks on application layer can not be handled by the eventstore, an application should handle it's own locks on case of cancel or fail events triggered for a process which is already running. 38 | - Eventstore should know the worker of an event on proccessing state. 39 | -------------------------------------------------------------------------------- /emon-vis/config/environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | module.exports = function (environment) { 5 | let ENV = { 6 | modulePrefix: 'emon-vis', 7 | environment, 8 | rootURL: '/', 9 | locationType: 'auto', 10 | EmberENV: { 11 | FEATURES: { 12 | // Here you can enable experimental features on an ember canary build 13 | // e.g. 'with-controller': true 14 | }, 15 | EXTEND_PROTOTYPES: { 16 | // Prevent Ember Data from overriding Date.parse. 17 | Date: false 18 | } 19 | }, 20 | 21 | APP: { 22 | // Here you can pass flags/options to your application instance 23 | // when it is created 24 | } 25 | }; 26 | 27 | if (environment === 'development') { 28 | // ENV.APP.LOG_RESOLVER = true; 29 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 30 | // ENV.APP.LOG_TRANSITIONS = true; 31 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 32 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 33 | } 34 | 35 | if (environment === 'test') { 36 | // Testem prefers this... 37 | ENV.locationType = 'none'; 38 | 39 | // keep test console output quieter 40 | ENV.APP.LOG_ACTIVE_GENERATION = false; 41 | ENV.APP.LOG_VIEW_LOOKUPS = false; 42 | 43 | ENV.APP.rootElement = '#ember-testing'; 44 | } 45 | 46 | if (environment === 'production') { 47 | 48 | } 49 | 50 | return ENV; 51 | }; 52 | -------------------------------------------------------------------------------- /java-api/src/test/java/com/kloia/eventapis/cassandra/DefaultConcurrencyResolverTest.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.cassandra; 2 | 3 | import com.kloia.eventapis.common.EventKey; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.mockito.InjectMocks; 8 | import org.mockito.runners.MockitoJUnitRunner; 9 | 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | 12 | 13 | @RunWith(MockitoJUnitRunner.class) 14 | public class DefaultConcurrencyResolverTest { 15 | 16 | @InjectMocks 17 | private DefaultConcurrencyResolver defaultConcurrencyResolver; 18 | 19 | @Test 20 | public void testTryMore() throws Exception { 21 | try { 22 | defaultConcurrencyResolver.tryMore(); 23 | } catch (Exception e) { 24 | assertThat(e, Matchers.instanceOf(ConcurrentEventException.class)); 25 | assertThat(e.getMessage(), Matchers.containsString("Concurrent Events")); 26 | } 27 | } 28 | 29 | @Test 30 | public void testCalculateNext() throws Exception { 31 | EventKey eventKey = new EventKey("stock", 4); 32 | 33 | try { 34 | defaultConcurrencyResolver.calculateNext(eventKey, 5); 35 | } catch (Exception e) { 36 | assertThat(e, Matchers.instanceOf(ConcurrentEventException.class)); 37 | assertThat(e.getMessage(), Matchers.containsString("Concurrent Events for:")); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /spec/schema/operation.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/operation.json", 4 | "title": "EventApis Event Wrapper", 5 | "description": "EventApis Event Wrapper Schema", 6 | "type": "object", 7 | "properties": { 8 | "event": { 9 | "transactionState": "string", 10 | "description": "Published state of Operation", 11 | "enum": [ 12 | "RUNNING", 13 | "TXN_FAILED", 14 | "TXN_SUCCEEDED" 15 | ] 16 | }, 17 | "aggregateId": { 18 | "type": "string", 19 | "description": "Aggregate Id of Operation" 20 | }, 21 | "parentId": { 22 | "type": "string", 23 | "description": "Sender of Event - Service Name" 24 | }, 25 | "sender": { 26 | "type": "string", 27 | "description": "Sender of Event - Service Name" 28 | }, 29 | "opDate": { 30 | "type": "integer", 31 | "description": "Event Send Epoch" 32 | }, 33 | "context": { 34 | "$ref": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/context.json" 35 | }, 36 | "userContext": { 37 | "type": "object", 38 | "description": "User Context extension to carry with events", 39 | "additionalProperties": true 40 | } 41 | }, 42 | "required": [ 43 | "event", 44 | "sender", 45 | "aggregateId", 46 | "context", 47 | "opDate", 48 | "userContext" 49 | ] 50 | } -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/Context.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.function.Consumer; 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") 16 | public class Context implements Serializable { 17 | 18 | private static final long serialVersionUID = 7165801319573687119L; 19 | 20 | private String opId; 21 | private String parentOpId; 22 | private String commandContext; 23 | private long commandTimeout; 24 | private long startTime; 25 | 26 | @JsonIgnore 27 | private transient boolean preGenerated; 28 | @JsonIgnore 29 | private transient List> preGenerationConsumers = new ArrayList<>(); 30 | 31 | public Context(String opId) { 32 | this.opId = opId; 33 | } 34 | 35 | public void setGenerated() { 36 | preGenerated = false; 37 | preGenerationConsumers.forEach(contextConsumer -> contextConsumer.accept(this)); 38 | } 39 | 40 | // private long getExpireTime() { 41 | // return startTime + commandTimeout; 42 | // } 43 | // 44 | // public boolean isEmpty() { 45 | // return opId == null; 46 | // } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /spring-integration/src/main/java/com/kloia/eventapis/spring/configuration/SpringKafkaOpListener.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.spring.configuration; 2 | 3 | import com.kloia.eventapis.api.IUserContext; 4 | import com.kloia.eventapis.exception.EventStoreException; 5 | import com.kloia.eventapis.pojos.Operation; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.kafka.clients.consumer.ConsumerRecord; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.kafka.annotation.KafkaListener; 10 | import org.springframework.stereotype.Controller; 11 | 12 | @Controller 13 | @Slf4j 14 | public class SpringKafkaOpListener { 15 | @Autowired(required = false) 16 | AggregateListenerService aggregateListenerService; 17 | 18 | @Autowired 19 | IUserContext userContext; 20 | 21 | @KafkaListener(topics = Operation.OPERATION_EVENTS, containerFactory = "operationsKafkaListenerContainerFactory") 22 | void listenOperations(ConsumerRecord record) throws EventStoreException { 23 | String key = record.key(); 24 | Operation value = record.value(); 25 | log.debug("Trying Snapshot: " + key + " " + value); 26 | userContext.extractUserContext(value.getUserContext()); 27 | aggregateListenerService.listenOperations(record); 28 | } 29 | 30 | public void recover(Exception exception) throws Exception { 31 | log.error("Operation Handle is failed"); 32 | throw exception; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /emon-vis/app/components/visjs-node.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import VisJsChild from '../components/visjs-child'; 3 | 4 | export default VisJsChild.extend({ 5 | type: 'node', 6 | 7 | /** 8 | * @public 9 | * 10 | * Unique node-identifier. Also use this value for the 11 | * edges. 12 | * @type {String} 13 | */ 14 | nId: '', 15 | 16 | /** 17 | * @public 18 | * 19 | * If set, this overrides the networks global color. 20 | * Use a Hex-Value when setting this. 21 | * @type {String} 22 | */ 23 | color: false, 24 | 25 | colorChanged: Ember.observer('color', function () { 26 | let container = this.get('containerLayer'); 27 | container.updateNodeColor(this.get('nId'), this.get('color')); 28 | }), 29 | 30 | /** 31 | * @public 32 | * 33 | * If set this displays a label under/in the node, depending on 34 | * whether an image is shown or not. 35 | * @type {String} 36 | */ 37 | label: undefined, 38 | 39 | labelChanged: Ember.observer('label', function () { 40 | let container = this.get('containerLayer'); 41 | container.updateNodeLabel(this.get('nId'), this.get('label')); 42 | }), 43 | 44 | /** 45 | * @public 46 | * 47 | * If set, a given image-url will be shown as image. 48 | * @type {String} 49 | */ 50 | image: false, 51 | 52 | imageChanged: Ember.observer('image', function () { 53 | let container = this.get('containerLayer'); 54 | container.updateNodeImage(this.get('nId'), this.get('image')); 55 | }) 56 | 57 | }); 58 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/service/processor/EndOffsetSetter.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.service.processor; 2 | 3 | import com.hazelcast.map.AbstractEntryProcessor; 4 | import com.kloia.eventapis.api.emon.domain.Partition; 5 | import com.kloia.eventapis.api.emon.domain.Topic; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.util.Map; 9 | 10 | @Slf4j 11 | public class EndOffsetSetter extends AbstractEntryProcessor { 12 | 13 | private static final long serialVersionUID = 1754073597874826572L; 14 | 15 | private final int partitionNo; 16 | private final long offset; 17 | 18 | public EndOffsetSetter(int partitionNo, long offset) { 19 | this.partitionNo = partitionNo; 20 | this.offset = offset; 21 | } 22 | 23 | @Override 24 | public Object process(Map.Entry entry) { 25 | Topic topic = entry.getValue(); 26 | if (topic == null) { 27 | log.warn("Null Topic Registration in EndOffsetSetter" + entry.getKey()); 28 | topic = new Topic(); 29 | } 30 | topic.getPartitions().compute(partitionNo, (integer, partition) -> { 31 | if (partition == null) { 32 | return new Partition(partitionNo, offset); 33 | } else { 34 | partition.setOffset(Math.max(offset, partition.getOffset())); 35 | } 36 | return partition; 37 | }); 38 | entry.setValue(topic); 39 | return entry; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/view/EntityFunctionSpec.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.view; 2 | 3 | import com.google.common.reflect.TypeToken; 4 | import lombok.Getter; 5 | import lombok.NonNull; 6 | 7 | import java.lang.reflect.ParameterizedType; 8 | 9 | /** 10 | * Created by zeldalozdemir on 21/02/2017. 11 | */ 12 | @Getter 13 | public abstract class EntityFunctionSpec { 14 | @Getter 15 | private final EntityFunction entityFunction; 16 | 17 | public EntityFunctionSpec(@NonNull EntityFunction entityFunction) { 18 | this.entityFunction = entityFunction; 19 | } 20 | 21 | public Class getQueryType() { 22 | ParameterizedType type = (ParameterizedType) TypeToken.of(this.getClass()).getSupertype(EntityFunctionSpec.class).getType(); 23 | try { 24 | return (Class) Class.forName(type.getActualTypeArguments()[1].getTypeName()); 25 | } catch (ClassNotFoundException e) { 26 | throw new RuntimeException(e); 27 | } 28 | } 29 | 30 | public Class getEntityType() { 31 | ParameterizedType type = (ParameterizedType) TypeToken.of(this.getClass()).getSupertype(EntityFunctionSpec.class).getType(); 32 | try { 33 | return (Class) Class.forName(type.getActualTypeArguments()[0].getTypeName()); 34 | } catch (ClassNotFoundException e) { 35 | throw new RuntimeException(e); 36 | } 37 | 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /spec/schema/command.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/command.response.json", 4 | "title": "EventApis Command Response", 5 | "description": "EventApis Command Response Schema", 6 | "type": "object", 7 | "properties": { 8 | "headers": { 9 | "type": "object", 10 | "properties": { 11 | "X-OPID": { 12 | "type": "string", 13 | "format": "uuid", 14 | "description": "Command starts operation with this ID" 15 | }, 16 | "X-OP-TIMEOUT": { 17 | "type": "integer", 18 | "minimum": 0, 19 | "description": "Timeout in Milliseconds, Requester can assume Operation will be finished(success or fail), meaning underlying System will guarantee that it should reach consistent state after that timeout" 20 | }, 21 | "X-OP-START-TIME": { 22 | "type": "integer", 23 | "minimum": 0, 24 | "description": "Reference starting time of Operation, especially to use X-OP-TIMEOUT" 25 | } 26 | }, 27 | "required": [ 28 | "X-OPID", 29 | "X-OP-TIMEOUT", 30 | "X-OP-START-TIME" 31 | ] 32 | }, 33 | "body": { 34 | "allOf": [ 35 | { 36 | "$ref": "https://github.com/kloiasoft/eventapis/blob/master/spec/schema/event.key.json" 37 | } 38 | ], 39 | "additionalProperties": true 40 | } 41 | }, 42 | "required": [ 43 | "body" 44 | ] 45 | } -------------------------------------------------------------------------------- /emon-vis/README.md: -------------------------------------------------------------------------------- 1 | # emon-vis 2 | 3 | This README outlines the details of collaborating on this Ember application. 4 | A short introduction of this app could easily go here. 5 | 6 | ## Prerequisites 7 | 8 | You will need the following things properly installed on your computer. 9 | 10 | * [Git](https://git-scm.com/) 11 | * [Node.js](https://nodejs.org/) (with npm) 12 | * [Ember CLI](https://ember-cli.com/) 13 | * [Google Chrome](https://google.com/chrome/) 14 | 15 | ## Installation 16 | 17 | * `git clone ` this repository 18 | * `cd emon-vis` 19 | * `npm install` 20 | 21 | ## Running / Development 22 | 23 | * `ember serve` 24 | * Visit your app at [http://localhost:4200](http://localhost:4200). 25 | * Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). 26 | 27 | ### Code Generators 28 | 29 | Make use of the many generators for code, try `ember help generate` for more details 30 | 31 | ### Running Tests 32 | 33 | * `ember test` 34 | * `ember test --server` 35 | 36 | ### Building 37 | 38 | * `ember build` (development) 39 | * `ember build --environment production` (production) 40 | 41 | ### Deploying 42 | 43 | Specify what it takes to deploy your app. 44 | 45 | ## Further Reading / Useful Links 46 | 47 | * [ember.js](https://emberjs.com/) 48 | * [ember-cli](https://ember-cli.com/) 49 | * Development Browser Extensions 50 | * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) 51 | * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) 52 | -------------------------------------------------------------------------------- /emon-vis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emon-vis", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "Small description for emon-vis goes here", 6 | "license": "MIT", 7 | "author": "", 8 | "directories": { 9 | "doc": "doc", 10 | "test": "tests" 11 | }, 12 | "repository": "", 13 | "scripts": { 14 | "build": "ember build", 15 | "start": "ember serve", 16 | "test": "ember test" 17 | }, 18 | "devDependencies": { 19 | "bootstrap": "^4.0.0-beta.2", 20 | "broccoli-asset-rev": "^2.4.5", 21 | "ember-ajax": "^3.0.0", 22 | "ember-bootstrap": "^1.0.0-rc.5", 23 | "ember-cli": "~2.17.0", 24 | "ember-cli-app-version": "^3.0.0", 25 | "ember-cli-babel": "^6.6.0", 26 | "ember-cli-dependency-checker": "^2.0.0", 27 | "ember-cli-eslint": "^4.2.1", 28 | "ember-cli-htmlbars": "^2.0.1", 29 | "ember-cli-htmlbars-inline-precompile": "^1.0.0", 30 | "ember-cli-inject-live-reload": "^1.4.1", 31 | "ember-cli-qunit": "^4.1.1", 32 | "ember-cli-sass": "^7.1.2", 33 | "ember-cli-shims": "^1.2.0", 34 | "ember-cli-sri": "^2.1.0", 35 | "ember-cli-uglify": "^2.0.0", 36 | "ember-data": "~2.17.0", 37 | "ember-export-application-global": "^2.0.0", 38 | "ember-load-initializers": "^1.0.0", 39 | "ember-resolver": "^4.0.0", 40 | "ember-source": "~2.17.0", 41 | "ember-welcome-page": "^3.0.0", 42 | "glob": "^4.5.3", 43 | "http-proxy": "^1.16.2", 44 | "loader.js": "^4.2.3", 45 | "morgan": "^1.9.0" 46 | }, 47 | "engines": { 48 | "node": "^4.5 || 6.* || >= 7.*" 49 | }, 50 | "dependencies": { 51 | "vis": "^4.20.1" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /travis/settings.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | bintray-kloia-eventapis 6 | ${env.MVN_USERNAME} 7 | ${env.MVN_PASSWORD} 8 | 9 | 10 | oss-snapshots 11 | ${env.MVN_SNAPSHOT_USERNAME} 12 | ${env.MVN_SNAPSHOT_PASSWORD} 13 | 14 | 15 | maven.oracle.com 16 | ${env.MVN_ORACLE_USERNAME} 17 | ${env.MVN_ORACLE_PASSWORD} 18 | 19 | 20 | ANY 21 | ANY 22 | OAM 11g 23 | 24 | 25 | 26 | 27 | 28 | http.protocol.allow-circular-redirects 29 | %b,true 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/common/EventRecorder.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.common; 2 | 3 | import com.kloia.eventapis.cassandra.ConcurrencyResolver; 4 | import com.kloia.eventapis.cassandra.ConcurrentEventResolver; 5 | import com.kloia.eventapis.cassandra.EntityEvent; 6 | import com.kloia.eventapis.exception.EventStoreException; 7 | import com.kloia.eventapis.pojos.EventState; 8 | 9 | import javax.annotation.Nullable; 10 | import java.util.List; 11 | import java.util.Optional; 12 | import java.util.function.Function; 13 | import java.util.function.Supplier; 14 | 15 | /** 16 | * Created by zeldalozdemir on 23/02/2017. 17 | */ 18 | public interface EventRecorder { 19 | 20 | EventKey recordEntityEvent( 21 | RecordedEvent event, long date, 22 | Optional previousEventKey, 23 | Function> concurrencyResolverFactory 24 | ) 25 | throws EventStoreException, T; 26 | 27 | EventKey recordEntityEvent( 28 | R event, long date, 29 | Optional previousEventKey, 30 | Supplier> concurrentEventResolverSupplier) 31 | throws EventStoreException, T; 32 | 33 | List markFail(String key); 34 | 35 | String updateEvent(EventKey eventKey, @Nullable RecordedEvent newEventData, @Nullable EventState newEventState, @Nullable String newEventType) throws EventStoreException; 36 | 37 | String updateEvent(EventKey eventKey, RecordedEvent newEventData) throws EventStoreException; 38 | } 39 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/api/ViewQuery.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api; 2 | 3 | 4 | import com.kloia.eventapis.cassandra.EntityEvent; 5 | import com.kloia.eventapis.common.EventKey; 6 | import com.kloia.eventapis.common.PublishedEvent; 7 | import com.kloia.eventapis.exception.EventStoreException; 8 | import com.kloia.eventapis.view.Entity; 9 | 10 | import javax.annotation.Nullable; 11 | import java.util.List; 12 | import java.util.function.Function; 13 | 14 | /** 15 | * Created by zeldalozdemir on 23/02/2017. 16 | */ 17 | public interface ViewQuery { 18 | E queryEntity(String entityId) throws EventStoreException; 19 | 20 | E queryEntity(String entityId, int version) throws EventStoreException; 21 | 22 | E queryEntity(EventKey eventKey) throws EventStoreException; 23 | 24 | E queryEntity(String entityId, @Nullable Integer version, E previousEntity) throws EventStoreException; 25 | 26 | List queryByOpId(String opId) throws EventStoreException; 27 | 28 | List queryByOpId(String key, Function findOne) throws EventStoreException; 29 | 30 | List queryHistory(String entityId) throws EventStoreException; 31 | 32 | EntityEvent queryEvent(String entityId, int version) throws EventStoreException; 33 | 34 | T queryEventData(String entityId, int version) throws EventStoreException; 35 | 36 | List queryEventKeysByOpId(String opId); 37 | 38 | /* List queryByField(List clauses) throws EventStoreException; 39 | 40 | List multipleQueryByField(List> clauses) throws EventStoreException;*/ 41 | 42 | } 43 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/kafka/PublishedEventWrapper.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.kafka; 2 | 3 | import com.fasterxml.jackson.annotation.JsonGetter; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonRawValue; 6 | import com.fasterxml.jackson.annotation.JsonSetter; 7 | import com.fasterxml.jackson.databind.node.ObjectNode; 8 | import com.kloia.eventapis.common.Context; 9 | import lombok.Data; 10 | import lombok.ToString; 11 | 12 | import java.io.Serializable; 13 | import java.util.Map; 14 | 15 | /** 16 | * Created by zeldalozdemir on 25/04/2017. 17 | */ 18 | @Data 19 | @ToString(exclude = "userContext") 20 | public class PublishedEventWrapper implements Serializable { 21 | 22 | private static final long serialVersionUID = 7950670808405003425L; 23 | 24 | @JsonIgnore 25 | private String event; 26 | private Context context; 27 | private String sender; 28 | private long opDate; 29 | private Map userContext; 30 | 31 | public PublishedEventWrapper() { 32 | } 33 | 34 | public PublishedEventWrapper(Context context, String eventData, long opDate) { 35 | this.context = context; 36 | this.event = eventData; 37 | this.opDate = opDate; 38 | } 39 | 40 | @JsonGetter 41 | @JsonRawValue 42 | public String getEvent() { 43 | return event; 44 | } 45 | 46 | @JsonSetter 47 | public void setEvent(ObjectNode event) { 48 | this.event = event.toString(); 49 | } 50 | 51 | @JsonSetter 52 | public void setEventData(String eventData) { 53 | this.event = eventData; 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/domain/ServiceData.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.function.Function; 13 | import java.util.stream.Collectors; 14 | 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @JsonInclude(JsonInclude.Include.NON_NULL) 19 | public class ServiceData implements Serializable { 20 | private static final long serialVersionUID = 2401532791975588L; 21 | 22 | private String serviceName; 23 | private Map partitions = new HashMap<>(); 24 | 25 | public ServiceData(String serviceName, List partitionList) { 26 | this.serviceName = serviceName; 27 | this.setPartitions(partitionList); 28 | } 29 | 30 | 31 | public static ServiceData createServiceData(String consumer, List value) { 32 | return new ServiceData(consumer, value.stream().collect(Collectors.toMap(Partition::getNumber, Function.identity()))); 33 | } 34 | 35 | public Partition getPartition(int number) { 36 | if (partitions != null) 37 | return partitions.get(number); 38 | else 39 | return null; 40 | } 41 | 42 | public Partition setPartition(Partition partition) { 43 | return partitions.put(partition.getNumber(), partition); 44 | } 45 | 46 | public void setPartitions(List partitionList) { 47 | partitions = partitionList.stream().collect(Collectors.toMap(Partition::getNumber, Function.identity())); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /java-api/src/test/java/com/kloia/eventapis/api/impl/EmptyUserContextTest.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.impl; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.mockito.InjectMocks; 6 | import org.mockito.Mockito; 7 | import org.mockito.runners.MockitoJUnitRunner; 8 | 9 | import java.util.Map; 10 | 11 | import static org.hamcrest.Matchers.nullValue; 12 | import static org.junit.Assert.assertThat; 13 | import static org.mockito.Mockito.verifyZeroInteractions; 14 | 15 | @RunWith(MockitoJUnitRunner.class) 16 | public class EmptyUserContextTest { 17 | 18 | @InjectMocks 19 | private EmptyUserContext emptyUserContext; 20 | 21 | @Test 22 | public void shouldGetUserContext() throws Exception { 23 | // Given 24 | 25 | // When 26 | Map actual = emptyUserContext.getUserContext(); 27 | 28 | // Then 29 | assertThat(actual, nullValue()); 30 | } 31 | 32 | @Test 33 | public void shouldExtractUserContext() throws Exception { 34 | // Given 35 | Map userContext = (Map) Mockito.mock(Map.class); 36 | 37 | // When 38 | emptyUserContext.extractUserContext(userContext); 39 | 40 | // Then 41 | verifyZeroInteractions(userContext); 42 | } 43 | 44 | @Test 45 | public void shouldClearUserContext() throws Exception { 46 | // Given 47 | 48 | // When 49 | emptyUserContext.clearUserContext(); 50 | 51 | // Then 52 | 53 | } 54 | 55 | @Test 56 | public void shouldGetAuditInfo() throws Exception { 57 | // Given 58 | 59 | // When 60 | String actual = emptyUserContext.getAuditInfo(); 61 | 62 | // Then 63 | assertThat(actual, nullValue()); 64 | } 65 | } -------------------------------------------------------------------------------- /emon/src/main/java/com/kloia/eventapis/api/emon/service/OperationsBroadcaster.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.service; 2 | 3 | import com.hazelcast.core.IMap; 4 | import com.hazelcast.core.ITopic; 5 | import com.hazelcast.core.Message; 6 | import com.hazelcast.core.MessageListener; 7 | import com.kloia.eventapis.api.emon.domain.Topology; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 12 | 13 | import javax.annotation.PostConstruct; 14 | import java.io.IOException; 15 | import java.util.ArrayList; 16 | import java.util.Collections; 17 | import java.util.List; 18 | 19 | @Service 20 | @Slf4j 21 | public class OperationsBroadcaster implements MessageListener { 22 | 23 | @Autowired 24 | private ITopic operationsTopic; 25 | 26 | private final List emitters = Collections.synchronizedList(new ArrayList<>()); 27 | 28 | @PostConstruct 29 | private void postConstruct() { 30 | operationsTopic.addMessageListener(this); 31 | } 32 | 33 | 34 | public void registerEmitter(SseEmitter sseEmitter) { 35 | emitters.add(sseEmitter); 36 | } 37 | 38 | public void deregisterEmitter(SseEmitter sseEmitter) { 39 | emitters.remove(sseEmitter); 40 | } 41 | 42 | @Override 43 | public void onMessage(Message message) { 44 | emitters.removeIf(sseEmitter -> { 45 | try { 46 | sseEmitter.send(message.getMessageObject()); 47 | return false; 48 | } catch (Exception e) { 49 | log.error(e.getMessage(), e); 50 | return true; 51 | } 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/kafka/KafkaOperationRepositoryFactory.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.kafka; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.kloia.eventapis.api.IUserContext; 5 | import com.kloia.eventapis.common.OperationContext; 6 | import com.kloia.eventapis.pojos.Operation; 7 | import org.apache.kafka.clients.producer.KafkaProducer; 8 | import org.apache.kafka.common.serialization.StringSerializer; 9 | 10 | public class KafkaOperationRepositoryFactory { 11 | private KafkaProperties kafkaProperties; 12 | private IUserContext userContext; 13 | private OperationContext operationContext; 14 | 15 | public KafkaOperationRepositoryFactory(KafkaProperties kafkaProperties, IUserContext userContext, OperationContext operationContext) { 16 | this.kafkaProperties = kafkaProperties; 17 | this.userContext = userContext; 18 | this.operationContext = operationContext; 19 | } 20 | 21 | public KafkaOperationRepository createKafkaOperationRepository(ObjectMapper objectMapper) { 22 | KafkaProducer operationsKafka = new KafkaProducer<>( 23 | kafkaProperties.buildProducerProperties(), 24 | new StringSerializer(), 25 | new JsonSerializer<>(objectMapper) 26 | ); 27 | KafkaProducer eventsKafka = new KafkaProducer<>( 28 | kafkaProperties.buildProducerProperties(), 29 | new StringSerializer(), 30 | new JsonSerializer<>(objectMapper) 31 | ); 32 | return new KafkaOperationRepository( 33 | operationContext, 34 | userContext, 35 | operationsKafka, 36 | eventsKafka, 37 | kafkaProperties.getConsumer().getGroupId() 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /kafka-tester/src/main/java/Eventapis.java: -------------------------------------------------------------------------------- 1 | import lombok.extern.slf4j.Slf4j; 2 | import org.apache.kafka.clients.admin.AdminClient; 3 | import org.apache.kafka.clients.admin.TopicListing; 4 | import org.apache.kafka.clients.producer.ProducerConfig; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.concurrent.ExecutionException; 13 | 14 | /** 15 | * Created by mali on 20/01/2017. 16 | */ 17 | @Slf4j 18 | @SpringBootApplication 19 | 20 | public class Eventapis { 21 | 22 | 23 | public static void mai2n(String[] args) { 24 | ConfigurableApplicationContext context = SpringApplication.run(Eventapis.class, args); 25 | } 26 | 27 | public static void main(String[] args) throws ExecutionException, InterruptedException { 28 | Map props = new HashMap<>(); 29 | // list of host:port pairs used for establishing the initial connections 30 | // to the Kakfa cluster 31 | props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, 32 | "kafka-local:9092"); 33 | // props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, 34 | // JsonSerializer.class); 35 | // props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, 36 | // JsonSerializer.class); 37 | // value to block, after which it will throw a TimeoutException 38 | props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 50000); 39 | AdminClient adminClient = AdminClient.create(props); 40 | adminClient.describeCluster(); 41 | Collection topicListings = adminClient.listTopics().listings().get(); 42 | System.out.println(topicListings); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /emon/src/main/java/com/kloia/eventapis/api/emon/dto/TopicResponseDto.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.kloia.eventapis.api.emon.domain.Partition; 6 | import com.kloia.eventapis.api.emon.domain.ServiceData; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.stream.Collectors; 14 | 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class TopicResponseDto { 19 | 20 | @JsonIgnore 21 | private Map serviceDataHashMap = new HashMap<>(); 22 | 23 | @JsonIgnore 24 | private Map partitionsMap = new HashMap<>(); 25 | 26 | public Map> getServiceData() { 27 | return getServiceDataHashMap().entrySet().stream().collect( 28 | Collectors.toMap(Map.Entry::getKey, 29 | o -> o.getValue().getPartitions().entrySet().stream().collect( 30 | Collectors.toMap(Map.Entry::getKey, p -> { 31 | if (p.getValue().getLag() != null && p.getValue().getLag() > 0L) { 32 | return p.getValue().getOffset() + "(lag=" + p.getValue().getLag() + ")"; 33 | } else { 34 | return p.getValue().getOffset().toString(); 35 | } 36 | })) 37 | ) 38 | ); 39 | 40 | } 41 | 42 | @JsonProperty("partitions") 43 | public Map getPartitions() { 44 | return partitionsMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, o -> o.getValue().getOffset())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /emon-lib/src/main/java/com/kloia/eventapis/api/emon/service/EventMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.api.emon.service; 2 | 3 | import com.kloia.eventapis.kafka.PublishedEventWrapper; 4 | import com.kloia.eventapis.pojos.Operation; 5 | import org.apache.kafka.clients.consumer.ConsumerRebalanceListener; 6 | import org.apache.kafka.clients.consumer.ConsumerRecord; 7 | import org.apache.kafka.common.TopicPartition; 8 | import org.springframework.kafka.listener.ConsumerSeekAware; 9 | import org.springframework.kafka.listener.MessageListener; 10 | 11 | import java.io.Serializable; 12 | import java.util.Collection; 13 | import java.util.Map; 14 | 15 | public interface EventMessageListener extends MessageListener, ConsumerRebalanceListener, ConsumerSeekAware { 16 | @Override 17 | default void onMessage(ConsumerRecord data) { 18 | if (data.value() instanceof PublishedEventWrapper) 19 | onEventMessage(data, (PublishedEventWrapper) data.value()); 20 | else if (data.value() instanceof Operation) 21 | onOperationMessage(data, (Operation) data.value()); 22 | } 23 | 24 | void onOperationMessage(ConsumerRecord record, Operation operation); 25 | 26 | void onEventMessage(ConsumerRecord record, PublishedEventWrapper eventWrapper); 27 | 28 | @Override 29 | default void onPartitionsRevoked(Collection partitions) { 30 | } 31 | 32 | @Override 33 | default void onPartitionsAssigned(Collection partitions) { 34 | } 35 | 36 | @Override 37 | default void registerSeekCallback(ConsumerSeekCallback callback) { 38 | } 39 | 40 | @Override 41 | default void onPartitionsAssigned(Map assignments, ConsumerSeekCallback callback) { 42 | } 43 | 44 | @Override 45 | default void onIdleContainer(Map assignments, ConsumerSeekCallback callback) { 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spring-integration/src/main/java/com/kloia/eventapis/spring/configuration/DataMigrationService.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.spring.configuration; 2 | 3 | 4 | import com.kloia.eventapis.api.ViewQuery; 5 | import com.kloia.eventapis.common.EventKey; 6 | import com.kloia.eventapis.common.EventRecorder; 7 | import com.kloia.eventapis.common.RecordedEvent; 8 | import com.kloia.eventapis.exception.EventStoreException; 9 | import com.kloia.eventapis.pojos.EventState; 10 | import com.kloia.eventapis.view.Entity; 11 | import com.kloia.eventapis.view.SnapshotRepository; 12 | 13 | import javax.annotation.Nullable; 14 | 15 | public class DataMigrationService { 16 | 17 | private EventRecorder eventRecorder; 18 | private ViewQuery viewQuery; 19 | private SnapshotRepository snapshotRepository; 20 | 21 | public DataMigrationService(EventRecorder eventRecorder, ViewQuery viewQuery, SnapshotRepository snapshotRepository) { 22 | this.eventRecorder = eventRecorder; 23 | this.viewQuery = viewQuery; 24 | this.snapshotRepository = snapshotRepository; 25 | } 26 | 27 | public T updateEvent(EventKey eventKey, boolean snapshot, @Nullable RecordedEvent newEventData, @Nullable EventState newEventState, @Nullable String newEventType) throws EventStoreException { 28 | eventRecorder.updateEvent(eventKey, newEventData, newEventState, newEventType); 29 | T entity = viewQuery.queryEntity(eventKey.getEntityId()); 30 | if (snapshot) 31 | entity = snapshotRepository.save(entity); 32 | return entity; 33 | } 34 | 35 | public T updateEvent(EventKey eventKey, boolean snapshot, RecordedEvent newEventData) throws EventStoreException { 36 | return this.updateEvent(eventKey, snapshot, newEventData, null, null); 37 | } 38 | 39 | public T snapshotOnly(String entityId) throws EventStoreException { 40 | T entity = viewQuery.queryEntity(entityId); 41 | return snapshotRepository.save(entity); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /emon-lib/src/test/java/com/kloia/eventapis/pojos/OperationTest.java: -------------------------------------------------------------------------------- 1 | package com.kloia.eventapis.pojos; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import com.hazelcast.core.IMap; 6 | import com.hazelcast.map.EntryBackupProcessor; 7 | import com.hazelcast.map.EntryProcessor; 8 | import org.junit.Test; 9 | 10 | import java.util.Map; 11 | import java.util.regex.Pattern; 12 | 13 | /** 14 | * Created by zeldalozdemir on 26/01/2017. 15 | */ 16 | public class OperationTest { 17 | @Test 18 | public void testReadWriteExternal() throws Exception { 19 | HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance(); 20 | IMap test = hazelcastInstance.getMap("test"); 21 | test.executeOnKey("123", new EntryProcessor() { 22 | @Override 23 | public Object process(Map.Entry entry) { 24 | entry.setValue("Blabla"); 25 | return entry; 26 | } 27 | 28 | @Override 29 | public EntryBackupProcessor getBackupProcessor() { 30 | return null; 31 | } 32 | }); 33 | 34 | System.out.println(test.get("123")); 35 | 36 | 37 | } 38 | 39 | @Test 40 | public void regexpTest() { 41 | Pattern compile = Pattern.compile("^(.+Event|operation-events)$"); 42 | assert compile.matcher("BalBlaEvent").matches(); 43 | assert !compile.matcher("BalBlaEvent2as").matches(); 44 | assert !compile.matcher("Event").matches(); 45 | assert compile.matcher("operation-events").matches(); 46 | assert !compile.matcher("operation").matches(); 47 | assert !compile.matcher("events").matches(); 48 | assert !compile.matcher("blablaevents").matches(); 49 | } 50 | 51 | @Test 52 | public void regexpTest2() { 53 | Pattern compile = Pattern.compile("^(.+command-query|.+-command)$"); 54 | assert compile.matcher("payment3d-process-command").matches(); 55 | 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /samples/2-basic/payment-service/src/main/java/com/kloia/sample/controller/PaymentRestController.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.controller; 2 | 3 | import com.kloia.eventapis.api.ViewQuery; 4 | import com.kloia.eventapis.exception.EventStoreException; 5 | import com.kloia.sample.model.Payment; 6 | import com.kloia.sample.repository.PaymentRepository; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.cloud.netflix.feign.EnableFeignClients; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import java.io.IOException; 18 | 19 | 20 | /** 21 | * Created by zeldalozdemir on 09/02/2017. 22 | */ 23 | @Slf4j 24 | @RestController 25 | @RequestMapping(value = "/payment/v1/") 26 | @EnableFeignClients 27 | public class PaymentRestController { 28 | 29 | @Autowired 30 | private ViewQuery paymentEventRepository; 31 | 32 | @Autowired 33 | private PaymentRepository paymentRepository; 34 | 35 | @RequestMapping(value = "/{paymentId}", method = RequestMethod.GET) 36 | public ResponseEntity getPayment(@PathVariable("paymentId") String paymentId) throws IOException, EventStoreException { 37 | return new ResponseEntity(paymentRepository.findOne(paymentId), HttpStatus.CREATED); 38 | } 39 | 40 | @RequestMapping(value = "/{paymentId}/{version}", method = RequestMethod.GET) 41 | public ResponseEntity getPaymentWithVersion(@PathVariable("paymentId") String paymentId, @PathVariable("version") Integer version) throws IOException, EventStoreException { 42 | return new ResponseEntity(paymentEventRepository.queryEntity(paymentId, version), HttpStatus.CREATED); 43 | } 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /samples/2-basic/order-service/src/main/java/com/kloia/sample/controller/OrderRestController.java: -------------------------------------------------------------------------------- 1 | package com.kloia.sample.controller; 2 | 3 | import com.kloia.eventapis.api.ViewQuery; 4 | import com.kloia.eventapis.exception.EventStoreException; 5 | import com.kloia.sample.model.Orders; 6 | import com.kloia.sample.repository.OrderRepository; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.PathVariable; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import java.io.IOException; 17 | 18 | 19 | /** 20 | * Created by zeldalozdemir on 09/02/2017. 21 | */ 22 | @Slf4j 23 | @RestController 24 | @RequestMapping(value = "/order/v1/") 25 | public class OrderRestController { 26 | 27 | @Autowired 28 | private OrderRepository orderRepository; 29 | @Autowired 30 | private ViewQuery orderViewQuery; 31 | 32 | @RequestMapping(value = "/{orderId}", method = RequestMethod.GET) 33 | public ResponseEntity getOrder(@PathVariable("orderId") String orderId) throws IOException, EventStoreException { 34 | return new ResponseEntity(orderRepository.findOne(orderId), HttpStatus.OK); 35 | } 36 | 37 | @RequestMapping(method = RequestMethod.GET) 38 | public ResponseEntity getOrders() throws IOException, EventStoreException { 39 | return new ResponseEntity(orderRepository.findAll(), HttpStatus.OK); 40 | } 41 | 42 | @RequestMapping(value = "/{orderId}/{version}", method = RequestMethod.GET) 43 | public ResponseEntity getOrderWithVersion(@PathVariable("orderId") String orderId, @PathVariable("version") Integer version) throws IOException, EventStoreException { 44 | return new ResponseEntity(orderViewQuery.queryEntity(orderId, version), HttpStatus.OK); 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /java-api/src/main/java/com/kloia/eventapis/kafka/JsonSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.kloia.eventapis.kafka; 18 | 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | import org.apache.kafka.common.errors.SerializationException; 21 | import org.apache.kafka.common.serialization.Serializer; 22 | 23 | import javax.annotation.Nonnull; 24 | import java.io.IOException; 25 | import java.util.Map; 26 | 27 | /** 28 | * Generic {@link Serializer} for sending Java objects to Kafka as JSON. 29 | * 30 | * @param class of the entity, representing messages 31 | * @author Igor Stepanov 32 | * @author Artem Bilan 33 | */ 34 | public class JsonSerializer implements Serializer { 35 | 36 | protected final ObjectMapper objectMapper; 37 | 38 | 39 | public JsonSerializer(@Nonnull ObjectMapper objectMapper) { 40 | this.objectMapper = objectMapper; 41 | } 42 | 43 | public void configure(Map configs, boolean isKey) { 44 | // No-op 45 | } 46 | 47 | public byte[] serialize(String topic, T data) { 48 | try { 49 | byte[] result = null; 50 | if (data != null) { 51 | result = this.objectMapper.writeValueAsBytes(data); 52 | } 53 | return result; 54 | } catch (IOException exception) { 55 | throw new SerializationException("Can't serialize data [" + data + "] for topic [" + topic + "]", exception); 56 | } 57 | } 58 | 59 | public void close() { 60 | // No-op 61 | } 62 | 63 | } 64 | --------------------------------------------------------------------------------