├── .gitignore ├── README.adoc ├── chapter02 ├── 01 - Generated project │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── springbook │ │ │ │ └── application │ │ │ │ └── Application.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── springbook │ │ └── application │ │ └── ApplicationTests.java └── 02 - Logging config │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── springbook │ │ │ └── application │ │ │ └── Application.java │ └── resources │ │ ├── application.properties │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── springbook │ │ └── application │ │ └── ApplicationTests.java │ └── resources │ └── logback-test.xml ├── chapter03 └── 01 - Generated project │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ └── CopsbootApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── copsboot │ └── CopsbootApplicationTests.java ├── chapter04 ├── 01 - User domain │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ └── user │ │ │ │ ├── User.java │ │ │ │ └── UserRole.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ └── CopsbootApplicationTests.java │ │ └── resources │ │ └── logback-test.xml ├── 02 - User with JPA │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ └── user │ │ │ │ ├── User.java │ │ │ │ ├── UserRepository.java │ │ │ │ └── UserRole.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ └── user │ │ │ └── UserRepositoryTest.java │ │ └── resources │ │ └── logback-test.xml └── 03 - User with JPA refactored │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── copsboot │ │ │ ├── CopsbootApplication.java │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ └── user │ │ │ │ ├── User.java │ │ │ │ ├── UserId.java │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ └── UserRole.java │ │ │ ├── orm │ │ │ └── jpa │ │ │ │ ├── AbstractEntity.java │ │ │ │ ├── AbstractEntityId.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityId.java │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ └── UniqueIdGenerator.java │ │ │ └── util │ │ │ └── ArtifactForFramework.java │ └── resources │ │ ├── application.properties │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── example │ │ └── copsboot │ │ ├── CopsbootApplicationTests.java │ │ └── user │ │ └── UserRepositoryTest.java │ └── resources │ └── logback-test.xml ├── chapter05 └── 01 - Oauth2 │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── copsboot │ │ │ ├── CopsbootApplication.java │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ ├── infrastructure │ │ │ │ ├── SpringProfiles.java │ │ │ │ └── security │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ └── user │ │ │ │ ├── User.java │ │ │ │ ├── UserId.java │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ ├── UserRole.java │ │ │ │ └── web │ │ │ │ └── UserRestController.java │ │ │ ├── orm │ │ │ └── jpa │ │ │ │ ├── AbstractEntity.java │ │ │ │ ├── AbstractEntityId.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityId.java │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ └── UniqueIdGenerator.java │ │ │ └── util │ │ │ └── ArtifactForFramework.java │ └── resources │ │ ├── application.properties │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── example │ │ └── copsboot │ │ ├── CopsbootApplicationTests.java │ │ └── user │ │ ├── UserRepositoryTest.java │ │ └── web │ │ └── UserRestControllerTest.java │ └── resources │ └── logback-test.xml ├── chapter06 ├── 01 - User rest controller │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ └── logback-test.xml ├── 02 - user role │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ └── logback-test.xml ├── 03 - Writing API Documentation │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ └── Copsboot REST API Guide.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ └── logback-test.xml ├── 04 - Generating snippets │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ ├── Copsboot REST API Guide.adoc │ │ │ └── _users.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ ├── UserRestControllerDocumentation.java │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ └── logback-test.xml └── 05 - Refactoring │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── docs │ └── asciidoc │ │ ├── Copsboot REST API Guide.adoc │ │ └── _users.adoc │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── copsboot │ │ │ ├── CopsbootApplication.java │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ ├── infrastructure │ │ │ │ ├── SpringProfiles.java │ │ │ │ └── security │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ └── user │ │ │ │ ├── AuthServerId.java │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ ├── CreateUserParameters.java │ │ │ │ ├── User.java │ │ │ │ ├── UserId.java │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ ├── UserRole.java │ │ │ │ ├── UserService.java │ │ │ │ └── web │ │ │ │ ├── CreateUserRequest.java │ │ │ │ ├── UserDto.java │ │ │ │ └── UserRestController.java │ │ │ ├── orm │ │ │ └── jpa │ │ │ │ ├── AbstractEntity.java │ │ │ │ ├── AbstractEntityId.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityId.java │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ └── UniqueIdGenerator.java │ │ │ └── util │ │ │ └── ArtifactForFramework.java │ └── resources │ │ ├── application.properties │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── example │ │ └── copsboot │ │ ├── CopsbootApplicationTests.java │ │ ├── infrastructure │ │ └── test │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ └── CopsbootControllerTest.java │ │ └── user │ │ ├── UserRepositoryTest.java │ │ └── web │ │ ├── UserRestControllerDocumentation.java │ │ └── UserRestControllerTest.java │ └── resources │ └── logback-test.xml ├── chapter07 ├── 01 - postgresql │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ ├── Copsboot REST API Guide.adoc │ │ │ └── _users.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application-local.properties │ │ │ ├── application.properties │ │ │ ├── db │ │ │ └── migration │ │ │ │ └── V1.0.0.1__users.sql │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ ├── infrastructure │ │ │ └── test │ │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ │ └── CopsbootControllerTest.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ ├── UserRestControllerDocumentation.java │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ └── logback-test.xml └── 02 - testcontainers │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── docs │ └── asciidoc │ │ ├── Copsboot REST API Guide.adoc │ │ └── _users.adoc │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── copsboot │ │ │ ├── CopsbootApplication.java │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ ├── infrastructure │ │ │ │ ├── SpringProfiles.java │ │ │ │ └── security │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ └── user │ │ │ │ ├── AuthServerId.java │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ ├── CreateUserParameters.java │ │ │ │ ├── User.java │ │ │ │ ├── UserId.java │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ ├── UserRole.java │ │ │ │ ├── UserService.java │ │ │ │ └── web │ │ │ │ ├── CreateUserRequest.java │ │ │ │ ├── UserDto.java │ │ │ │ └── UserRestController.java │ │ │ ├── orm │ │ │ └── jpa │ │ │ │ ├── AbstractEntity.java │ │ │ │ ├── AbstractEntityId.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityId.java │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ └── UniqueIdGenerator.java │ │ │ └── util │ │ │ └── ArtifactForFramework.java │ └── resources │ │ ├── application-local.properties │ │ ├── application.properties │ │ ├── db │ │ └── migration │ │ │ └── V1.0.0.1__users.sql │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── example │ │ └── copsboot │ │ ├── CopsbootApplicationTests.java │ │ ├── infrastructure │ │ └── test │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ └── CopsbootControllerTest.java │ │ └── user │ │ ├── UserRepositoryTest.java │ │ └── web │ │ ├── UserRestControllerDocumentation.java │ │ └── UserRestControllerTest.java │ └── resources │ ├── application-integration-test.properties │ ├── application-repository-test.properties │ └── logback-test.xml ├── chapter08 ├── 01 - builtin │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ ├── Copsboot REST API Guide.adoc │ │ │ └── _users.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ ├── mvc │ │ │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application-local.properties │ │ │ ├── application.properties │ │ │ ├── db │ │ │ └── migration │ │ │ │ └── V1.0.0.1__users.sql │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ ├── infrastructure │ │ │ └── test │ │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ │ └── CopsbootControllerTest.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ ├── UserRestControllerDocumentation.java │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ ├── application-integration-test.properties │ │ ├── application-repository-test.properties │ │ └── logback-test.xml ├── 02 - customfield │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ ├── Copsboot REST API Guide.adoc │ │ │ └── _users.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ ├── mvc │ │ │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ ├── report │ │ │ │ │ ├── CreateReportParameters.java │ │ │ │ │ ├── Report.java │ │ │ │ │ ├── ReportId.java │ │ │ │ │ ├── ReportRepository.java │ │ │ │ │ ├── ReportRepositoryCustom.java │ │ │ │ │ ├── ReportRepositoryImpl.java │ │ │ │ │ ├── ReportService.java │ │ │ │ │ └── web │ │ │ │ │ │ ├── CreateReportRequest.java │ │ │ │ │ │ ├── ReportDto.java │ │ │ │ │ │ └── ReportRestController.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserIdAttributeConverter.java │ │ │ │ │ ├── UserNotFoundException.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application-local.properties │ │ │ ├── application.properties │ │ │ ├── db │ │ │ └── migration │ │ │ │ ├── V1.0.0.1__users.sql │ │ │ │ └── V1.0.0.2__reports.sql │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ ├── infrastructure │ │ │ └── test │ │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ │ └── CopsbootControllerTest.java │ │ │ ├── report │ │ │ └── web │ │ │ │ └── ReportRestControllerTest.java │ │ │ └── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ ├── UserRestControllerDocumentation.java │ │ │ └── UserRestControllerTest.java │ │ └── resources │ │ ├── application-integration-test.properties │ │ ├── application-repository-test.properties │ │ └── logback-test.xml ├── 03 - customfieldfinal │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ ├── Copsboot REST API Guide.adoc │ │ │ └── _users.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ ├── mvc │ │ │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ ├── report │ │ │ │ │ ├── CreateReportParameters.java │ │ │ │ │ ├── Report.java │ │ │ │ │ ├── ReportId.java │ │ │ │ │ ├── ReportRepository.java │ │ │ │ │ ├── ReportRepositoryCustom.java │ │ │ │ │ ├── ReportRepositoryImpl.java │ │ │ │ │ ├── ReportService.java │ │ │ │ │ └── web │ │ │ │ │ │ ├── CreateReportRequest.java │ │ │ │ │ │ ├── ReportDescriptionValidator.java │ │ │ │ │ │ ├── ReportDto.java │ │ │ │ │ │ ├── ReportRestController.java │ │ │ │ │ │ └── ValidReportDescription.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserIdAttributeConverter.java │ │ │ │ │ ├── UserNotFoundException.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application-local.properties │ │ │ ├── application.properties │ │ │ ├── db │ │ │ └── migration │ │ │ │ ├── V1.0.0.1__users.sql │ │ │ │ └── V1.0.0.2__reports.sql │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ ├── infrastructure │ │ │ └── test │ │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ │ └── CopsbootControllerTest.java │ │ │ ├── report │ │ │ └── web │ │ │ │ ├── ReportDescriptionValidatorTest.java │ │ │ │ └── ReportRestControllerTest.java │ │ │ ├── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ │ ├── UserRestControllerDocumentation.java │ │ │ │ └── UserRestControllerTest.java │ │ │ └── util │ │ │ └── test │ │ │ └── ConstraintViolationSetAssert.java │ │ └── resources │ │ ├── application-integration-test.properties │ │ ├── application-repository-test.properties │ │ └── logback-test.xml ├── 04 - objectvalidation │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── docs │ │ └── asciidoc │ │ │ ├── Copsboot REST API Guide.adoc │ │ │ └── _users.adoc │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── copsboot │ │ │ │ ├── CopsbootApplication.java │ │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SpringProfiles.java │ │ │ │ │ ├── mvc │ │ │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ │ │ └── security │ │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ ├── report │ │ │ │ │ ├── CreateReportParameters.java │ │ │ │ │ ├── Report.java │ │ │ │ │ ├── ReportId.java │ │ │ │ │ ├── ReportRepository.java │ │ │ │ │ ├── ReportRepositoryCustom.java │ │ │ │ │ ├── ReportRepositoryImpl.java │ │ │ │ │ ├── ReportService.java │ │ │ │ │ └── web │ │ │ │ │ │ ├── CreateReportRequest.java │ │ │ │ │ │ ├── CreateReportRequestValidator.java │ │ │ │ │ │ ├── ReportDescriptionValidator.java │ │ │ │ │ │ ├── ReportDto.java │ │ │ │ │ │ ├── ReportRestController.java │ │ │ │ │ │ ├── ValidCreateReportRequest.java │ │ │ │ │ │ └── ValidReportDescription.java │ │ │ │ └── user │ │ │ │ │ ├── AuthServerId.java │ │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ │ ├── CreateUserParameters.java │ │ │ │ │ ├── User.java │ │ │ │ │ ├── UserId.java │ │ │ │ │ ├── UserIdAttributeConverter.java │ │ │ │ │ ├── UserNotFoundException.java │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ │ ├── UserRole.java │ │ │ │ │ ├── UserService.java │ │ │ │ │ └── web │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── UserDto.java │ │ │ │ │ └── UserRestController.java │ │ │ │ ├── orm │ │ │ │ └── jpa │ │ │ │ │ ├── AbstractEntity.java │ │ │ │ │ ├── AbstractEntityId.java │ │ │ │ │ ├── Entity.java │ │ │ │ │ ├── EntityId.java │ │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ │ └── UniqueIdGenerator.java │ │ │ │ └── util │ │ │ │ └── ArtifactForFramework.java │ │ └── resources │ │ │ ├── application-local.properties │ │ │ ├── application.properties │ │ │ ├── db │ │ │ └── migration │ │ │ │ ├── V1.0.0.1__users.sql │ │ │ │ └── V1.0.0.2__reports.sql │ │ │ └── logback-spring.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copsboot │ │ │ ├── CopsbootApplicationTests.java │ │ │ ├── infrastructure │ │ │ └── test │ │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ │ └── CopsbootControllerTest.java │ │ │ ├── report │ │ │ └── web │ │ │ │ ├── CreateReportRequestValidatorTest.java │ │ │ │ ├── ReportDescriptionValidatorTest.java │ │ │ │ └── ReportRestControllerTest.java │ │ │ ├── user │ │ │ ├── UserRepositoryTest.java │ │ │ └── web │ │ │ │ ├── UserRestControllerDocumentation.java │ │ │ │ └── UserRestControllerTest.java │ │ │ └── util │ │ │ └── test │ │ │ └── ConstraintViolationSetAssert.java │ │ └── resources │ │ ├── application-integration-test.properties │ │ ├── application-repository-test.properties │ │ └── logback-test.xml └── 05 - validatorspringbean │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── docker-compose.yaml │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── docs │ └── asciidoc │ │ ├── Copsboot REST API Guide.adoc │ │ └── _users.adoc │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── copsboot │ │ │ ├── CopsbootApplication.java │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ ├── infrastructure │ │ │ │ ├── SpringProfiles.java │ │ │ │ ├── mvc │ │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ │ └── security │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ ├── report │ │ │ │ ├── CreateReportParameters.java │ │ │ │ ├── Report.java │ │ │ │ ├── ReportId.java │ │ │ │ ├── ReportRepository.java │ │ │ │ ├── ReportRepositoryCustom.java │ │ │ │ ├── ReportRepositoryImpl.java │ │ │ │ ├── ReportService.java │ │ │ │ └── web │ │ │ │ │ ├── CreateReportRequest.java │ │ │ │ │ ├── CreateReportRequestValidator.java │ │ │ │ │ ├── ReportDescriptionValidator.java │ │ │ │ │ ├── ReportDto.java │ │ │ │ │ ├── ReportRestController.java │ │ │ │ │ ├── ValidCreateReportRequest.java │ │ │ │ │ └── ValidReportDescription.java │ │ │ └── user │ │ │ │ ├── AuthServerId.java │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ ├── CreateUserParameters.java │ │ │ │ ├── User.java │ │ │ │ ├── UserId.java │ │ │ │ ├── UserIdAttributeConverter.java │ │ │ │ ├── UserNotFoundException.java │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ ├── UserRole.java │ │ │ │ ├── UserService.java │ │ │ │ └── web │ │ │ │ ├── CreateUserRequest.java │ │ │ │ ├── CreateUserRequestValidator.java │ │ │ │ ├── UserDto.java │ │ │ │ ├── UserRestController.java │ │ │ │ └── ValidCreateUserRequest.java │ │ │ ├── orm │ │ │ └── jpa │ │ │ │ ├── AbstractEntity.java │ │ │ │ ├── AbstractEntityId.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityId.java │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ └── UniqueIdGenerator.java │ │ │ └── util │ │ │ └── ArtifactForFramework.java │ └── resources │ │ ├── application-local.properties │ │ ├── application.properties │ │ ├── db │ │ └── migration │ │ │ ├── V1.0.0.1__users.sql │ │ │ └── V1.0.0.2__reports.sql │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── example │ │ └── copsboot │ │ ├── CopsbootApplicationTests.java │ │ ├── infrastructure │ │ └── test │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ └── CopsbootControllerTest.java │ │ ├── report │ │ └── web │ │ │ ├── CreateReportRequestValidatorTest.java │ │ │ ├── ReportDescriptionValidatorTest.java │ │ │ └── ReportRestControllerTest.java │ │ ├── user │ │ ├── UserRepositoryTest.java │ │ └── web │ │ │ ├── CreateUserRequestValidatorTest.java │ │ │ ├── UserRestControllerDocumentation.java │ │ │ └── UserRestControllerTest.java │ │ └── util │ │ └── test │ │ └── ConstraintViolationSetAssert.java │ └── resources │ ├── application-integration-test.properties │ ├── application-repository-test.properties │ └── logback-test.xml └── chapter09 ├── 01 - fileupload ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── docker-compose.yaml ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── docs │ └── asciidoc │ │ ├── Copsboot REST API Guide.adoc │ │ └── _users.adoc │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── copsboot │ │ │ ├── CopsbootApplication.java │ │ │ ├── CopsbootApplicationConfiguration.java │ │ │ ├── infrastructure │ │ │ │ ├── SpringProfiles.java │ │ │ │ ├── mvc │ │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ │ └── security │ │ │ │ │ └── WebSecurityConfiguration.java │ │ │ ├── report │ │ │ │ ├── CreateReportParameters.java │ │ │ │ ├── Report.java │ │ │ │ ├── ReportId.java │ │ │ │ ├── ReportRepository.java │ │ │ │ ├── ReportRepositoryCustom.java │ │ │ │ ├── ReportRepositoryImpl.java │ │ │ │ ├── ReportService.java │ │ │ │ └── web │ │ │ │ │ ├── CreateReportRequest.java │ │ │ │ │ ├── CreateReportRequestValidator.java │ │ │ │ │ ├── ReportDescriptionValidator.java │ │ │ │ │ ├── ReportDto.java │ │ │ │ │ ├── ReportRestController.java │ │ │ │ │ ├── ValidCreateReportRequest.java │ │ │ │ │ └── ValidReportDescription.java │ │ │ └── user │ │ │ │ ├── AuthServerId.java │ │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ │ ├── CreateUserParameters.java │ │ │ │ ├── User.java │ │ │ │ ├── UserId.java │ │ │ │ ├── UserIdAttributeConverter.java │ │ │ │ ├── UserNotFoundException.java │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ ├── UserRepositoryImpl.java │ │ │ │ ├── UserRole.java │ │ │ │ ├── UserService.java │ │ │ │ └── web │ │ │ │ ├── CreateUserRequest.java │ │ │ │ ├── CreateUserRequestValidator.java │ │ │ │ ├── UserDto.java │ │ │ │ ├── UserRestController.java │ │ │ │ └── ValidCreateUserRequest.java │ │ │ ├── orm │ │ │ └── jpa │ │ │ │ ├── AbstractEntity.java │ │ │ │ ├── AbstractEntityId.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityId.java │ │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ │ └── UniqueIdGenerator.java │ │ │ └── util │ │ │ └── ArtifactForFramework.java │ └── resources │ │ ├── application-local.properties │ │ ├── application.properties │ │ ├── db │ │ └── migration │ │ │ ├── V1.0.0.1__users.sql │ │ │ └── V1.0.0.2__reports.sql │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── example │ │ └── copsboot │ │ ├── CopsbootApplicationTests.java │ │ ├── infrastructure │ │ └── test │ │ │ ├── CopsbootControllerDocumentationTest.java │ │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ │ └── CopsbootControllerTest.java │ │ ├── report │ │ └── web │ │ │ ├── CreateReportRequestValidatorTest.java │ │ │ ├── ReportDescriptionValidatorTest.java │ │ │ └── ReportRestControllerTest.java │ │ ├── user │ │ ├── UserRepositoryTest.java │ │ └── web │ │ │ ├── CreateUserRequestValidatorTest.java │ │ │ ├── UserRestControllerDocumentation.java │ │ │ └── UserRestControllerTest.java │ │ └── util │ │ └── test │ │ └── ConstraintViolationSetAssert.java │ └── resources │ ├── application-integration-test.properties │ ├── application-repository-test.properties │ └── logback-test.xml └── 02 - validation ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── docker-compose.yaml ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── docs └── asciidoc │ ├── Copsboot REST API Guide.adoc │ └── _users.adoc ├── main ├── java │ └── com │ │ └── example │ │ ├── copsboot │ │ ├── CopsbootApplication.java │ │ ├── CopsbootApplicationConfiguration.java │ │ ├── infrastructure │ │ │ ├── SpringProfiles.java │ │ │ ├── mvc │ │ │ │ ├── FieldErrorResponse.java │ │ │ │ └── RestControllerExceptionHandler.java │ │ │ └── security │ │ │ │ └── WebSecurityConfiguration.java │ │ ├── report │ │ │ ├── CreateReportParameters.java │ │ │ ├── Report.java │ │ │ ├── ReportId.java │ │ │ ├── ReportRepository.java │ │ │ ├── ReportRepositoryCustom.java │ │ │ ├── ReportRepositoryImpl.java │ │ │ ├── ReportService.java │ │ │ └── web │ │ │ │ ├── CreateReportRequest.java │ │ │ │ ├── CreateReportRequestValidator.java │ │ │ │ ├── ReportDescriptionValidator.java │ │ │ │ ├── ReportDto.java │ │ │ │ ├── ReportRestController.java │ │ │ │ ├── ValidCreateReportRequest.java │ │ │ │ └── ValidReportDescription.java │ │ └── user │ │ │ ├── AuthServerId.java │ │ │ ├── AuthServerIdAttributeConverter.java │ │ │ ├── CreateUserParameters.java │ │ │ ├── User.java │ │ │ ├── UserId.java │ │ │ ├── UserIdAttributeConverter.java │ │ │ ├── UserNotFoundException.java │ │ │ ├── UserRepository.java │ │ │ ├── UserRepositoryCustom.java │ │ │ ├── UserRepositoryImpl.java │ │ │ ├── UserRole.java │ │ │ ├── UserService.java │ │ │ └── web │ │ │ ├── CreateUserRequest.java │ │ │ ├── CreateUserRequestValidator.java │ │ │ ├── UserDto.java │ │ │ ├── UserRestController.java │ │ │ └── ValidCreateUserRequest.java │ │ ├── orm │ │ └── jpa │ │ │ ├── AbstractEntity.java │ │ │ ├── AbstractEntityId.java │ │ │ ├── Entity.java │ │ │ ├── EntityId.java │ │ │ ├── InMemoryUniqueIdGenerator.java │ │ │ └── UniqueIdGenerator.java │ │ └── util │ │ └── ArtifactForFramework.java └── resources │ ├── application-local.properties │ ├── application.properties │ ├── db │ └── migration │ │ ├── V1.0.0.1__users.sql │ │ └── V1.0.0.2__reports.sql │ └── logback-spring.xml └── test ├── java └── com │ └── example │ └── copsboot │ ├── CopsbootApplicationTests.java │ ├── infrastructure │ └── test │ │ ├── CopsbootControllerDocumentationTest.java │ │ ├── CopsbootControllerDocumentationTestConfiguration.java │ │ └── CopsbootControllerTest.java │ ├── report │ └── web │ │ ├── CreateReportRequestValidatorTest.java │ │ ├── KeycloakAdminClientFacade.java │ │ ├── ReportDescriptionValidatorTest.java │ │ ├── ReportRestControllerIntegrationTest.java │ │ └── ReportRestControllerTest.java │ ├── user │ ├── UserRepositoryTest.java │ └── web │ │ ├── CreateUserRequestValidatorTest.java │ │ ├── UserRestControllerDocumentation.java │ │ └── UserRestControllerTest.java │ └── util │ └── test │ └── ConstraintViolationSetAssert.java └── resources ├── application-integration-test.properties ├── application-repository-test.properties ├── jwt-officer.json └── logback-test.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.iml 3 | .idea 4 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Source Code to 'Practical Guide to Building an API Back End with Spring Boot' 2 | 3 | This repository contains the source code for the InfoQ mini-book 'Practical Guide to Building an API Back End with Spring Boot'. See https://www.infoq.com/minibooks/spring-boot-building-api-backend for the free download of the book. 4 | 5 | This branch contains the sources for the latest version of the book, targeting Spring Boot 3. 6 | 7 | If you want to view the sources for the previous edition of the book targeting Spring Boot 2, see the https://github.com/wimdeblauwe/spring-boot-building-api-backend/tree/release/1.x[release/1.x] branch. 8 | -------------------------------------------------------------------------------- /chapter02/01 - Generated project/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter02/01 - Generated project/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter02/01 - Generated project/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter02/01 - Generated project/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter02/01 - Generated project/src/main/java/com/springbook/application/Application.java: -------------------------------------------------------------------------------- 1 | package com.springbook.application; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | // tag::class[] 7 | @SpringBootApplication //<1> 8 | public class Application { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(Application.class, args); 12 | } 13 | } 14 | // end::class[] 15 | -------------------------------------------------------------------------------- /chapter02/01 - Generated project/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /chapter02/01 - Generated project/src/test/java/com/springbook/application/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.springbook.application; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter02/02 - Logging config/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter02/02 - Logging config/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter02/02 - Logging config/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter02/02 - Logging config/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter02/02 - Logging config/src/main/java/com/springbook/application/Application.java: -------------------------------------------------------------------------------- 1 | package com.springbook.application; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | // tag::class[] 7 | @SpringBootApplication //<1> 8 | public class Application { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(Application.class, args); 12 | } 13 | } 14 | // end::class[] 15 | -------------------------------------------------------------------------------- /chapter02/02 - Logging config/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter02/02 - Logging config/src/main/resources/application.properties -------------------------------------------------------------------------------- /chapter02/02 - Logging config/src/test/java/com/springbook/application/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.springbook.application; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter03/01 - Generated project/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter03/01 - Generated project/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter03/01 - Generated project/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter03/01 - Generated project/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter03/01 - Generated project/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter03/01 - Generated project/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /chapter03/01 - Generated project/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter04/01 - User domain/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter04/01 - User domain/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter04/01 - User domain/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter04/01 - User domain/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter04/01 - User domain/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter04/01 - User domain/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter04/01 - User domain/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /chapter04/01 - User domain/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter04/02 - User with JPA/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.UUID; 6 | 7 | public interface UserRepository extends CrudRepository { 8 | } 9 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /chapter04/02 - User with JPA/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter04/03 - User with JPA refactored/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import java.util.UUID; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | public class CopsbootApplicationConfiguration { 11 | 12 | @Bean 13 | public UniqueIdGenerator uniqueIdGenerator() { 14 | return new InMemoryUniqueIdGenerator(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.UUID; 6 | //tag::class[] 7 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 8 | } 9 | //end::class[] 10 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /chapter04/03 - User with JPA refactored/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter05/01 - Oauth2/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | identity: 4 | image: 'quay.io/keycloak/keycloak:22.0.1' 5 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 6 | ports: 7 | - '8180:8080' 8 | environment: 9 | KEYCLOAK_LOGLEVEL: 'INFO' 10 | KEYCLOAK_ADMIN: 'admin' 11 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 12 | KC_HOSTNAME: 'localhost' 13 | KC_HEALTH_ENABLED: 'true' 14 | KC_METRICS_ENABLED: 'true' 15 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | } 10 | //end::class[] 11 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | -------------------------------------------------------------------------------- /chapter05/01 - Oauth2/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter06/01 - User rest controller/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | identity: 4 | image: 'quay.io/keycloak/keycloak:22.0.1' 5 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 6 | ports: 7 | - '8180:8080' 8 | environment: 9 | KEYCLOAK_LOGLEVEL: 'INFO' 10 | KEYCLOAK_ADMIN: 'admin' 11 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 12 | KC_HOSTNAME: 'localhost' 13 | KC_HEALTH_ENABLED: 'true' 14 | KC_METRICS_ENABLED: 'true' 15 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | -------------------------------------------------------------------------------- /chapter06/01 - User rest controller/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/02 - user role/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter06/02 - user role/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter06/02 - user role/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter06/02 - user role/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter06/02 - user role/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | identity: 4 | image: 'quay.io/keycloak/keycloak:22.0.1' 5 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 6 | ports: 7 | - '8180:8080' 8 | environment: 9 | KEYCLOAK_LOGLEVEL: 'INFO' 10 | KEYCLOAK_ADMIN: 'admin' 11 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 12 | KC_HOSTNAME: 'localhost' 13 | KC_HEALTH_ENABLED: 'true' 14 | KC_METRICS_ENABLED: 'true' 15 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | -------------------------------------------------------------------------------- /chapter06/02 - user role/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter06/03 - Writing API Documentation/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | identity: 4 | image: 'quay.io/keycloak/keycloak:22.0.1' 5 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 6 | ports: 7 | - '8180:8080' 8 | environment: 9 | KEYCLOAK_LOGLEVEL: 'INFO' 10 | KEYCLOAK_ADMIN: 'admin' 11 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 12 | KC_HOSTNAME: 'localhost' 13 | KC_HEALTH_ENABLED: 'true' 14 | KC_METRICS_ENABLED: 'true' 15 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | -------------------------------------------------------------------------------- /chapter06/03 - Writing API Documentation/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter06/04 - Generating snippets/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | identity: 4 | image: 'quay.io/keycloak/keycloak:22.0.1' 5 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 6 | ports: 7 | - '8180:8080' 8 | environment: 9 | KEYCLOAK_LOGLEVEL: 'INFO' 10 | KEYCLOAK_ADMIN: 'admin' 11 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 12 | KC_HOSTNAME: 'localhost' 13 | KC_HEALTH_ENABLED: 'true' 14 | KC_METRICS_ENABLED: 'true' 15 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | -------------------------------------------------------------------------------- /chapter06/04 - Generating snippets/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter06/05 - Refactoring/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | identity: 4 | image: 'quay.io/keycloak/keycloak:22.0.1' 5 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 6 | ports: 7 | - '8180:8080' 8 | environment: 9 | KEYCLOAK_LOGLEVEL: 'INFO' 10 | KEYCLOAK_ADMIN: 'admin' 11 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 12 | KC_HOSTNAME: 'localhost' 13 | KC_HEALTH_ENABLED: 'true' 14 | KC_METRICS_ENABLED: 'true' 15 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | -------------------------------------------------------------------------------- /chapter06/05 - Refactoring/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter07/01 - postgresql/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter07/01 - postgresql/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | db: 4 | image: 'postgres:16.0' 5 | ports: 6 | - 5432:5432 7 | environment: 8 | POSTGRES_PASSWORD: my-postgres-db-pwd 9 | identity: 10 | image: 'quay.io/keycloak/keycloak:22.0.1' 11 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 12 | ports: 13 | - '8180:8080' 14 | environment: 15 | KEYCLOAK_LOGLEVEL: 'INFO' 16 | KEYCLOAK_ADMIN: 'admin' 17 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 18 | KC_HOSTNAME: 'localhost' 19 | KC_HEALTH_ENABLED: 'true' 20 | KC_METRICS_ENABLED: 'true' 21 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | 10 | private SpringProfiles() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter07/01 - postgresql/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CopsbootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter07/02 - testcontainers/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter07/02 - testcontainers/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter08/01 - builtin/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter08/01 - builtin/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | db: 4 | image: 'postgres:16.0' 5 | ports: 6 | - 5432:5432 7 | environment: 8 | POSTGRES_PASSWORD: my-postgres-db-pwd 9 | identity: 10 | image: 'quay.io/keycloak/keycloak:22.0.1' 11 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 12 | ports: 13 | - '8180:8080' 14 | environment: 15 | KEYCLOAK_LOGLEVEL: 'INFO' 16 | KEYCLOAK_ADMIN: 'admin' 17 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 18 | KC_HOSTNAME: 'localhost' 19 | KC_HEALTH_ENABLED: 'true' 20 | KC_METRICS_ENABLED: 'true' 21 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | 3 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 4 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 5 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 6 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/01 - builtin/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter08/02 - customfield/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter08/02 - customfield/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | db: 4 | image: 'postgres:16.0' 5 | ports: 6 | - 5432:5432 7 | environment: 8 | POSTGRES_PASSWORD: my-postgres-db-pwd 9 | identity: 10 | image: 'quay.io/keycloak/keycloak:22.0.1' 11 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 12 | ports: 13 | - '8180:8080' 14 | environment: 15 | KEYCLOAK_LOGLEVEL: 'INFO' 16 | KEYCLOAK_ADMIN: 'admin' 17 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 18 | KC_HOSTNAME: 'localhost' 19 | KC_HEALTH_ENABLED: 'true' 20 | KC_METRICS_ENABLED: 'true' 21 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/report/CreateReportParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserId; 4 | 5 | import java.time.Instant; 6 | 7 | public record CreateReportParameters(UserId userId, Instant dateTime, String description) { 8 | } 9 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/report/ReportId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | import com.example.util.ArtifactForFramework; 5 | 6 | import java.util.UUID; 7 | 8 | public class ReportId extends AbstractEntityId { 9 | @ArtifactForFramework 10 | protected ReportId() { 11 | } 12 | 13 | public ReportId(UUID id) { 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/report/ReportRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserRepositoryCustom; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface ReportRepository extends CrudRepository, ReportRepositoryCustom { 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/report/ReportRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | public interface ReportRepositoryCustom { 4 | ReportId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/report/ReportRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class ReportRepositoryImpl implements ReportRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public ReportRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public ReportId nextId() { 16 | return new ReportId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/report/web/CreateReportRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report.web; 2 | 3 | import com.example.copsboot.report.CreateReportParameters; 4 | import com.example.copsboot.user.UserId; 5 | 6 | import java.time.Instant; 7 | 8 | public record CreateReportRequest(Instant dateTime, String description) { 9 | public CreateReportParameters toParameters(UserId userId) { 10 | return new CreateReportParameters(userId, dateTime, description); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | 3 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 4 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 5 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 6 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/main/resources/db/migration/V1.0.0.2__reports.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE report 2 | ( 3 | date_time TIMESTAMP(6) WITH TIME ZONE, 4 | id uuid NOT NULL, 5 | description VARCHAR(255), 6 | reporter_id uuid, 7 | PRIMARY KEY (id) 8 | ); 9 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/02 - customfield/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter08/03 - customfieldfinal/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/report/CreateReportParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserId; 4 | 5 | import java.time.Instant; 6 | 7 | public record CreateReportParameters(UserId userId, Instant dateTime, String description) { 8 | } 9 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/report/ReportId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | import com.example.util.ArtifactForFramework; 5 | 6 | import java.util.UUID; 7 | 8 | public class ReportId extends AbstractEntityId { 9 | @ArtifactForFramework 10 | protected ReportId() { 11 | } 12 | 13 | public ReportId(UUID id) { 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/report/ReportRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserRepositoryCustom; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface ReportRepository extends CrudRepository, ReportRepositoryCustom { 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/report/ReportRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | public interface ReportRepositoryCustom { 4 | ReportId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/report/ReportRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class ReportRepositoryImpl implements ReportRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public ReportRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public ReportId nextId() { 16 | return new ReportId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/report/web/CreateReportRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report.web; 2 | 3 | import com.example.copsboot.report.CreateReportParameters; 4 | import com.example.copsboot.user.UserId; 5 | 6 | import java.time.Instant; 7 | 8 | public record CreateReportRequest(Instant dateTime, @ValidReportDescription String description) { 9 | public CreateReportParameters toParameters(UserId userId) { 10 | return new CreateReportParameters(userId, dateTime, description); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | 3 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 4 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 5 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 6 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/main/resources/db/migration/V1.0.0.2__reports.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE report 2 | ( 3 | date_time TIMESTAMP(6) WITH TIME ZONE, 4 | id uuid NOT NULL, 5 | description VARCHAR(255), 6 | reporter_id uuid, 7 | PRIMARY KEY (id) 8 | ); 9 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/03 - customfieldfinal/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter08/04 - objectvalidation/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/report/CreateReportParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserId; 4 | 5 | import java.time.Instant; 6 | 7 | public record CreateReportParameters(UserId userId, Instant dateTime, String description) { 8 | } 9 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/report/ReportId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | import com.example.util.ArtifactForFramework; 5 | 6 | import java.util.UUID; 7 | 8 | public class ReportId extends AbstractEntityId { 9 | @ArtifactForFramework 10 | protected ReportId() { 11 | } 12 | 13 | public ReportId(UUID id) { 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/report/ReportRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserRepositoryCustom; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface ReportRepository extends CrudRepository, ReportRepositoryCustom { 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/report/ReportRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | public interface ReportRepositoryCustom { 4 | ReportId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/report/ReportRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class ReportRepositoryImpl implements ReportRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public ReportRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public ReportId nextId() { 16 | return new ReportId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | } 11 | //end::class[] 12 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | 3 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 4 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 5 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 6 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/main/resources/db/migration/V1.0.0.2__reports.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE report 2 | ( 3 | date_time TIMESTAMP(6) WITH TIME ZONE, 4 | id uuid NOT NULL, 5 | description VARCHAR(255), 6 | reporter_id uuid, 7 | PRIMARY KEY (id) 8 | ); 9 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/04 - objectvalidation/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter08/05 - validatorspringbean/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/report/CreateReportParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserId; 4 | 5 | import java.time.Instant; 6 | 7 | public record CreateReportParameters(UserId userId, Instant dateTime, String description) { 8 | } 9 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/report/ReportId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | import com.example.util.ArtifactForFramework; 5 | 6 | import java.util.UUID; 7 | 8 | public class ReportId extends AbstractEntityId { 9 | @ArtifactForFramework 10 | protected ReportId() { 11 | } 12 | 13 | public ReportId(UUID id) { 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/report/ReportRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserRepositoryCustom; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface ReportRepository extends CrudRepository, ReportRepositoryCustom { 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/report/ReportRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | public interface ReportRepositoryCustom { 4 | ReportId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/report/ReportRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class ReportRepositoryImpl implements ReportRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public ReportRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public ReportId nextId() { 16 | return new ReportId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | 11 | Optional findByMobileToken(String mobileToken); 12 | } 13 | //end::class[] 14 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | 3 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 4 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 5 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 6 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/main/resources/db/migration/V1.0.0.2__reports.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE report 2 | ( 3 | date_time TIMESTAMP(6) WITH TIME ZONE, 4 | id uuid NOT NULL, 5 | description VARCHAR(255), 6 | reporter_id uuid, 7 | PRIMARY KEY (id) 8 | ); 9 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter08/05 - validatorspringbean/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter09/01 - fileupload/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter09/01 - fileupload/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | db: 4 | image: 'postgres:16.0' 5 | ports: 6 | - 5432:5432 7 | environment: 8 | POSTGRES_PASSWORD: my-postgres-db-pwd 9 | identity: 10 | image: 'quay.io/keycloak/keycloak:22.0.1' 11 | entrypoint: /opt/keycloak/bin/kc.sh start-dev --import-realm 12 | ports: 13 | - '8180:8080' 14 | environment: 15 | KEYCLOAK_LOGLEVEL: 'INFO' 16 | KEYCLOAK_ADMIN: 'admin' 17 | KEYCLOAK_ADMIN_PASSWORD: 'admin-secret' 18 | KC_HOSTNAME: 'localhost' 19 | KC_HEALTH_ENABLED: 'true' 20 | KC_METRICS_ENABLED: 'true' 21 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/report/CreateReportParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserId; 4 | 5 | import java.time.Instant; 6 | 7 | public record CreateReportParameters(UserId userId, Instant dateTime, String description) { 8 | } 9 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/report/ReportId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | import com.example.util.ArtifactForFramework; 5 | 6 | import java.util.UUID; 7 | 8 | public class ReportId extends AbstractEntityId { 9 | @ArtifactForFramework 10 | protected ReportId() { 11 | } 12 | 13 | public ReportId(UUID id) { 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/report/ReportRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserRepositoryCustom; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface ReportRepository extends CrudRepository, ReportRepositoryCustom { 7 | } 8 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/report/ReportRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | public interface ReportRepositoryCustom { 4 | ReportId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/report/ReportRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class ReportRepositoryImpl implements ReportRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public ReportRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public ReportId nextId() { 16 | return new ReportId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | 11 | Optional findByMobileToken(String mobileToken); 12 | } 13 | //end::class[] 14 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/copsboot 2 | 3 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 4 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 5 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 6 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/main/resources/db/migration/V1.0.0.2__reports.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE report 2 | ( 3 | date_time TIMESTAMP(6) WITH TIME ZONE, 4 | id uuid NOT NULL, 5 | description VARCHAR(255), 6 | reporter_id uuid, 7 | PRIMARY KEY (id) 8 | ); 9 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter09/01 - fileupload/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | -------------------------------------------------------------------------------- /chapter09/02 - validation/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wimdeblauwe/spring-boot-building-api-backend/7fdd3603121fe8ebe81234c232cb240974153b84/chapter09/02 - validation/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter09/02 - validation/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/docs/asciidoc/Copsboot REST API Guide.adoc: -------------------------------------------------------------------------------- 1 | = Copsboot REST API Guide 2 | :icons: font 3 | :toc: 4 | :toclevels: 2 5 | 6 | :numbered: 7 | 8 | == Introduction 9 | 10 | The Copsboot project uses a REST API for interfacing with the server. 11 | 12 | This documentation covers version {project-version} of the application. 13 | 14 | include::_users.adoc[] 15 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/CopsbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CopsbootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CopsbootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/CopsbootApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.orm.jpa.InMemoryUniqueIdGenerator; 4 | import com.example.orm.jpa.UniqueIdGenerator; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.UUID; 9 | 10 | @Configuration 11 | public class CopsbootApplicationConfiguration { 12 | 13 | @Bean 14 | public UniqueIdGenerator uniqueIdGenerator() { 15 | return new InMemoryUniqueIdGenerator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/infrastructure/SpringProfiles.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure; 2 | 3 | public final class SpringProfiles { 4 | public static final String DEV = "dev"; 5 | public static final String LOCAL = "local"; 6 | public static final String TEST = "test"; 7 | public static final String STAGING = "staging"; 8 | public static final String PROD = "prod"; 9 | public static final String REPOSITORY_TEST = "repository-test"; 10 | public static final String INTEGRATION_TEST = "integration-test"; 11 | 12 | private SpringProfiles() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/infrastructure/mvc/FieldErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.infrastructure.mvc; 2 | 3 | public record FieldErrorResponse(String fieldName, String errorMesesage) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/report/CreateReportParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserId; 4 | 5 | import java.time.Instant; 6 | 7 | public record CreateReportParameters(UserId userId, Instant dateTime, String description) { 8 | } 9 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/report/ReportId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | import com.example.util.ArtifactForFramework; 5 | 6 | import java.util.UUID; 7 | 8 | public class ReportId extends AbstractEntityId { 9 | @ArtifactForFramework 10 | protected ReportId() { 11 | } 12 | 13 | public ReportId(UUID id) { 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/report/ReportRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.copsboot.user.UserRepositoryCustom; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface ReportRepository extends CrudRepository, ReportRepositoryCustom { 7 | } 8 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/report/ReportRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | public interface ReportRepositoryCustom { 4 | ReportId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/report/ReportRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.report; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class ReportRepositoryImpl implements ReportRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public ReportRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public ReportId nextId() { 16 | return new ReportId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/AuthServerId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.util.UUID; 6 | 7 | public record AuthServerId(UUID value) { 8 | public AuthServerId { 9 | Assert.notNull(value, "The AuthServerId value should not be null"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/CreateUserParameters.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public record CreateUserParameters(AuthServerId authServerId, String email, String mobileToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/UserId.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.AbstractEntityId; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserId extends AbstractEntityId { 8 | 9 | protected UserId() { //<1> 10 | 11 | } 12 | 13 | public UserId(UUID id) { //<2> 14 | super(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import java.util.Optional; 6 | 7 | //tag::class[] 8 | public interface UserRepository extends CrudRepository, UserRepositoryCustom { 9 | Optional findByAuthServerId(AuthServerId authServerId); 10 | 11 | Optional findByMobileToken(String mobileToken); 12 | } 13 | //end::class[] 14 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public interface UserRepositoryCustom { 4 | UserId nextId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | import com.example.orm.jpa.UniqueIdGenerator; 4 | 5 | import java.util.UUID; 6 | 7 | public class UserRepositoryImpl implements UserRepositoryCustom { 8 | private final UniqueIdGenerator generator; 9 | 10 | public UserRepositoryImpl(UniqueIdGenerator generator) { 11 | this.generator = generator; 12 | } 13 | 14 | @Override 15 | public UserId nextId() { 16 | return new UserId(generator.getNextUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user; 2 | 3 | public enum UserRole { 4 | OFFICER, 5 | CAPTAIN, 6 | ADMIN 7 | } 8 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/copsboot/user/web/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot.user.web; 2 | 3 | import com.example.copsboot.user.User; 4 | 5 | import java.util.UUID; 6 | 7 | public record UserDto(UUID userId, String email, UUID authServerId, String mobileToken) { 8 | public static UserDto fromUser(User user) { 9 | return new UserDto(user.getId().getId(), 10 | user.getEmail(), 11 | user.getAuthServerId().value(), 12 | user.getMobileToken()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/orm/jpa/Entity.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | 4 | /** 5 | * Interface for entity objects. 6 | * 7 | * @param the type of {@link EntityId} that will be used in this entity 8 | */ 9 | public interface Entity { 10 | 11 | T getId(); 12 | } 13 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/orm/jpa/EntityId.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for primary keys of entities. 7 | * 8 | * @param the underlying type of the entity id 9 | */ 10 | public interface EntityId extends Serializable { 11 | 12 | T getId(); 13 | 14 | String asString(); //<1> 15 | } 16 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/orm/jpa/InMemoryUniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | import java.util.UUID; 4 | 5 | public class InMemoryUniqueIdGenerator implements UniqueIdGenerator { 6 | @Override 7 | public UUID getNextUniqueId() { 8 | return UUID.randomUUID(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/orm/jpa/UniqueIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.example.orm.jpa; 2 | 3 | public interface UniqueIdGenerator { 4 | T getNextUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/java/com/example/util/ArtifactForFramework.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | public @interface ArtifactForFramework { 4 | } 5 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | com.c4-soft.springaddons.oidc.ops[0].iss=http://localhost:8180/realms/copsboot 2 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].path=$.realm_access.roles 3 | com.c4-soft.springaddons.oidc.ops[0].authorities[0].prefix=ROLE_ 4 | 5 | spring.servlet.multipart.max-file-size=1MB 6 | spring.servlet.multipart.max-request-size=10MB 7 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/resources/db/migration/V1.0.0.1__users.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE copsboot_user 2 | ( 3 | id uuid NOT NULL PRIMARY KEY, 4 | auth_server_id uuid, 5 | email VARCHAR(255), 6 | mobile_token VARCHAR(255) 7 | ); 8 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/main/resources/db/migration/V1.0.0.2__reports.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE report 2 | ( 3 | date_time TIMESTAMP(6) WITH TIME ZONE, 4 | id uuid NOT NULL, 5 | description VARCHAR(255), 6 | reporter_id uuid, 7 | PRIMARY KEY (id) 8 | ); 9 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/test/java/com/example/copsboot/CopsbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.copsboot; 2 | 3 | import com.example.copsboot.infrastructure.SpringProfiles; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | 8 | @SpringBootTest 9 | @ActiveProfiles(SpringProfiles.INTEGRATION_TEST) 10 | class CopsbootApplicationTests { 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/test/resources/application-integration-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | 8 | #logging.level.org.springframework.security=DEBUG 9 | #logging.level.org.springframework=DEBUG 10 | -------------------------------------------------------------------------------- /chapter09/02 - validation/src/test/resources/application-repository-test.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:tc:postgresql:16://localhost/copsbootdb 2 | spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver 3 | spring.datasource.username=user 4 | spring.datasource.password=password 5 | spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect 6 | spring.jpa.hibernate.ddl-auto=validate 7 | --------------------------------------------------------------------------------