This Spring Boot demo application demonstrates several aspects of Spring Boot and surrounding technologies. It might be a good starting point for Spring Boot projects with a similar technology stack, or just can be used as a quickstart to test new technologies or potential solutions for certain Spring Boot related problems.
One main focus is on Keycloak, which acts as authentication (OpenID Connect) and authorization (OAuth2) provider. Keycloak's authorization is combined with Spring Security's controller function annotations based on the role and authority management framework. Be aware, that especially the authorization role model is not necessarily a typical real-world model. The core intention here is to restrict the REST Api to user roles provided by Keycloak or by a JPA datasource (Postgres) and to demonstrate the user and role management functionality on both sides.
As database a Postgres instance is running also (as Keycloak) in a local Docker container. Note, that the relational model might be as well a bit 'constructed' in order to reflect all relevant database table relationships and the resulting Hibernate uni- and bi-directional entity representations.
- Spring Boot
- OAuth2
- Keycloak
- Hibernate
- Lombok
- Rest API
- Flyway
- RESTEasy
- WebFlux
- JSP
- Maven
- Postgres
- Docker
- Swagger API Documentation
- Sonarqube
- Typescript DTO Generation
On localhost:8080 some JSP pages with brief user information can be found which are severed by a Spring Boot embedded Tomcat.
An appropriate Angular frontend client is available within my GitHub account. To be able to access most of the implemented features, which are mainly user and role management related, start the frontend locally, navigate to http://localhost:4200 and login as a user with the super admin role.
Username: nilsign
Password: root
There are two options to setup a Keycloak instance running in a Docker container. The easy one is the pre-configured option. Here the creation of the Keycloak realm, clients, secrets, users, roles and all the other configuration work is already done and out of the box available. Also, there is no need to exchange the client secret in the source code, as it is correct already.
To get more used to Keycloak and Docker the manual configuration option is recommended.
For a manual setup of the docker container skip this chapter and instead follow the instructions of the manual configuration.
-
Download a fully pre-configured Docker Keycloak image as tar.
-
Load the tar and then just run it in a Docker container.
$ docker load < [Path to downloaded tar]/jboss-keycloak-demo-project-docker-image-v6.tar $ docker run --name demo-project-keycloak-v6 -p 8100:8080 jboss/keycloak:demo-project-v6
-
To access the Keycloak Administration Console navigate to http://localhost:8100 and enter the following credentials.
Username:
nilsign@gmail.com
Password:root
Note, that the password for all other Keycloak Realm users is also
root
.
-
Get a virgin Keycloak Docker image.
$ docker pull jboss/keycloak
-
Start Keycloak in a Docker container named "demo-project-keycloak", add the Keycloak Admin User and restart Keycloak with port mapping (localhost:8100->8080).
$ docker images $ docker run --name demo-project-keycloak -e KEYCLOAK_USER=nilsign@gmail.com -e KEYCLOAK_PASSWORD=root -p 8100:8080 jboss/keycloak
-
Navigate to http://localhost:8100
-
Login as Keycloak Administrator, use
nilsign@gmail.com
as user androot
as password and navigate to the Administration Console. -
If Keycloak responds to http requests with this payload
"error": "invalid_grant - Account is not fully set up"
, ensure that the temporary Keycloak password is not active anymore! This can be tested by a Keycloak logout and re-login or by simply browsing to http://localhost:8100 in the web browsers Incognito-Mode. If required, there will be a prompt to enter a permanent password.
-
Navigate to http://localhost:8100/auth/admin/master/console
-
Press Realm "Master" -> Add Realm.
Name:
DemoProjectRealm
-
Navigate to DemoProjectRealm->Configure->Clients->"Account". http://localhost:8100/auth/realms/DemoProjectRealm/account
Enable Service Accounts: ON
Enable Authorization: ON
-
Navigate to DemoProjectRealm->Configure->Roles->Realm Roles->"Add roles".
Role Name:
ROLE_REALM_GLOBALADMIN
-
Navigate to DemoProjectRealm->Configure->Manage->Users->"Add user".
Username:
nilsign
Email:nilsign@nilsign.com
Do NOT mix up this user with "nilsign@gmail.com", which is administrator of Keycloak itself.
-
Navigate to DemoProjectRealm->Configure->Manage->Users->nilsign->"Credentials", enter temporary password and press "Set Password".
-
Navigate to DemoProjectRealm->Configure->Manage->Users->nilsign->Role Mappings->"Realm Roles", select
ROLE_REALM_GLOBALADMIN
and press "Add selected".
-
Navigate to DemoProjectRealm->Configure->Clients->"Create".
Client ID:
DemoProjectRestApiClient
-
Navigate to DemoProjectRealm->Configure->Clients->"DemoProjectRestApiClient".
Enabled: ON
Valid Redirect URIs:http://localhost:8080/*
Web Origins:+
-
Navigate to DemoProjectRealm->Configure->Clients->DemoProjectRestApiClient->Roles->"Add Role".
Role Name:
ROLE_REALM_CLIENT_ADMIN
Repeat 1. with Role Name:
ROLE_REALM_CLIENT_SELLER
Repeat 1. with the Role Name:ROLE_REALM_CLIENT_BUYER
-
Navigate to DemoProjectRealm->Configure->Manage->Users->"Add user".
Username:
nilsign
Email:nilsign@nilsign.com
Temporary Password:root
Do NOT this user mix up this with the Keycloak administrator "nilsign@gmail.com".
Repeat 2. with:
Username:
ada
Email:ada.mistrate@nilsign.com
Temporary Password:root
Username:
selma
Email:selma.sellington@nilsign.com
Temporary Password:root
Username:
bud
Email:bud.buyman@nilsign.com
Temporary Password:root
Username:
mad
Email:mad.allistoles@nilsign.com
Temporary Password:root
-
Navigate to DemoProjectRealm->Manage->Users-> ...
... nilsign->Role Mappings->Client Roles->"DemoProjectRestApiClient"
Select role
ROLE_REALM_CLIENT_ADMIN
and press "Add selected"... nilsign->Role Mappings->Client Roles->"realm-management"
Select role
manage-users
and press "Add selected"
Select rolerealm-admin
and press "Add selected"
Select roleview-realm
and press "Add selected"... ada->Role Mappings->Client Roles->"DemoProjectRestApiClient"
Select role
ROLE_REALM_CLIENT_ADMIN
and press "Add selected"
Select roleROLE_REALM_CLIENT_SELLER
and press "Add selected"... ada->Role Mappings->Client Roles->"realm-management"
Select role
view-realm
and press "Add selected"... selma->Role Mappings->Client Roles->"DemoProjectRestApiClient"
Select role
ROLE_REALM_CLIENT_SELLER
and press "Add selected"... bud->Role Mappings->Client Roles->"DemoProjectRestApiClient"
Select role
ROLE_REALM_CLIENT_BUYER
and press "Add selected"
Open the application.yaml(s)
in the project's 'resources' folder and set the correct (your)
Keycloak's "client-secret".
Note, that the (in case of manual setup) correct client secret can be found at
DemoProjectRealm->Configure->Clients->Account->"Credentials"
-
(Optional) Commit the running Keycloak Docker container to a new Docker image.
$ docker ps -a $ docker commit [CONTAINER ID] jboss/keycloak:demo-project-v8
-
(Requires: 9) To start the new jboss/keycloak:demo-project-v8 Docker image execute
$ docker run -p 8100:8080 jboss/keycloak:demo-project-v8
-
To start a stopped container (e.g. after reboot, docker update etc...) call start with the container name or id.
$ docker ps -a $ docker start demo-project-keycloak $ docker start [CONTAINER ID]
-
(Optional) Get Keycloak Server logs
$ docker logs --timestamps --details --follow [CONTAINER ID]
Test the Keycloak instance with Postman
POST REQUEST: http://localhost:8100/auth/realms/DemoProjectRealm/protocol/openid-connect/token
REQUEST BODY: x-www-form-urlencoded
KEY: client_id
=> VALUE: DemoProjectRestApiClient
KEY: username
=> VALUE: nilsign@nilsign.com
KEY: password
=> VALUE: root
KEY: grant_type
=> VALUE: password
KEY: client_secret
=> VALUE: 6a06b69f-8108-4d40-af64-ed1325385c5d
Note, that the correct client secret can be found at DemoProjectRealm->Configure->Clients->Account->Credentials
-
Get Postgres alpine image.
Note, that the selected Postgres version must be supported by Flyway. Check here which postgres version is supported.$ docker pull postgres:11-alpine
-
Run the image named "postgres:11.0-alpine" in detached mode in a container named "demo-project-postgres" with
root
as Postgres password for the Postgres super admin user namedpostgres
.$ docker images $ docker run --name demo-project-postgres -e POSTGRES_PASSWORD=root -d -p 5432:5432 postgres:11-alpine
Start and stop a Docker container.
$ docker stop [CONTAINER ID] $ docker start [CONTAINER ID]
-
(Optional) List all running Docker containers.
$ docker ps
-
(Optional) List all containers (including the stopped containers).
$ docker ps -a
-
(Optional) Get postgres Server logs.
$ docker logs --timestamps --details --follow [CONTAINER ID]
-
Bash into the running postgres Alpine Linux container with the name "demo-project-postgres" (Note, on Windows with MINGW64 cmd use
winpty
as prefix).$ docker exec -it demo-project-postgres bash $ winpty docker exec -it demo-project-postgres bash
-
Switch into the Postgres CLI (psql) within the Docker container with the default user "postgres".
$ psql -U postgres
-
(Use 2. xor 3.) Switch into the Postgres CLI (psql) from the outside of the Docker container.
$ psql -h localhost -p 5432 -U postgres
-
(Optional) List all postgres servers users.
postgres=# \du
-
Create a the Demo Project Postgres database (Do not forget the semicolon!).
postgres=# CREATE DATABASE demoprojectdb;
-
(Optional) List all databases.
postgres=# \l
-
(Optional) Connect to database "demoprojectdb".
postgres=# \c demoprojectdb;
-
(Optional) Disconnect from database "demoprojectdb".
postgres=# \q
Get Sonarqube Docker image and run it in a Docker container.
$ docker pull sonarqube
$ docker run -d --name sonarqube -p 9000:9000 sonarqube
"typescript-generator is a tool for generating TypeScript definition files (.d.ts) from Java JSON classes. If you have REST service written in Java using object to JSON (wire format) mapping you can use typescript-generator to generate TypeScript interfaces or classes from Java classes."
Execute the following maven goal and a directory named 'generated' will appear with a Typescript
file containing all Typescript DTO models. Copy the dto-models.ts
file into the corresponding REST
API client (e.g. a Angular Frontend) project and use it there to communicate with this backend through
its REST API.
Adapt the typescript-generator Maven plugIn
values in the the pom.xml
to e.g. mark additional java packages to be included in the Typescript
DTO model generation.
$ mvn typescript-generator:generate
-
Execute Sonarqube's code analyses.
$ mvn sonar:sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.login="admin" -Dsonar.password="admin"
-
Navigate to the to http://localhost:9000 and enter the default credentials to inspect the results.
Username:
admin
Password:admin
More detailed information can be found on the official Sonarqube and Sonarqube Docker pages
A Swagger API documentation can be found here once the project is running (locally) on the DEV environment.
Note that only authenticated users can reach the Swagger API documentation. So, when a redirect from the swagger URL above to the Keycloak login page occurs, use the usual credentials.
Username: nilsign
Password: root
- RestAPI extensions depending on the concrete FE needs
- RestAPI Request Error Handling
- Unit tests
- Integration tests