This is the backend API for Presentium, handling connections with the databse, the reader devices and frontend instances. It is built with Spring Boot in Java 21.
The project is built with Gradle.
The API documentation is available at api.presentium.ch/swagger-ui.html. It is built automatically using Springdoc and available on the local instance as well.
Start the development server on http://localhost:13000
:
./gradlew bootRun
Or by using the dev profile [start]
profile in IntelliJ IDEA, stored in the .run
folder.
We leverage
Spring Boot's Docker Compose module
to provision the local development environment. This includes a PostgreSQL database, a dex
server acting as a OIDC
provider, and a Redis instance for session data and caching.
Running the API server in a development environment will automatically call docker compose up
and add the necessary
connection details to the application context.
Tip
When testing, either manually or in integration / end-to-end tests, you can use the TestcontainersConfiguration
which
provides the same environment as the local development setup, but it is volatile and is reset between each runs.
A Spring runner is also configured to use the Testcontainers configuration in TestPresentiumApiApplication
. Which
can be started using the ./gradlew bootTestRun
command.
When changing the database model, one should ensure that the changes are correctly defined in the Liquibase migrations.
Liquibase migrations shall always be placed under the app version they are being introduced. They can be found in the
src/main/resources/db/changelog
directory.
Migration files are named with a prefix that corresponds to the GitHub Issue number that the task is related to,
followed by a short description of the task. For example, GH-1_add-users-table.xml
.
Each version directory contains a local _changelog.yaml
file that should be referenced in the main changelog.yaml
file.
Note
We use YAML
files for indexes as it is easier to follow when there is only simple references.
For actual changelog files, please use the XML
format, as it makes sure the changes can be correctly validated.
To help with creating changelog files, a unit test DDLGeneratorTest
should be run once. It will generate the DDL in
sql/ddl/create.sql
, which can be used as a reference for the new changelog file (for example by using diffs).
This application is split into standard layers. The business layer shall be responsible of handling the business model and its logic (using entities, repositories, services, etc.), while the API layer shall be responsible for handling API calls and responses.
Therefore, the application should mainly work using business entities at all times, and the API layer will use mappers to convert said business entities to view models that represent exposed information. The API also defines request bodies for request requiring it, using mappers to convert them to business entities straight away.
Controllers are responsible for opening transactions, calling services, and returning the response. They are responsible for ensuring that the user making the call is authorized to do so, validating that the sent data is correct, then calling the business service to perform the operation. If the business service sends a response, the controller should convert it to a view model and return it, handling any exceptions should one arise.
api
package contains the API layer, with controllers, mappers, and view models.business
package contains the business layer, with entities, repositories, services, and mappers.
Inside packages, we try to separate concerns by their business domain. For example, the user
domain
is held in api.user
for the API layer, and business.model.user
for the data domain.
In theory, all endpoints should require authentication, but the access level can be changed depending
on if it is reserved for teachers or teacher and students. To test these endpoints, you can use the
@WithMockAuthenticatedUser
annotation and sub-annotations, like @WithMockTeacherUser
,
@WithMockStudentUser
, or @WithMockAdminUser
.
Using the local development environment provisioned with docker compose, you can generate an access
token by using the mock oidc debugger at http://localhost:17580/presentium/debugger. You will simply
need to configure the scope to openid profile email
and get the token.
You can then use the Swagger UI to try out the API at http://localhost:13000/swagger-ui/index.html.
You will need to provide the token in the Authorize
button at the top right of the page, the token
to use is the access_token
field from the OIDC debugger.
Testing gRPC calls is trickier due to the mTLS (mutual TLS) requirement. If you have grpcui installed, you can use the following command to attach to the api
grpcui \
-bind=0.0.0.0 -port=8080 \
-cacert=src/test/resources/docker/vault/presentium_servers_inter_ca.pem \
-cert=src/test/resources/docker/vault/device.crt \
-key=src/test/resources/docker/vault/device.key \
localhost:13050
Each commit on the main
branch is deployed to staging-api.presentium.ch
using GitHub Actions, to a dedicated namespace on the Cloud infrastructure.
The default branch therefore is main
and it is protected. When a change is ready to be deployed,
the deployment workflow should be triggered manually providing the desired version number.
Please refer to the Contributing Guide before making a pull request.