Skip to content

Latest commit

 

History

History
225 lines (147 loc) · 9.3 KB

README.md

File metadata and controls

225 lines (147 loc) · 9.3 KB

Backend

Java service built with the Spring WebFlux reactive stack.

Development

Run Service

Requires the all but backend to be running in docker:

# optionally add -d or --detached for detached mode
../run.sh dev --no-backend

Start backend with IntelliJ:

  • Use the checked in run config in ../.idea/runConfigurations/. If you open just this backend folder with IntelliJ, you will need to copy and adjust it.

Start backend with VS Code:

  • The launch config in .vscode/launch.json should be used automatically

Start backend from CLI:

SPRING_PROFILES_ACTIVE=local ./gradlew bootRun

Note

The application depends on a Java package from a private GitHub package repository. To be able to download it in the Gradle build process, you'll need to set up your local env as described in the root readme.

Lookup tables

Some dropdown menus in the frontend get populated via calls to the backend that query the respective database tables. If you are developing locally and want to see values in those dropdown menus you need to do this one-time step: trigger the import of XML files to these database tables. Furthermore, some e2e tests are testing this behaviour. Those will fail locally if your lookup tables are not populated.

To import the XML files, follow these steps:

  • Download the XML files doktyp.xml, gerichtdata_gesamt.xml, buland.xml, sachneudata_gesamt.xml, zitartdata_gesamt.xml (Link in the Engineering Onboarding Wiki)
  • Start the application (see root README), open it in your browser and log in
  • Copy the SESSION cookie value from the Browser Developer Tools --> Application Tab --> Cookies (If you prefer using Postman, it also supports importing cookies from your browser.)

Fill these variables with your values:

export PATH_TO_XML_FILES="/path/to/xml/files"    # where you placed the xml files
export SESSION_VALUE="your-session-cookie-value" # copied from Browser Developer Tools
export HOST="http://127.0.0.1"                   # backend host

Then do the requests with curl:

curl -v -X PUT -H 'Content-Type: application/xml' -H "cookie: SESSION=$SESSION_VALUE" --data "@$PATH_TO_XML_FILES/doktyp.xml" $HOST/api/v1/caselaw/lookuptableimporter/doktyp
curl -v -X PUT -H 'Content-Type: application/xml' -H "cookie: SESSION=$SESSION_VALUE" --data "@$PATH_TO_XML_FILES/gerichtdata_gesamt.xml" $HOST/api/v1/caselaw/lookuptableimporter/gerichtdata
curl -v -X PUT -H 'Content-Type: application/xml' -H "cookie: SESSION=$SESSION_VALUE" --data "@$PATH_TO_XML_FILES/buland.xml" $HOST/api/v1/caselaw/lookuptableimporter/buland
curl -v -X PUT -H 'Content-Type: application/xml' -H "cookie: SESSION=$SESSION_VALUE" --data "@$PATH_TO_XML_FILES/sachneudata_gesamt.xml" $HOST/api/v1/caselaw/lookuptableimporter/fieldOfLaw
curl -v -X PUT -H 'Content-Type: application/xml' -H "cookie: SESSION=$SESSION_VALUE" --data "@$PATH_TO_XML_FILES/zitartdata_gesamt.xml" $HOST/api/v1/caselaw/lookuptableimporter/zitart

Refresh materialized views

curl -v -X PUT -H "cookie: SESSION=$SESSION_VALUE" http://127.0.0.1/api/v1/caselaw/normabbreviation/refreshMaterializedViews

Database Setup & Migration with Flyway

The application uses Flyway for maintaining and versioning database migrations. In order to create a change in the database you should follow one of the two methods:

  1. If you want to create a migration using SQL:
    • You should create a new sql file on the directory src\main\resources\db\migration.
    • The file should be named in the following format: Vx.x__teamname_create_table_xyz.sql where x.x is your migration version (make sure to pull first from the repository and see what is the latest version otherwise migrations wouldn't work properly).
  2. If you want to create a migration using Java:
    • You should create a new Java class on the directory src\main\java\db\migration that extends BaseJavaMigration and implements the method void migrate(Context context) throws Exception.
    • The file should be named in the following format: Vx_x__teamname_create_table_xyz.sql where x_x is your migration version (make sure to pull first from the repository and see what is the latest version in the sql path and the java path otherwise migrations wouldn't work properly).

For both migration file names, the teamname can be replaced with: whether caselaw or norms and is normally followed by a descriptive name for the migration.

Flyway automatically detects new files and run migrations accordingly on sprint boot start.

Tests

The project has distinct unit and integration test sets.

To run just the unit tests:

./gradlew test

To run the integration tests:

./gradlew integrationTest

Note

Running integration tests requires passing unit tests (in Gradle terms: integration tests depend on unit tests), so unit tests are going to be run first. In case there are failing unit tests we won't attempt to continue running any integration tests.

To run integration tests exclusively, without the unit test dependency:

./gradlew integrationTest --exclude-task test

Denoting an integration test is accomplished by using a JUnit 5 tag annotation: @Tag("integration").

Furthermore, there is another type of test worth mentioning. We're using ArchUnit for ensuring certain architectural characteristics, for instance making sure that there are no cyclic dependencies.

Formatting & Styleguide

Check our Java Styleguides document. To set up IntelliJ IDEA follow these instructions. Consistent formatting, for Java as well as various other types of source code, is being enforced via Spotless.

Check formatting:

./gradlew spotlessCheck

Autoformat sources:

./gradlew spotlessApply

Code quality analysis

Continuous code quality analysis is performed in the pipeline upon pushing to trunk; it requires a token provided as SONAR_TOKEN repository secret that needs to be obtained from https://sonarcloud.io.

To run the analysis locally:

SONAR_TOKEN=[sonar-token] ./gradlew sonarqube

Go to https://sonarcloud.io for the analysis results.

Container image

Container images running the application are automatically published by the pipeline to the GitHub Packages Container registry.

To run the latest published image:

docker run -p8080:8080 "ghcr.io/digitalservicebund/ris-backend-service:$(git log -1 origin/main --format='%H')"

The service will be accessible at http://localhost:8080.

We are using Spring's built-in support for producing an optimized container image:

./gradlew bootBuildImage
docker run -p8080:8080 ghcr.io/digitalservicebund/ris-backend-service

Container images in the registry are signed with keyless signatures.

To verify an image:

COSIGN_EXPERIMENTAL=1 cosign verify "ghcr.io/digitalservicebund/ris-backend-service:$(git log -1 origin/main --format='%H')"

If you need to push a new container image to the registry manually there are two ways to do this:

Via built-in Gradle task:

export CONTAINER_REGISTRY=ghcr.io
export CONTAINER_IMAGE_NAME=digitalservicebund/ris-backend-service
export CONTAINER_IMAGE_VERSION="$(git log -1 --format='%H')"
CONTAINER_REGISTRY_USER=[github-user] CONTAINER_REGISTRY_PASSWORD=[github-token] ./gradlew bootBuildImage --publishImage

Note: Make sure you're using a GitHub token with the necessary write:packages scope for this to work.

Using Docker:

echo [github-token] | docker login ghcr.io -u [github-user] --password-stdin
docker push "ghcr.io/digitalservicebund/ris-backend-service:$(git log -1 --format='%H')"

Note: Make sure you're using a GitHub token with the necessary write:packages scope for this to work.

Vulnerability Scanning

Scanning container images for vulnerabilities is performed with Trivy as part of the pipeline's build job, as well as each night for the latest published image in the container repository.

To run a scan locally:

./gradlew bootBuildImage
trivy image --severity HIGH,CRITICAL ghcr.io/digitalservicebund/ris-backend-service:latest

License Scanning

License scanning is performed as part of the pipeline's build job. Whenever a production dependency is being added with a yet unknown license the build is going to fail.

To run a scan locally:

./gradlew checkLicense

Dependency Updates

Can be used to show the latest release version for every dependency. Generate a report in build/dependencyUpdates/report.txt.

To run a scan locally:

./gradlew dependencyUpdates -Drevision=release