Generating an application using a Maven archetype

See how easy it is to use Maven to generate a Java application that demonstrates the concepts of CQRS and event sourcing.

Generating code or example applications can be a great way to get started with a new tool or concept.

In this guide you will learn how to generate a Java/Dropwizard application using a Maven archetype.

The generated application will be a fully functional backend service exposing a HTTP API according to the principles of CQRS. The API will use Serialized for storing events and projections so if you don't have an account yet, head over here to register one for free!

Generating the code

Start by opening a shell and type the following:

mvn archetype:generate \
  -DarchetypeGroupId=io.serialized.archetype \
  -DarchetypeArtifactId=serialized-dropwizard-archetype

You will be prompted for groupId and artifactId. Just enter com.example and my-test-service if you can't come up with anything better.

The version and package can be skipped (keeping default) by pressing ENTER.

Finally, you will have choose if you want to keep the suggested names for the aggregateRoot and the applicationName.

Building the code

Build the code by changing to the new directory and execute Maven:

cd my-test-service

mvn verify

Wait for the code to build and the tests to complete.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Starting the service

Make sure to set/export the API keys to your Serialized project:

For Mac and Linux users:

export SERIALIZED_ACCESS_KEY=<your-access-key>
export SERIALIZED_SECRET_ACCESS_KEY=<your-secret-key>

or if you are on Windows:

set SERIALIZED_ACCESS_KEY=<your-access-key>
set SERIALIZED_SECRET_ACCESS_KEY=<your-secret-key>

Start the service:

java -jar target/my-test-service-1.0-SNAPSHOT.jar server config/config.yml

Calling the command API of your service

When we want to write/make state changes to our aggregate root we call the command API.

Note: We will assume you kept the suggested aggregate root name Game in the following API calls.

Open a new shell and perform the following curl to send a start command:

curl -i http://localhost:8080/commands/start-game \
  --header "Content-Type: application/json" \
  --data '
  {  
     "gameId": "3dbc7063-76d6-4df2-8ab4-72d1f897563b"
  }
  '

The expected response should be something like this:

HTTP/1.1 201 Created
Location: http://localhost:8080/queries/games/3dbc7063-76d6-4df2-8ab4-72d1f897563b
Content-Length: 0

Note that the Location header points to where we can access the projected read-model via the query API.

The start command results in a stored event called GameStarted was stored in Serialized. Browse to the Console and have a look at it!

Calling the query API of your service

When we want to get our data, we use the query API.

Try to get the projected game state using this simple GET request:

curl -i http://localhost:8080/queries/games/3dbc7063-76d6-4df2-8ab4-72d1f897563b

The expected response should be something like this:

HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept-Encoding
Content-Length: 28

{
  "status" : "STARTED"
}

Make a second state change by sending another command to the API

Let's send a finish command to put our aggregate root into its end-state:

curl -i http://localhost:8080/commands/finish-game \
  --header "Content-Type: application/json" \
  --data '
  {  
     "gameId": "3dbc7063-76d6-4df2-8ab4-72d1f897563b"
  }
  '

Verify the change using the query API

Do the same GET request as before:

curl -i http://localhost:8080/queries/games/3dbc7063-76d6-4df2-8ab4-72d1f897563b

The status field should now say FINISHED.

Extending the service

Your are now ready to add your own functionality to your service! Try to add some fields to existing commands/events, introduce new commands or play around with the projections.

Check out our sample code for inspiration!

More info regarding the Java Client can be found on our site.

Detailed info regarding the API:s can be found in the official documentation.