GithubHelp home page GithubHelp logo

eventuate-examples / eventuate-examples-java-customers-and-orders Goto Github PK

View Code? Open in Web Editor NEW
388.0 38.0 205.0 409 KB

Java version of the Customers and Orders event sourcing example from my presentations

Java 94.25% Shell 4.48% Groovy 0.88% Dockerfile 0.40%

eventuate-examples-java-customers-and-orders's Introduction

This is the Java version of the customers and orders example that I've used in numerous presentations on developing microservices with event sourcing and CQRS. The code is built using the Eventuate platform. It illustrates how to implement an eventually consistent credit limit check using event sourcing. For more information, see this presentation from Gluecon 2016

About Eventuate™

The application is built using Eventuate, which is an application platform for writing transactional microservices. It provides a simple yet powerful event-driven programming model that is based on event sourcing and Command Query Responsibility Segregation (CQRS). Eventuate solves the distributed data management problems inherent in a microservice architecture. It consists of a scalable, distributed event store and client libraries for various languages and frameworks including Java, Scala, and the Spring framework.

Building and running the application.

This is a Java 8, Gradle project. However, you do not need to install Gradle since it will be downloaded automatically. You just need to have Java 8 installed.

Building and running using Eventuate Local

First, build the application:

./gradlew assemble

Next, you can launch the application using Docker Compose

Note:

If the containers aren't accessible via localhost - e.g. you are using Docker Toolbox, you will have to use ${DOCKER_HOST_IP} instead of localhost. See this http://eventuate.io/docs/usingdocker.html[guide to setting DOCKER_HOST_IP] for more information.

./gradlew <database-mode>ComposeBuild
./gradlew <database-mode>ComposeUp

Where database-mode is one of:

  • mysqlbinlog - use MySQL with Binlog-based event publishing
  • postgreswal - use Postgres with Postgres WAL-based event publishing
  • postgrespolling - use Postgres with generic JDBC polling-based event publishing

Finally, you can use the Swagger UI provided by the services to create customers and orders, and view the order history:

  • http://localhost:8081/swagger-ui.html - Create a customer
  • http://localhost:8083/swagger-ui.html - Create an order
  • http://localhost:8082/swagger-ui.html - View the customer and the order

(Hint: best to open these URLs in separate tabs)

The script ./show-urls.sh will display the URLs.

eventuate-examples-java-customers-and-orders's People

Contributors

cer avatar dartartem avatar dartpopikyardo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eventuate-examples-java-customers-and-orders's Issues

Add code doc

In the customer event handler, it checks if there is enough credit and then makes the reservation, without further synchronisation or locking.

I assume this works because with Kafka, the consumer of the events for a certain customer would always apply them in order and not in concurrency.

Would that be worth a java doc in the customer event consumer's reserve credit method?

Simplify the project

Principles to follow:

  • A module per service, e.g. customer-service - instead of 3+/service
    
  • Discarded support for monolith - not important - that enables the module structure to be simpler
    
  • Simpler, more sensible naming conventions - no command-side, query-side, ..., instead - e.g. customer-service
    
  • Each service has an application.properties that defines some sensible defaults - simplifies the amount of configuration needed in docker-compose.yml 
    

Build fail

When I run build-and-test-all.sh, the script fails with:

Could not resolve all dependencies for configuration ':customers-service:testCompileClasspath'.
> Could not find net.chrisrichardson.eventstore.examples.customersandorders:common-contracts:1.0-SNAPSHOT.
  Required by:
      project :customers-service

orders-service is giving tcp socket rejection during gradle build

gradle build of orders-service is giving the tcp socket rejection error.

Error

Creating ordersservice_customercommandside_1 ... done
Will use 172.17.0.1 (network bridge) as host of customercommandside
Probing TCP socket on 172.17.0.1:8081 of service 'customercommandside_1'
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))
Waiting for TCP socket on 172.17.0.1:8081 of service 'customercommandside_1' (Connection refused (Connection refused))

Upgrading Eventuate Local to BUILD-SNAPSHOT causes test failure

OrderServiceInProcessComponentTest failed with

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.datasource.driver-class-name' in value "${spring.datasource.driver-class-name}"
	at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
	at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
	at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236)

Bean initialization issue in customer service

After gradle build is successful. During the jar execution leads to bean initialization isuue.

Error

11:40:23.227 ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerWorkflow' defined in class path resource [net/chrisrichardson/eventstore/examples/customersandorders/customersservice/backend/CustomerBackendConfiguration.class]: Initialization of bean failed; nested exception is io.eventuate.EventuateSubscriptionFailedException: Subscription failed: customerWorkflow
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at net.chrisrichardson.eventstore.examples.customersandorders.customersservice.CustomersServiceMain.main(CustomersServiceMain.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: io.eventuate.EventuateSubscriptionFailedException: Subscription failed: customerWorkflow
at io.eventuate.javaclient.spring.EventDispatcherInitializer.registerEventHandler(EventDispatcherInitializer.java:109)
at io.eventuate.javaclient.spring.EventHandlerBeanPostProcessor.postProcessBeforeInitialization(EventHandlerBeanPostProcessor.java:25)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
... 23 common frames omitted
Caused by: java.util.concurrent.TimeoutException: null
at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1771)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at io.eventuate.javaclient.spring.EventDispatcherInitializer.registerEventHandler(EventDispatcherInitializer.java:106)
... 27 common frames omitted

gradle Build failing

C:\temp\eventuate>gradle build
Starting a Gradle Daemon, 2 stopped Daemons could not be reused, use --status for details

Configure project :customers-service
The plugin id 'spring-boot' is deprecated. Please use 'org.springframework.boot' instead.

Configure project :orders-history-view-service
The plugin id 'spring-boot' is deprecated. Please use 'org.springframework.boot' instead.

Configure project :orders-service
The plugin id 'spring-boot' is deprecated. Please use 'org.springframework.boot' instead.

FAILURE: Build failed with an exception.

  • What went wrong:
    Could not resolve all files for configuration ':customers-service:testCompileClasspath'.

Could not find net.chrisrichardson.eventstore.examples.customersandorders:common-contracts:1.0-SNAPSHOT.
Required by:
project :customers-service

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 34s
23 actionable tasks: 23 executed

orderhistoryqueryside consistently times out on Kafka

I'm trying to run this sample on Windows. Everything starts up nicely except for the order history query side service. There I get this exception:

14:06:27.635  WARN  o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderHistoryViewWorkflow' defined in class path resource [net/chrisrichardson/eventstore/examples/customersandorders/ordershistoryviewservice/backend/OrderHistoryViewBackendConfiguration.class]: Initialization of bean failed; nested exception is java.lang.RuntimeException: java.lang.RuntimeException: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata
14:06:29.715  INFO  o.s.b.a.l.AutoConfigurationReportLoggingInitializer -

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
14:06:29.720  ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderHistoryViewWorkflow' defined in class path resource [net/chrisrichardson/eventstore/examples/customersandorders/ordershistoryviewservice/backend/OrderHistoryViewBackendConfiguration.class]: Initialization of bean failed; nested exception is java.lang.RuntimeException: java.lang.RuntimeException: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
        at net.chrisrichardson.eventstore.examples.customersandorders.ordershistoryviewservice.OrderHistoryQuerySideService.main(OrderHistoryQuerySideService.java:19)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata
        at io.eventuate.local.java.kafka.consumer.EventuateKafkaConsumer.start(EventuateKafkaConsumer.java:115)
        at io.eventuate.local.java.jdbckafkastore.EventuateKafkaAggregateSubscriptions.subscribe(EventuateKafkaAggregateSubscriptions.java:85)
        at io.eventuate.javaclient.commonimpl.EventuateAggregateStoreImpl.subscribe(EventuateAggregateStoreImpl.java:158)
        at io.eventuate.javaclient.spring.EventDispatcherInitializer.registerEventHandler(EventDispatcherInitializer.java:105)
        at io.eventuate.javaclient.spring.EventHandlerBeanPostProcessor.postProcessBeforeInitialization(EventHandlerBeanPostProcessor.java:25)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
        ... 23 common frames omitted
Caused by: java.lang.RuntimeException: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata
        at io.eventuate.local.java.kafka.consumer.EventuateKafkaConsumer.verifyTopicExistsBeforeSubscribing(EventuateKafkaConsumer.java:48)
        at io.eventuate.local.java.kafka.consumer.EventuateKafkaConsumer.start(EventuateKafkaConsumer.java:70)
        ... 30 common frames omitted
Caused by: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata

Any idea what I can do to resolve this? The DOCKER_HOST_IP is set correctly.

eventuate.apiKeySecret null

I have an error in the ordercommandside container:

14:26:08.601  ERROR o.s.b.b.PropertiesConfigurationFactory - Properties configuration failed validation
14:26:08.609  ERROR o.s.b.b.PropertiesConfigurationFactory - Field error in object 'eventuate' on field 'apiKeySecret': rejected value [null]; codes [NotBlank.eventuate.apiKeySecret,NotBlank.apiKeySecret,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [eventuate.apiKeySecret,apiKeySecret]; arguments []; default message [apiKeySecret]]; default message [may not be empty]
14:26:08.609  ERROR o.s.b.b.PropertiesConfigurationFactory - Field error in object 'eventuate' on field 'apiKeyId': rejected value [null]; codes [NotBlank.eventuate.apiKeyId,NotBlank.apiKeyId,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [eventuate.apiKeyId,apiKeyId]; arguments []; default message [apiKeyId]]; default message [may not be empty]
14:26:08.660  ERROR o.s.b.f.s.DefaultListableBeanFactory - Destroy method on bean with name 'org.springframework.context.annotation.internalScheduledAnnotationProcessor' threw an exception
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a4f0f29: startup date [Fri Jul 28 14:26:00 UTC 2017]; root of context hierarchy

It seems that the apiKeyId and apiKeySecret are not set and the container crashes.

Deployment Issue

I am adding/creating new API for fetching information of all customers and for that I have added new method getAllCustomers() in CustomerOrderHistoryController Class. Build is successful but after deployment the new API is giving 404. Is there any configuration I am missing out on?

command used to build -./gradlew assemble -P eventuateDriver=local
Command used for docker - docker-compose -f docker-compose-eventuate-local-mysql.yml up

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.