diff --git a/README.md b/README.md index 5cb81ed..8602ac9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ ## Requirements - [GraalVM 23](https://www.graalvm.org/) -- PostgreSQL 17, but a Docker Compose file is available for your convenience +- PostgreSQL 17, but a Docker Compose file is available for your convenience. + If you decide to run it locally, **please check application.yml for default values**. ## Generate sources @@ -13,4 +14,74 @@ To generate code from the API contract, run `./mvnw generate-sources` 1. Make sure your `JAVA_HOME` or `GRAALVM_HOME` environment variable is correctly pointing to your JDK. -1. Run `./mvnw -Pnative native:compile`. \ No newline at end of file +1. Run `./mvnw -Pnative native:compile`. + +Note that you don't need to build a native executable to run a development +environment. + +## Choices + +### GraalVM + +It's my first time using GraalVM, but I took the opportunity of using it in this +project because of its small scale. Its goals are to improve the performance of +JVM-based applications to match native languages. + +Startup times are also greatly improved; less than 0.5 seconds. The drawback is +that the build times are greatly lengthened; around 1 minute for an empty +project. + +### PostgreSQL + +I don't think I have to explain much about PostgreSQL, but it's well-suited for +both small and large-scale projects. Also, support with Spring Boot is, in my +experience, flawless. + +### Flyway + +I'm experienced with Liquibase, but after quickly reading about errors related +to GraalVM, I understood it was unsupported. Flyway is another popular migration +tool, so I gave it a go. I have nothing to say for or against it. + +### JWT + +I knew the basics but never implemented the authentication layer myself. JWT +is a standard, but in an enterprise environment there would probably be an +OIDC-compliant service to be plugged into. + +After initializing the correct beans, it worked really well. + +As I don't specify the JWT secret, all issued tokens are not recognized after +a restart and must be regenerated (i.e. all users are logged out). + +LLMs were a great help here too, along with good ol' Baeldung. + +### Files + +At first, I wanted to store the files as a BYTEA in the database. I thought +this would be much simpler and minimalistic, but I was wrong on the first point. +I gave up after I couldn't find the root of the error "cannot convert to long", +despite not having a single long in my source code. Anyway, files are stored +on the filesystem and are retrieved by the `PdfServiceImpl`. This service makes +sure that the file name doesn't contain `".."` in the file name in order to +prevent [directory traversal attacks](https://en.wikipedia.org/wiki/Directory_traversal_attack). +Files are not uploaded by the user so there is virtually 0 chance of it containing +malicious characters, but I thought it was important to safeguard against this. + +### UUID + +As there is insanely little chance of collision, UUID are most useful in +distributed systems where we could give the responsibility of generating +the UUID to the clients. For a system like this, I doubt that the max value +of 64-bit integers would be reached, but the maintainability cost isn't much +higher than using integers. If anything, it at least prevents the user from +using the ID in the wrong place (i.e. `DELETE /person/1` instead of +`DELETE /city/1`) as no entity shares the same ID. + +### json-patch + +I used [json-patch](https://github.com/java-json-tools/json-patch) to confirm +the status of documents. Instead of sending the whole representation, only +the operation (`op`), the path (`path`) to apply it to and the new value +(`value`) have to be supplied. +