Books
A demo project for Spring Boot / Data / security, social / oauth2 logons, JWT, Mongo, SpringBootAdmin, Docker, docker-compose, Github Actions and stateless apps. Now with an HTMX front end.
Install / Use
/learn @aidanwhiteley/BooksREADME
books
This project started as I wanted a simple "microservice" to use when trying out frameworks such as Docker, Docker Compose and Kubernetes. It then continued as my favourite project for sampling various web related technologies.
It has developed a little further such that it is starting to provide some functionality that may actually be useful.
So welcome to the "Cloudy Bookclub"!
[!NOTE]
Now uplifted to the latest Spring Boot 4.x and Java 21 and with a default, HTMX based front end provided.
Implementation
The main functionality included in the microservice includes
- being based on latest Spring Boot 4.x and Java 21
- Oauth2 based logon using
- the oauth2 logon data is transmogrified into locally stored users - with associated roles - and into a JWT token - making the web application entirely free of http session state (see later for whether using JWTs as session tokens is a good idea)
- Spring Security for role based method level authorisation
- Mongo based persistence with the use of Spring Data MongoRepository
- next to no persistence code
- except for some Mongo aggregation queries added to the Repository implementation
- accessing the Google Books API with the Spring RestTemplate
- and Docker images and a Docker Compose file that runs all the tiers of the application with one
docker compose up -dcommand - new in 2025 - there is now a "built in" front end implementation using HTMX. There's a blog post available about migrating a React front end to Java/Spring Boot/Thymeleaf.
- The earlier JSON data APIs are still retained meaning that the alternative React / Typescript front end implementation still works.
Live application
This project runs live under Docker Compose using the HTMX front end at https://cloudybookclub.com/ and with an alternate React / Typescript client application front end available at https://spa.cloudybookclub.com/

Quick Start (on Windows)
- Install Java JDK 21
- Clone the project
- From the root of the project, type
mvnw.cmd spring-boot:run - Point a browser at http://localhost:8080/
Running in development
The checked in default Spring profile is "mongo-java-server-no-auth". This uses an in memory fake Mongo instance - mongo-java-server - so there is no need to run MongoDb locally. It also auto logs you on with a dummy admin user so there is no need to set up OAuth config to explore the application. So you should be able to just check out the code and run and test the application for development purposes with no other dependencies.
To develop Mongo related code you should switch to the "dev" profile which does expect to be able to connect to a real MongoDb instance.
Please check the console log when running the application. Any key constraints/warnings related to the Spring profile being used will be output to the console.
Tests
All tests should run fine "out of the box" i.e. with a clean checkout of the code you should be able to successfully run
mvnw.cmd clean compile test package and all tests should pass (with the code coverage reports output to target/site/jococo/index.html)
By default, the tests run against mongo-java-server so there is no need to install MongoDb to test most of the application. Functionality not supported by mogo-java-server such as full text indexes results in some tests being skipped when running with the mongo-java-server Spring profile.
When running the CI builds with GitHub Actions, all tests run against a real Mongo instance.
Some of the integration tests make use of WireMock - see the /src/test/resources/mappings and __files directories for the configuration details.
The tests are probably about 50/50 between unit tests and vastly more useful integration tests...
Stress Test
To support a simple load test, there is a Maven plugin configured that runs a basic Gatling load test.
After starting the Spring Boot application (i.e. mvnw.cmd spring-boot:run or via your IDE) run the command:
mvnw.cmd gatling:test
The source code of this test in at test/java/com/aidanwhiteley/books/loadtest/StressTestSimulation.java. The checked in config ensures that, by default, the number of request per second is low enough not to stress an average PC.
Mutation Tests
There is support for mutation testing using the Pitest library.
To try it out use something similar to
mvnw.cmd -Ppitest -DwithHistory=true -DtargetClasses="com.aidanwhiteley.books.service.*" test
Be warned, the first run will take a long time (many minutes) - especially if the glob for targetClasses is wide. Subsequent runs should be much quicker.
Unfortunately, this mutation support wasn't in place when the tests were originally written meaning that the
current test suite have some tests that survive too many mutations! The mutation test code is there for any new code.
How to build and run
This project makes use of the excellent Lombok project. So to build in your favourite IDE, if necessary head on over to Lombok and click the appropriate "Install" link (tested with IntelliJ and Eclipse).
In preparation for playing with recent Java features such as virtual threads and pattern matching, the build of this project now requires JDK21.
With appropriate versions of the JDK (i.e. 21+) and optionally Maven and Mongo installed, start with
mvnw.cmd clean compile test
and then try
mvnw.cmd spring-boot:run
To access the application using the default HTMX based front end, point your browser to http://localhost:8080/
To run a client Single Page Application to access the microservice API, head on over to https://github.com/aidanwhiteley/books-react or see the section below on using Docker.
Available Spring profiles
There are Spring profile files for a range of development and test scenarios.
dev-mongo-java-server-no-auth (the default selected in application.yml)
- uses an in memory mongo-java-server rather than a real MongoDb
- configured such that all request have admin access. No oauth set up required and no logon
- clears down the DB and reloads test data on every restart
dev-mongo-java-server
- uses an in memory mongo-java-server rather than a real MongoDb
- requires oauth configured correctly for access to update operations
- clears down the DB and reloads test data on every restart
dev-mongodb-no-auth
- uses a real MongoDb
- configured such that all request have admin access. No oauth set up required and no logon
- clears down the DB and reloads test data on every restart
dev-mongodb
- uses a real MongoDb
- requires oauth configured correctly for access to update operations
- clears down DB and reloads test data on every restart
CI
- uses a real MongoDb
- clears down the DB and reloads test data on every restart
container-demo-no-auth
- requires the use of "docker-compose up" to start Docker containers - see later
- uses a real MongoDb
- configured such that all request have admin access and oauth config is not required
- clears down the Mongo DB and reloads test data on every restart of the Docker containers
Configuring for production
"Out of the box" the code runs with the "mongo-java-server-no-auth" Spring profile - see the first line of application.yml. None of the checked in available Spring profiles are intended for production use. You will need to decide the required functionality for your environment and configure your Spring profile accordingly.
For instance, you WILL want to set/change the secretKey used for the JWT token signing (see books:jwt:secretKey in the yml files). Please see the code in com.aidanwhiteley.books.controller.jwt.JwtUtils::createRandomBase64EncodedSecretKey which will allow you to generate a random SecretKey rather than using the default one supplied in the non-propduction properties files.
You will also need access to a Mongo instance. The connection URL (in the yml files) will result in the automatic creation of a Mongo database and the two required collections (dependant on the security config of your Mongo install).
Check the console log when running in production - you should see NO warning messages!
How to configure application logon security
A lot of the functionality is normally protected behind oauth2 authentication (via Google and Facebook). To use this, you must set up credentials (oauth2 client ids) on Google and/or Facebook. You must then make the client-id and client-secret available to the running code. There are "placeholders" for these in /src/main/resources/application.yml i.e. replace the existing "NotInSCMx" (Not In Source Code Management!) values with your own.
Sample data
There is some sample data provided to make initial understanding of the functionality a bit easier. It is in the /src/main/resources/sample_data. See the #README.txt in that directory. See the details above for the available Spring profiles to see when this sample data is autoloaded.
Indexes
The Mongo indexes required by the application are not "auto created" (except when running in Docker containers). You can manually apply the indexes defined in /src/main/resources/indexes. In particular, the application's Search functionality won't work unless you run the command to bu
