SkillAgentSearch skills...

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/Books

README

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.

Actions CI Build Sonar Quality Gate

Implementation

The main functionality included in the microservice includes

  • being based on latest Spring Boot 4.x and Java 21
  • Oauth2 based logon using
    • Google
    • Facebook
  • 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 -d command
  • 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/

The Cloudy Book Club

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

View on GitHub
GitHub Stars106
CategoryDevelopment
Updated1mo ago
Forks29

Languages

Java

Security Score

85/100

Audited on Feb 15, 2026

No findings