Giter Club home page Giter Club logo

giftcard-demo's Introduction

Getting started with Axon

This Axon Framework demo application focuses around a simple giftcard domain, designed to show various aspects of the framework. The app can be run in various modes, using Spring-boot Profiles: by selecting a specific profile, only the corresponding parts of the app will be active. Select none, and the default behaviour is activated, which activates everything. This way you can experiment with Axon in a (structured) monolith as well as in micro-services.

Where to find more information:

  • The Axon Reference Guide is definitive guide on the Axon Framework and Axon Server.
  • Visit www.axoniq.io to find out about AxonIQ, the team behind the Axon Framework and Server.
  • Subscribe to the AxonIQ YouTube channel to get the latest Webinars, announcements, and customer stories.
  • To start a fresh Axon Application, you can go to start.axoniq.io.
  • Additional information may be gained by following some of AxonIQ's courses on the AxonIQ Academy.
  • The latest version of the Giftcard App can be found on GitHub.
  • Docker images for Axon Server are pushed to Docker Hub.
  • If there are any Axon related questions remaining, you can always go to the forum.

The Giftcard app

Background story

See the wikipedia article for a basic definition of gift cards. Essentially, there are just two events in the life cycle of a gift card:

  • They get issued: a new gift card gets created with some amount of money stored.
  • They get redeemed: all or part of the monetary value stored on the gift card is used to purchase something.

Structure of the App

The Giftcard application is split into four parts, using four sub-packages of io.axoniq.demo.giftcard:

  • The api package contains the (Java Records) sourcecode of the messages and entity. They form the API (sic) of the application.
  • The command package contains the GiftCard Aggregate class, with all command- and associated eventsourcing handlers.
  • The query package provides the query handlers, with their associated event handlers.
  • The rest package contains the Spring Webflux-based Web API.

Of these packages, command, query, and gui (enabling the rest package) are also configured as profiles.

Building the Giftcard app from the sources

To build the demo app, simply run the provided Maven wrapper:

./mvnw clean package

Note that the Giftcard app expects JDK 17 to be used.

Running the Giftcard app

The simplest way to run the app is by using the Spring-boot maven plugin:

./mvnw spring-boot:run

However, if you have copied the jar file giftcard-demo-4.8.jar from the Maven target directory to some other location, you can also start it with:

java -jar giftcard-demo-4.8.jar

The Web GUI can be found at http://localhost:8080.

If you want to activate only the command profile, use:

java -Dspring.profiles.active=command -jar giftcard-demo-4.8.jar

Idem for query and gui.

Running the Giftcard app as microservices

To run the Giftcard app as if it were three separate microservices, use the Spring-boot spring.profiles.active option as follows:

$ java -Dspring.profiles.active=command -jar giftcard-demo-4.8.jar

This will start only the command part. To complete the app, open two other command shells, and start one with profile query, and the last one with gui. Again you can open the Web GUI at http://localhost:8080. The three parts of the application work together through the running instance of the Axon Server, which distributes the Commands, Queries, and Events. It's also possible to explore the REST API using Swagger or get the Open Api definition to create a client.

Running Axon Server

By default, the Axon Framework is configured to expect a running Axon Server instance, and it will complain if the server is not found. To run Axon Server, you'll need a Java runtime.
A copy of the server JAR file has been provided in the demo package. You can run it locally, in a Docker container (including Kubernetes or even Mini-kube), or on a separate server.

The section below give a fair description on how to run Axon Server for this sample project. If you are looking for more in depth information on the subject, we recommend this three-part blog series:

  1. Running Axon Server - Going from local developer install to full-featured cluster in the cloud
  2. Running Axon Server in Docker - Continuing from local developer install to containerized
  3. Running Axon Server in a Virtual Machine

Running Axon Server locally

To run Axon Server locally, all you need to do is put the server JAR file in the directory where you want it to live, and start it using:

java -jar axonserver.jar

You will see that it creates a subdirectory data where it will store its information.

Running Axon Server in a Docker container

To run Axon Server in Docker you can use the image provided on Docker Hub:

$ docker run -d --name my-axon-server -p 8024:8024 -p 8124:8124 axoniq/axonserver
...some container id...
$

WARNING This is not a supported image for production purposes. Please use with caution.

If you want to run the clients in Docker containers as well, and are not using something like Kubernetes, use the "--hostname" option of the docker command to set a useful name like "axonserver", and pass the AXONSERVER_HOSTNAME environment variable to adjust the properties accordingly:

$ docker run -d --name my-axon-server -p 8024:8024 -p 8124:8124 --hostname axonserver -e AXONSERVER_HOSTNAME=axonserver axoniq/axonserver

When you start the client containers, you can now use "--link axonserver" to provide them with the correct DNS entry. The Axon Server Connector looks at the "axon.axonserver.servers" property to determine where Axon Server lives, so don't forget to set it to "axonserver".

Running Axon Server in Kubernetes and Mini-Kube

WARNING: Although you can get a pretty functional cluster running locally using Mini-Kube, you can run into trouble when you want to let it serve clients outside the cluster. Mini-Kube can provide access to HTTP servers running in the cluster, for other protocols you have to run a special protocol-agnostic proxy like you can with "kubectl port-forward <pod-name> <port-number>". Thus, for non-development scenarios, we don't recommend using Mini-Kube.

Deployment requires the use of a YAML descriptor, a working example of which can be found in the "kubernetes" directory. To run it, use the following commands in a separate window:

$ kubectl apply -f kubernetes/axonserver.yaml
statefulset.apps "axonserver" created
service "axonserver-gui" created
service "axonserver" created
$ kubectl port-forward axonserver-0 8124
Forwarding from 127.0.0.1:8124 -> 8124
Forwarding from [::1]:8124 -> 8124

You can now run the Giftcard app, which will connect through the proxied gRPC port. To see the Axon Server Web GUI, use "minikube service --url axonserver-gui" to obtain the URL for your browser. Actually, if you leave out the "--url", minikube will open the GUI in your default browser for you.

To clean up the deployment, use:

$ kubectl delete sts axonserver
statefulset.apps "axonserver" deleted
$ kubectl delete svc axonserver
service "axonserver" deleted
$ kubectl delete svc axonserver-gui
service "axonserver-gui" deleted

If you're using a 'real' Kubernetes cluster, you'll naturally not want to use "localhost" as hostname for Axon Server, so you need to add three lines to the container spec to specify the "AXONSERVER_HOSTNAME" setting:

...
      containers:
      - name: axonserver
        image: axoniq/axonserver
        imagePullPolicy: Always
        ports:
        - name: grpc
          containerPort: 8124
          protocol: TCP
        - name: gui
          containerPort: 8024
          protocol: TCP
        readinessProbe:
          httpGet:
            port: 8024
            path: /actuator/health
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 1
        env:
        - name: AXONSERVER_HOSTNAME
          value: axonserver
---
apiVersion: v1
kind: Service
...

Use "axonserver" (as that is the name of the Kubernetes service) if you're going to deploy the client next to the server in the cluster, which is what you'd probably want. Running the client outside the cluster, with Axon Server inside, entails extra work to enable and secure this, and is definitely beyond the scope of this example.

Configuring Axon Server

Axon Server uses sensible defaults for all of its settings, so it will actually run fine without any further configuration. However, if you want to make some changes, below are the most common options. For an exhaustive list, we recommend checking out the Configuration section of the Reference Guide.

Environment variables for customizing the Docker image of Axon Server

The axoniq/axonserver image can be customized at start by using one of the following environment variables. If no default is mentioned, leaving the environment variable unspecified will not add a line to the properties file.

  • AXONSERVER_NAME

    This is the name the Axon Server uses for itself.

  • AXONSERVER_HOSTNAME

    This is the hostname Axon Server communicates to the client as its contact point. Default is "localhost", because Docker generates a random name that is not resolvable outside the container.

  • AXONSERVER_DOMAIN

    This is the domain Axon Server can suffix the hostname with.

  • AXONSERVER_HTTP_PORT

    This is the port Axon Server uses for its Web GUI and REST API.

  • AXONSERVER_GRPC_PORT

    This is the gRPC port used by clients to exchange data with the server.

  • AXONSERVER_TOKEN

    Setting this will enable access control, which means the clients need to pass this token with each request.

  • AXONSERVER_EVENTSTORE

    This is the directory used for storing the Events.

  • AXONSERVER_CONTROLDB

    This is where Axon Server stores information of clients and what types of messages they are interested in.

Axon Server configuration

There are a number of things you can fine-tune in the server configuration. You can do this using an "axonserver.properties" file. All settings have sensible defaults.

  • axoniq.axonserver.name

    This is the name Axon Server uses for itself. The default is to use the hostname.

  • axoniq.axonserver.hostname

    This is the hostname clients will use to connect to the server. Note that an IP address can be used if the name cannot be resolved through DNS. The default value is the actual hostname reported by the OS.

  • server.port

    This is the port where Axon Server will listen for HTTP requests, by default 8024.

  • axoniq.axonserver.port

    This is the port where Axon Server will listen for gRPC requests, by default 8124.

  • axoniq.axonserver.event.storage

    This setting determines where event messages are stored, so make sure there is enough diskspace here. Losing this data means losing your Events-sourced Aggregates' state! Conversely, if you want a quick way to start from scratch, here's where to clean.

  • axoniq.axonserver.controldb-path

    This setting determines where the message hub stores its information. Losing this data will affect Axon Server's ability to determine which applications are connected, and what types of messages they are interested in.

  • axoniq.axonserver.accesscontrol.enabled

    Setting this to true will require clients to pass a token.

  • axoniq.axonserver.accesscontrol.token

    This is the token used for access control.

The Axon Server HTTP server

Axon Server provides two servers; one serving HTTP requests, the other gRPC. By default, these use ports 8024 and 8124 respectively, but you can change these in the settings.

The HTTP server has in its root context a management Web GUI, a health indicator is available at /actuator/health, and the REST API at /v1. The API's Swagger endpoint finally, is available at /swagger-ui.html, and gives the documentation on the REST API.

Data protection plugin

The data protection plugin can serve as an alternative to the Data Protection Module commonly used inside Axon application.

Data protection plugin config generation

The data protection maven plugin has been added to this project. It will automatically create a configuration output called axon-data-protection-config.json during the compile phase of the Maven Lifecycle. This output should be used for the configuration of the Data Protection Plugin on Axon Server.

Since at this moment the dataprotection-config-api and dataprotection-maven-plugin do not have any releases available on public repositories, these two projects will first need to be run locally to install these dependencies. Their repositories can be found here:

Two events have been included in the sample:

  • RedeemedEvent, an event used by the application
  • ExampleEvent, an unused event, but with a more complex data structure to show the config-api usage in more detail.

Using the data protection plugin in Axon Server

Running the docker-compose.yml file (rather than the kubernetes deployment) found in the docker directory will bring up an instance of axon server and and instance of vault to be able to run the example.

Use the axonserver-cli to upload and configure the data protection plugin (taken from https://docs.axoniq.io/reference-guide/axon-server/administration/plugins#plugin-administration)

Upload the data protection plugin

java -jar axonserver-cli.jar upload-plugin -t $(cat ./axonserver.token) -f axon-server-plugin-data-protection.jar -S https://localhost:8024 -i

Configure the plugin (https://docs.axoniq.io/reference-guide/axon-server/administration/plugins#configuring-a-plugin)

  • update the axon-data-protection-plugin-config.yaml file
    • set the vault configuration for your environment (if running the docker example, the vault token must match what is defined in the docker-compose file)
    • add the contents of the axon-data-protection-config.json file
  • run the following command to upload the configuration
java -jar ./axonserver-cli.jar configure-plugin -t $(cat ./axonserver.token) -p io.axoniq.axon-server-plugin-data-protection -v 1.0.0.SNAPSHOT -S https://localhost:8024 -i -c default -f axon-data-protection-config.yaml 

Activate the plugin for a context with the -c flag (https://docs.axoniq.io/reference-guide/axon-server/administration/plugins#activating-a-plugin)

java -jar ./axonserver-cli.jar activate-plugin -t $(cat ./axonserver.token) -p io.axoniq.axon-server-plugin-data-protection -v 1.0.0.SNAPSHOT -S https://localhost:8024 -i -c default

giftcard-demo's People

Contributors

abuijze avatar amarjanovic avatar azzazzel avatar benrunchey avatar bruceaxoniq avatar dependabot[bot] avatar gklijs avatar lfgcampos avatar smcvb avatar vermorkentech 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

giftcard-demo's Issues

Fatal error compiling: invalid flag: --release

My versions:

C:\work\axonquickstart-4.2\giftcard-demo>java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)

C:\work\axonquickstart-4.2\giftcard-demo>mvn --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T17:41:47+01:00)
Maven home: C:\work\soft\apache-maven-3.3.9\bin..
Java version: 1.8.0_112, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk1.8.0_112\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"

After playing with some OS tips I always ended with some kind of Fatal error compiling - either about incorrect source version, or class versions (apparently there is something compiled with Java 11?)

replay events and rebuild projection

Say our read model DB has crashed and data is lost in our projections, how can we tell axon, hey replay all the events so that our read model DB / projections are rebuilt from the beginning point of time?

websocket not working

In the log I see this:

2019-01-29 13:38:23.688  WARN 22729 --- [nio-8080-exec-3] c.v.spring.navigator.SpringViewProvider  : No SpringViews found
2019-01-29 13:38:27.824  WARN 22729 --- [nio-8080-exec-4] org.atmosphere.util.IOUtils              : More than one Servlet Mapping defined. WebSocket may not work org.apache.catalina.core.ApplicationServletRegistration@4d3fc8ed
2019-01-29 13:39:25.277 DEBUG 22729 --- [mmandReceiver-0] i.axoniq.demo.giftcard.command.GiftCard  : empty constructor invoked
2019-01-29 13:39:25.284 DEBUG 22729 --- [mmandReceiver-0] i.axoniq.demo.giftcard.command.GiftCard  : applying IssuedEvt(id=FC90B604-6C, amount=120)
2019-01-29 13:39:25.284 DEBUG 22729 --- [mmandReceiver-0] i.axoniq.demo.giftcard.command.GiftCard  : new remaining value: 120
2019-01-29 13:39:25.296 DEBUG 22729 --- [mmandReceiver-0] i.axoniq.demo.giftcard.command.GiftCard  : handling RedeemCmd(id=FC90B604-6C, amount=10)
2019-01-29 13:39:25.297 DEBUG 22729 --- [mmandReceiver-0] i.axoniq.demo.giftcard.command.GiftCard  : applying RedeemedEvt(id=FC90B604-6C, amount=10)
2019-01-29 13:39:25.297 DEBUG 22729 --- [mmandReceiver-0] i.axoniq.demo.giftcard.command.GiftCard  : new remaining value: 110
2019-01-29 13:39:28.291  INFO 22729 --- [nio-8080-exec-2] o.a.a.c.u.FlowControllingStreamObserver  : Observer stopped
2019-01-29 13:39:28.339  INFO 22729 --- [nio-8080-exec-5] o.a.a.c.u.FlowControllingStreamObserver  : Observer stopped
2019-01-29 13:40:01.192  WARN 22729 --- [Engine[Tomcat]]] io.axoniq.demo.giftcard.gui.GiftcardUI   : Closing UI
2019-01-29 13:40:06.213  WARN 22729 --- [nio-8080-exec-8] org.atmosphere.util.IOUtils              : More than one Servlet Mapping defined. WebSocket may not work org.apache.catalina.core.ApplicationServletRegistration@3c4ec762

The browser session closes after +/- 30 secs, and I get a black header in the UI stating that I need to take note of changes because session has been closed.
The app 'works' but when I redeem a giftcard, the list underneath is not updated -- no websocket push ??

Using OpenJDK 8 on Linux (Ubuntu). Using AxonServer as docker container.

meet exception "No qualifying bean of type 'com.thoughtworks.xstream.XStream' available" when start application

Basic information

  • JDK version: 11
  • Complete executable reproducer if available (e.g. GitHub Repo):

Steps to reproduce

  1. start the app in idea or execute java -jar

Expected behaviour

the application should started

Actual behaviour

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serializer' defined in class path resource [org/axonframework/springboot/autoconfig/AxonAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.axonframework.serialization.Serializer]: Factory method 'serializer' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.thoughtworks.xstream.XStream' available
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.23.jar:5.3.23]
... 78 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.axonframework.serialization.Serializer]: Factory method 'serializer' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.thoughtworks.xstream.XStream' available
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.23.jar:5.3.23]
... 92 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.thoughtworks.xstream.XStream' available
at org.axonframework.springboot.autoconfig.AxonAutoConfiguration.lambda$buildSerializer$5(AxonAutoConfiguration.java:203) ~[axon-spring-boot-autoconfigure-4.6.1.jar:4.6.1]
at java.base/java.util.Optional.orElseThrow(Optional.java:408) ~[na:na]
at org.axonframework.springboot.autoconfig.AxonAutoConfiguration.buildSerializer(AxonAutoConfiguration.java:203) ~[axon-spring-boot-autoconfigure-4.6.1.jar:4.6.1]
at org.axonframework.springboot.autoconfig.AxonAutoConfiguration.serializer(AxonAutoConfiguration.java:139) ~[axon-spring-boot-autoconfigure-4.6.1.jar:4.6.1]
at org.axonframework.springboot.autoconfig.AxonAutoConfiguration$$EnhancerBySpringCGLIB$$8e4e8f9c.CGLIB$serializer$0() ~[axon-spring-boot-autoconfigure-4.6.1.jar:4.6.1]
at org.axonframework.springboot.autoconfig.AxonAutoConfiguration$$EnhancerBySpringCGLIB$$8e4e8f9c$$FastClassBySpringCGLIB$$61b7777c.invoke() ~[axon-spring-boot-autoconfigure-4.6.1.jar:4.6.1]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.23.jar:5.3.23]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.23.jar:5.3.23]
at org.axonframework.springboot.autoconfig.AxonAutoConfiguration$$EnhancerBySpringCGLIB$$8e4e8f9c.serializer() ~[axon-spring-boot-autoconfigure-4.6.1.jar:4.6.1]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.23.jar:5.3.23]
... 93 common frames omitted

Add load generation module

The load generation module should have a command handler that takes a single command, which causes it to start a load test cycle using the parameters of the command.

The module should have a UI component that sends one or more of these commands to the modules that have been deployed.

Commands generated by the load test module should have a lower priority, so that commands through interactive interfaces (such as gc-gui) are handled first.

Provide load testing modules for Giftcard Demo

In order to simulate load on a system, some additional modules should be added to the Giftcard Demo application. The additional modules generate load, simulating high volume usage of the giftcard system and report metrics on the system's performance.

Cannot build freshly-cloned giftcard demo application

Basic information

  • JDK version:
$ java --version
java 11.0.15 2022-04-19 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.15+8-LTS-149)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.15+8-LTS-149, mixed mode)

Steps to reproduce

  • open terminal
  • git clone [email protected]:AxonIQ/giftcard-demo.git
  • cd giftcard-demo
  • ./mvnw clean package

Expected behaviour

  • app should build successfully

Actual behaviour

  • build fails:
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------< io.axoniq.demo:giftcard-demo >--------------------
[INFO] Building giftcard-demo 4.6
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.7.9:run (default-cli) > test-compile @ giftcard-demo >>>
[INFO]
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ giftcard-demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 4 resources
[INFO] Copying 0 resource
[INFO]
[INFO] --- kotlin-maven-plugin:1.8.10:compile (compile) @ giftcard-demo ---
WARN: zip file is empty: /Users/username/.m2/repository/org/axonframework/axon-modelling/4.7.2/axon-modelling-4.7.2.jar
java.util.zip.ZipException: zip file is empty
	at java.base/java.util.zip.ZipFile$Source.zerror(ZipFile.java:1597)
	at java.base/java.util.zip.ZipFile$Source.findEND(ZipFile.java:1401)
	at java.base/java.util.zip.ZipFile$Source.initCEN(ZipFile.java:1495)
	at java.base/java.util.zip.ZipFile$Source.<init>(ZipFile.java:1299)
	at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1262)
	at java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:733)
	at java.base/java.util.zip.ZipFile$CleanableResource.get(ZipFile.java:842)
	at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:248)
	at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:177)
	at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:148)
	at com.intellij.openapi.vfs.impl.ZipHandler$1.createAccessor(ZipHandler.java:32)
	at com.intellij.openapi.vfs.impl.ZipHandler$1.createAccessor(ZipHandler.java:25)
	at com.intellij.util.io.FileAccessorCache.createHandle(FileAccessorCache.java:62)
	at com.intellij.util.io.FileAccessorCache.get(FileAccessorCache.java:55)
	at com.intellij.openapi.vfs.impl.ZipHandler.getCachedZipFileHandle(ZipHandler.java:70)
	at com.intellij.openapi.vfs.impl.ZipHandler.acquireZipHandle(ZipHandler.java:117)
	at com.intellij.openapi.vfs.impl.ZipHandlerBase.createEntriesMap(ZipHandlerBase.java:38)
	at com.intellij.openapi.vfs.impl.ArchiveHandler.getEntriesMap(ArchiveHandler.java:179)
	at com.intellij.openapi.vfs.impl.jar.CoreJarHandler.<init>(CoreJarHandler.java:42)
	at com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem.lambda$new$0(CoreJarFileSystem.java:33)
	at com.intellij.util.containers.ConcurrentFactoryMap$2.create(ConcurrentFactoryMap.java:174)
	at com.intellij.util.containers.ConcurrentFactoryMap.get(ConcurrentFactoryMap.java:40)
	at com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem.findFileByPath(CoreJarFileSystem.java:44)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.findJarRoot(KotlinCoreEnvironment.kt:405)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.contentRootToVirtualFile(KotlinCoreEnvironment.kt:383)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.access$contentRootToVirtualFile(KotlinCoreEnvironment.kt:107)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$2.invoke(KotlinCoreEnvironment.kt:230)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$2.invoke(KotlinCoreEnvironment.kt:107)
	at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.convertClasspathRoots(ClasspathRootsResolver.kt:76)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:239)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:107)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:448)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.createCoreEnvironment(K2JVMCompiler.kt:201)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:152)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:101)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:47)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
	at org.jetbrains.kotlin.maven.KotlinCompileMojoBase.execCompiler(KotlinCompileMojoBase.java:228)
	at org.jetbrains.kotlin.maven.K2JVMCompileMojo.execCompiler(K2JVMCompileMojo.java:237)
	at org.jetbrains.kotlin.maven.K2JVMCompileMojo.execCompiler(K2JVMCompileMojo.java:55)
	at org.jetbrains.kotlin.maven.KotlinCompileMojoBase.execute(KotlinCompileMojoBase.java:209)
	at org.jetbrains.kotlin.maven.K2JVMCompileMojo.execute(K2JVMCompileMojo.java:222)
	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
	at org.apache.maven.lifecycle.internal.MojoExecutor.executeForkedExecutions(MojoExecutor.java:355)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:200)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.apache.maven.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:39)
	at org.apache.maven.wrapper.WrapperExecutor.execute(WrapperExecutor.java:122)
	at org.apache.maven.wrapper.MavenWrapperMain.main(MavenWrapperMain.java:61)
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt: (6, 26) Unresolved reference: modelling
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt: (10, 30) Unresolved reference: TargetAggregateIdentifier
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt: (11, 31) Unresolved reference: TargetAggregateIdentifier
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt: (12, 31) Unresolved reference: TargetAggregateIdentifier
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.385 s
[INFO] Finished at: 2023-03-26T20:00:36-06:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.jetbrains.kotlin:kotlin-maven-plugin:1.8.10:compile (compile) on project giftcard-demo: Compilation failure: Compilation failure:
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt:[6,26] Unresolved reference: modelling
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt:[10,30] Unresolved reference: TargetAggregateIdentifier
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt:[11,31] Unresolved reference: TargetAggregateIdentifier
[ERROR] /Users/username/work/axoniq/giftcard-demo/src/main/java/io/axoniq/demo/giftcard/api/api.kt:[12,31] Unresolved reference: TargetAggregateIdentifier
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

gc-gui won't start if spring-boot-devtools is added

When I add the spring-boot-devtools to the gc-gui project the application won't start anymore.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
</dependency>

Error:

2018-04-12 16:09:33.455  WARN 22365 --- [  restartedMain] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processorInfoConfiguration' defined in class path resource [io/axoniq/axonhub/client/boot/MessagingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'processorInfoConfiguration' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.axonframework.config.EventHandlingConfiguration' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2018-04-12 16:09:33.458  INFO 22365 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

Measure and expose read model latency

The load test module should display metrics on the measured latency of the read models.

This could either be done through a Scatter/Gather Query, or using a Subscription Query. Nodes would send regular updates with their own metrics.

Measure and report message throughput in components

All the components should report performance metrics they observe. The metrics can be exposed using HTTP endpoints (via Spring Boot Actuator, for example) and retrieved by the Load Test GUI on regular intervals.

Adding giftcard with existing ID gives cryptic error

There is an exception when creating a Giftcard with an existing ID. The exception is a technical exception that a normal user would not understand.

OUT_OF_RANGE: AXONIQ-2000 Invalid Sequence number 0 for aggregate Coen-1, expected 3

I guess this means we do not support creating a Giftcard with an existing ID. To show exception handling could be good to show this the right way as well

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.