Frontend: Aurelia
Backend: SpringBoot with MongoDB
The UI is going to transform its internal domain model to the domain model of the backend, and just use the REST API as a simple CRUD API.
Validation of the backends domain model happens in the backend.
Validation of the UI domain model happens in the UI.
Reasoning behind this is that first and foremost we want to play with Aurelia.
Install Docker. (either with toolbox or native)
Run docker-compose up
.
There now should be an instance running at 192.168.99.100:27017
.
brew install mongodb
to get at least a mongo shell.
Install the Mongo Plugin
in IntelliJ.
Add 192.168.99.100:27017
as a new connection, et voila, happy querying.
As an alternative, you can also install RoboMongo
We are now only serving static content, and therefore we don't need an IndexController
anymore.
Thymeleaf serves index.html
straight from the resources/static
dir.
This is why application.properties
has properties:
spring.jersey.applicationPath=/api
spring.jersey.type=filter
The spring.jersey.type=filter
property will run Jersey as a Filter instead of a Servlet.
The other thing I had to do was add the spring-boot-starter-thymeleaf
dependency, so that there's an automagic ViewResolver that tries to find a matching filename in /resources/static
.
To be able to work with this way of Aurelia app, install the aurelia-cli as follows:
npm install -g aurelia-cli
Or follow this guide for more info.
I generated it using au new --here
and modifying the default names to contain CQRS instead of default or whatever.
Mark src/main/resources/static/node_modules
as Excluded. 👍
First, since node_modules was excluded, you have to install all the dependencies. From the static dir, run:
npm install
Next, from the static dir, run the app via the CLI:
au run
We're using aurelia-notification, a non-official plugin for Aurelia which wraps humane.js to provide notifications that automatically disappear.
This required us to add a dependency on aurelia-18n, which required a dependency on i18next
and i18n-xhr-backend
.
There's stuff configured in main.js
for both i18n and notifications.
Whenever you want to change the humanejs theme, you'll have to modify
main.js:
.plugin('aurelia-notification', config => {
...
notifications: {
'success': 'humane-jackedup-success',
'error': 'humane-jackedup-error',
'info': 'humane-jackedup-info'
}
...
index.html:
<link rel="stylesheet" href="node_modules/humane-js/themes/jackedup.css">
aurelia.json:
{
"name": "humane-js",
"path": "../node_modules/humane-js",
"main": "humane",
"resources": [
"themes/jackedup.css"
]
}
Other than src/main/resources/application.properties, there's a src/test/resources/application.properties which overriding the main one at test runtime.
In the latter, the spring.data.mongodb.database
property is set to test
.
This is why we simply use the Application
and JerseyConfig
configuration classes of production.
We're calling our Resource with the jersey-proxy-client
framework.
This is why we're not @Autowiring
our own Resource, but instead using a WebResourceFactory
to proxy our Resource, and do all the actual http calls, marshalling and error handling via jersey-client
.
Note: We don't have automatic branch promotion so we have to do this manually.
- Make your changes.
- Build locally with
./gradlew buildDist stageUI build
- Build a docker image with
docker build . -t swsb/cqrsapp:1.0-SNAPSHOT
- Manually test your changes with
docker-compose up
- Merge your branch with prod with
git merge origin/prod
- If you had any conflicts, merge them and go back to step 2.
- Push your branch to github
- Wait for a successful Travis build of your branch
- Merge your branch on to prod with
git checkout prod && git merge <yourbranch>
- Push prod to github
- Travis will pick up the prod branch, and on a successful gradle build, Travis will build a docker image from your successfully built .ear file and push it to both DockerHub's and Heroku's registries.
- Heroku will pick up the newly pushed docker image and will restart the container with the new docker image.
Check out Travis' excellent documentation and our .travis.yml file.
Because we're actually deploying with Travis by pushing to the Heroku registry.
Preferably don't deploy manually, because there aren't necessarily any code changes pushed to our code repository.
First log in to the heroku registry with docker login -u=herokuuser -p=herokuauthtoken registry.heroku.com
, or with the CLI heroku container:login
.
Then make sure you create a tag based off your earlier built docker image (see above) with docker tag swsb/cqrsapp:1.0-SNAPSHOT registry.heroku.com/cool-quote-registration-system/web
.
And push that tag with docker push registry.heroku.com/cool-quote-registration-system/web
.
It's really important that there are Heroku config variables for every environment variable our docker container needs.
These are entered in heroku's settings tab.
Miss one, either by not listing a new one, or having a typo in one of them, and the app won't work anymore.
Either install the Heroku CLI and type heroku logs -a cool-quote-registration-system
, or log in to the Heroku dashboard and click on More > Logs.
First pull the latest successfully deployed docker image with docker pull swsb/cqrsapp
.
Then change docker-compose.yml to use the swsb/cqrsapp
image instead of the locally built :1.0-SNAPSHOT
tag.
And run docker-compose up
.