CQRS and eventsourcing with API Platform I
February 2, 2019
Last week I’have started to build a new backend for our groundwater managenment platform INOWAS-DSS. My goal was to use all the great tools which offers API Platform out of the box, combined with CQRS and event sourcing, which we are happy to have ready in production with our React-Web-App.
Happy with my first steps I shouted out into twitter:
Yesterday I’ve build an #eventsourcing prototype with JWT- auth based on @ApiPlatform and #symfony messenger. Anybody interested in a step-by-step tutorial? pic.twitter.com/wllRHcCjwk
— rabbl (@rabbl) February 1, 2019
I was overwhelmed from the feedback given by so many people.
So, here it comes with the following contents:
Contents
- Setup API Platform and CLI tools
- Setup user management and authentication
- Implementing CQRS with symfony messenger
- Implementing eventsourcing
Disclaimer
- This is an opinionated prototype of an ES implementation.
- It’s definitely not perfect.
- It does not treat every use case.
- I would like to hear your opinions about it.
The domain
For this tutorial a have choosen library example.
Assuming we have a big library with a lot of books.
Mainly you can find books, but you have also staff there and you have the users which are lending books.
- Books located in the library can be lend.
- New books can be aquired.
- Users can lend this books and bring them back.
- Books will get sorted out if they are out of date.
- …
Part I: Setup API Platform
Starting on the official website of the API Platform project you can find the Installation section.
I have cloned the repository into the folder api-platform-eventsourcing and checked out the latest stable version:
$ git clone https://github.com/api-platform/api-platform.git api-platform-eventsourcing
$ git tag
...
v2.3.0-beta.1
v2.3.1
v2.3.2
v2.3.3
v2.3.4
v2.3.5
v2.3.6
v2.4.0-beta.1
$ git checkout -b part-1 v2.3.6
As explained in the Docs you can start the whole distribution.
$ docker-compose up -d
Make sure you have the docker client running. You can list all running containers with:
$ docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
api-platform-eventsourcing_admin_1 /bin/sh -c yarn start Up 0.0.0.0:81->3000/tcp
api-platform-eventsourcing_api_1 nginx -g daemon off; Up 0.0.0.0:8080->80/tcp
api-platform-eventsourcing_cache-proxy_1 docker-varnish-entrypoint ... Up 0.0.0.0:8081->80/tcp
api-platform-eventsourcing_client_1 /bin/sh -c yarn start Up 0.0.0.0:80->3000/tcp
api-platform-eventsourcing_db_1 docker-entrypoint.sh postgres Up 0.0.0.0:5432->5432/tcp
api-platform-eventsourcing_h2-proxy_1 nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:444->444/tcp, 80/tcp, 0.0.0.0:8443->8443/tcp,
0.0.0.0:8444->8444/tcp
api-platform-eventsourcing_php_1 docker-entrypoint php-fpm Up 9000/tcp
Running console/composer commands
To execute symfony console commands you can run now:
$ docker-compose exec php bin/console
WARNING: The CONTAINER_REGISTRY_BASE variable is not set. Defaulting to a blank string.
Symfony 4.2.2 (env: dev, debug: true)
Usage:
command [options] [arguments]
....
To install additional composer packages run:
$ docker-compose exec php composer
WARNING: The CONTAINER_REGISTRY_BASE variable is not set. Defaulting to a blank string.
______
/ ____/___ ____ ___ ____ ____ ________ _____
/ / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
/_/
Composer version 1.8.2 2019-01-29 15:00:53
Usage:
command [options] [arguments]
....
Querying your API
Now you can make your first API call with cURL.
$ curl localhost:8080
{"@context":"\/contexts\/Entrypoint","@id":"\/","@type":"Entrypoint","greeting":"\/greetings"}%
For this tutorial I’m using mainly HTTPie ❤️ for HTTP-calls from the CLI.
$ http localhost:8080
HTTP/1.1 200 OK
Cache-Control: no-cache, private
Connection: keep-alive
Content-Type: application/ld+json; charset=utf-8
Date: Sat, 02 Feb 2019 17:03:50 GMT
Link: <http://localhost:8080/docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
Server: nginx/1.15.8
Transfer-Encoding: chunked
Vary: Accept
X-Content-Type-Options: nosniff
X-Debug-Token: e3e684
X-Debug-Token-Link: http://localhost:8080/_profiler/e3e684
X-Frame-Options: deny
X-Powered-By: PHP/7.2.14
{
"@context": "/contexts/Entrypoint",
"@id": "/",
"@type": "Entrypoint",
"greeting": "/greetings"
}
The response gives you some useful informations.
You can open the Symfony Profiler in your browser with the link given under X-Debug-Token-Link.
X-Debug-Token-Link: http://localhost:8080/_profiler/e3e684
Now we have everything setup and running and can finally start coding.