├── Chapter02 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ └── api │ ├── .gitignore │ ├── build.gradle │ └── src │ ├── main │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── api │ │ │ └── ApiApplication.kt │ └── resources │ │ └── application.properties │ └── test │ └── kotlin │ └── com │ └── journaler │ └── api │ └── ApiApplicationTests.kt ├── Chapter03 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ └── api │ ├── .gitignore │ ├── build.gradle │ └── src │ ├── main │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── api │ │ │ ├── ApiApplication.kt │ │ │ ├── controller │ │ │ ├── NoteController.kt │ │ │ └── TodoController.kt │ │ │ ├── data │ │ │ ├── Note.kt │ │ │ └── Todo.kt │ │ │ └── service │ │ │ ├── NoteService.kt │ │ │ └── TodoService.kt │ └── resources │ │ └── application.properties │ └── test │ └── kotlin │ └── com │ └── journaler │ └── api │ └── ApiApplicationTests.kt ├── Chapter04 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ └── api │ ├── .gitignore │ ├── build.gradle │ └── src │ ├── main │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── api │ │ │ ├── ApiApplication.kt │ │ │ ├── controller │ │ │ ├── NoteController.kt │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ ├── TodoController.kt │ │ │ └── TodoLaterThanRequest.kt │ │ │ ├── data │ │ │ ├── Note.kt │ │ │ ├── NoteDTO.kt │ │ │ ├── Todo.kt │ │ │ └── TodoDTO.kt │ │ │ ├── repository │ │ │ ├── NoteRepository.kt │ │ │ └── TodoRepository.kt │ │ │ └── service │ │ │ ├── NoteService.kt │ │ │ └── TodoService.kt │ └── resources │ │ └── application.properties │ └── test │ └── kotlin │ └── com │ └── journaler │ └── api │ └── ApiApplicationTests.kt ├── Chapter05 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ └── api │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ ├── main │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── api │ │ │ ├── ApiApplication.kt │ │ │ ├── controller │ │ │ ├── NoteController.kt │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ ├── TodoController.kt │ │ │ ├── TodoLaterThanRequest.kt │ │ │ └── UserController.kt │ │ │ ├── data │ │ │ ├── Note.kt │ │ │ ├── NoteDTO.kt │ │ │ ├── Todo.kt │ │ │ └── TodoDTO.kt │ │ │ ├── repository │ │ │ ├── NoteRepository.kt │ │ │ ├── TodoRepository.kt │ │ │ └── UserRepository.kt │ │ │ ├── security │ │ │ ├── Admin.kt │ │ │ ├── Member.kt │ │ │ ├── User.kt │ │ │ ├── UserDTO.kt │ │ │ ├── UserDetailsDTO.kt │ │ │ ├── WebSecurityAuthSuccessHandler.kt │ │ │ ├── WebSecurityConfiguration.kt │ │ │ └── WebSecurityEntryPoint.kt │ │ │ └── service │ │ │ ├── NoteService.kt │ │ │ ├── TodoService.kt │ │ │ └── UserService.kt │ └── resources │ │ └── application.properties │ └── test │ └── kotlin │ └── com │ └── journaler │ └── api │ ├── ApiApplicationTests.kt │ └── SecurityInitializationTest.kt ├── Chapter06 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ ├── api │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── api │ │ │ ├── ApiApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ ├── controller │ │ │ ├── NoteController.kt │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ ├── TodoController.kt │ │ │ └── TodoLaterThanRequest.kt │ │ │ ├── data │ │ │ ├── Note.kt │ │ │ ├── NoteDTO.kt │ │ │ ├── Todo.kt │ │ │ └── TodoDTO.kt │ │ │ ├── repository │ │ │ ├── NoteRepository.kt │ │ │ └── TodoRepository.kt │ │ │ ├── security │ │ │ └── WebSecurityConfiguration.kt │ │ │ └── service │ │ │ ├── NoteService.kt │ │ │ └── TodoService.kt │ │ └── resources │ │ └── bootstrap.properties │ ├── configuration │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── config │ │ │ └── ConfigApplication.kt │ │ └── resources │ │ └── application.properties │ ├── discovery │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── discovery │ │ │ ├── DiscoveryApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ └── security │ │ │ └── WebSecurityConfiguration.kt │ │ └── resources │ │ └── bootstrap.properties │ └── gateway │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ └── main │ ├── kotlin │ └── com │ │ └── journaler │ │ └── gateway │ │ ├── GatewayApplication.kt │ │ ├── SessionConfiguration.kt │ │ ├── SessionFilter.kt │ │ └── security │ │ └── WebSecurityConfiguration.kt │ └── resources │ └── bootstrap.properties ├── Chapter07 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ ├── api │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── api │ │ │ ├── ApiApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ ├── controller │ │ │ ├── NoteController.kt │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ ├── TodoController.kt │ │ │ └── TodoLaterThanRequest.kt │ │ │ ├── data │ │ │ ├── Note.kt │ │ │ ├── NoteDTO.kt │ │ │ ├── Todo.kt │ │ │ └── TodoDTO.kt │ │ │ ├── mail │ │ │ ├── MailMessage.kt │ │ │ ├── MailService.kt │ │ │ └── MailServiceImpl.kt │ │ │ ├── reactor │ │ │ ├── NotesCountNotification.kt │ │ │ ├── NotesCountNotificationConsumer.kt │ │ │ ├── NotesCountNotificationService.kt │ │ │ ├── NotesCountNotificationServiceImpl.kt │ │ │ ├── NotificationConsumer.kt │ │ │ ├── NotificationService.kt │ │ │ ├── TodosCountNotification.kt │ │ │ ├── TodosCountNotificationConsumer.kt │ │ │ ├── TodosCountNotificationService.kt │ │ │ └── TodosCountNotificationServiceImpl.kt │ │ │ ├── repository │ │ │ ├── NoteRepository.kt │ │ │ └── TodoRepository.kt │ │ │ ├── security │ │ │ └── WebSecurityConfiguration.kt │ │ │ └── service │ │ │ ├── NoteService.kt │ │ │ └── TodoService.kt │ │ └── resources │ │ └── bootstrap.properties │ ├── configuration │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── config │ │ │ └── ConfigApplication.kt │ │ └── resources │ │ └── application.properties │ ├── discovery │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── discovery │ │ │ ├── DiscoveryApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ └── security │ │ │ └── WebSecurityConfiguration.kt │ │ └── resources │ │ └── bootstrap.properties │ └── gateway │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ └── main │ ├── kotlin │ └── com │ │ └── journaler │ │ └── gateway │ │ ├── GatewayApplication.kt │ │ ├── SessionConfiguration.kt │ │ ├── SessionFilter.kt │ │ └── security │ │ └── WebSecurityConfiguration.kt │ └── resources │ └── bootstrap.properties ├── Chapter09 ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ ├── api │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── journaler │ │ │ │ └── api │ │ │ │ ├── ApiApplication.kt │ │ │ │ ├── controller │ │ │ │ ├── NoteController.kt │ │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ │ ├── TodoController.kt │ │ │ │ └── TodoLaterThanRequest.kt │ │ │ │ ├── data │ │ │ │ ├── Note.kt │ │ │ │ ├── NoteDTO.kt │ │ │ │ ├── Todo.kt │ │ │ │ └── TodoDTO.kt │ │ │ │ ├── repository │ │ │ │ ├── NoteRepository.kt │ │ │ │ └── TodoRepository.kt │ │ │ │ ├── security │ │ │ │ └── WebSecurityConfiguration.kt │ │ │ │ └── service │ │ │ │ ├── NoteService.kt │ │ │ │ └── TodoService.kt │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── journaler │ │ ├── NoteTest.kt │ │ ├── SuiteTest.kt │ │ └── TodoTest.kt │ ├── configuration │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── config │ │ │ └── ConfigApplication.kt │ │ └── resources │ │ └── application.properties │ ├── discovery │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── discovery │ │ │ ├── DiscoveryApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ └── security │ │ │ └── WebSecurityConfiguration.kt │ │ └── resources │ │ └── bootstrap.properties │ └── gateway │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ └── main │ ├── kotlin │ └── com │ │ └── journaler │ │ └── gateway │ │ ├── GatewayApplication.kt │ │ ├── SessionConfiguration.kt │ │ ├── SessionFilter.kt │ │ └── security │ │ └── WebSecurityConfiguration.kt │ └── resources │ └── bootstrap.properties ├── Chapter10 ├── ProjectA │ ├── Dependency injection │ │ ├── .gitignore │ │ └── src │ │ │ ├── ConstructorInjection.kt │ │ │ ├── FactoryInjection.kt │ │ │ ├── MusicPlayer.kt │ │ │ └── MusicPlayerIOC.kt │ └── Journaler API │ │ ├── api │ │ ├── .gitignore │ │ ├── README.md │ │ ├── build.gradle │ │ └── src │ │ │ ├── main │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── journaler │ │ │ │ │ └── api │ │ │ │ │ ├── ApiApplication.kt │ │ │ │ │ ├── controller │ │ │ │ │ ├── NoteController.kt │ │ │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ │ │ ├── TodoController.kt │ │ │ │ │ └── TodoLaterThanRequest.kt │ │ │ │ │ ├── data │ │ │ │ │ ├── Note.kt │ │ │ │ │ ├── NoteDTO.kt │ │ │ │ │ ├── Todo.kt │ │ │ │ │ └── TodoDTO.kt │ │ │ │ │ ├── repository │ │ │ │ │ ├── NoteRepository.kt │ │ │ │ │ └── TodoRepository.kt │ │ │ │ │ ├── security │ │ │ │ │ └── WebSecurityConfiguration.kt │ │ │ │ │ └── service │ │ │ │ │ ├── NoteService.kt │ │ │ │ │ └── TodoService.kt │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── kotlin │ │ │ └── com │ │ │ └── journaler │ │ │ ├── NoteTest.kt │ │ │ ├── SuiteTest.kt │ │ │ └── TodoTest.kt │ │ ├── configuration │ │ ├── .gitignore │ │ ├── README.md │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── journaler │ │ │ │ └── config │ │ │ │ └── ConfigApplication.kt │ │ │ └── resources │ │ │ └── application.properties │ │ ├── discovery │ │ ├── .gitignore │ │ ├── README.md │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── journaler │ │ │ │ └── discovery │ │ │ │ ├── DiscoveryApplication.kt │ │ │ │ ├── SessionConfiguration.kt │ │ │ │ └── security │ │ │ │ └── WebSecurityConfiguration.kt │ │ │ └── resources │ │ │ └── bootstrap.properties │ │ └── gateway │ │ ├── .gitignore │ │ ├── README.md │ │ ├── build.gradle │ │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── gateway │ │ │ ├── GatewayApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ ├── SessionFilter.kt │ │ │ └── security │ │ │ └── WebSecurityConfiguration.kt │ │ └── resources │ │ └── bootstrap.properties └── ProjectB │ ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt │ └── Journaler API │ ├── api │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── journaler │ │ │ │ └── api │ │ │ │ ├── ApiApplication.kt │ │ │ │ ├── controller │ │ │ │ ├── NoteController.kt │ │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ │ ├── TodoController.kt │ │ │ │ └── TodoLaterThanRequest.kt │ │ │ │ ├── data │ │ │ │ ├── Note.kt │ │ │ │ ├── NoteDTO.kt │ │ │ │ ├── Todo.kt │ │ │ │ └── TodoDTO.kt │ │ │ │ ├── repository │ │ │ │ ├── NoteRepository.kt │ │ │ │ └── TodoRepository.kt │ │ │ │ ├── security │ │ │ │ └── WebSecurityConfiguration.kt │ │ │ │ └── service │ │ │ │ ├── NoteService.kt │ │ │ │ └── TodoService.kt │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── journaler │ │ ├── NoteTest.kt │ │ ├── SuiteTest.kt │ │ └── TodoTest.kt │ ├── configuration │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── config │ │ │ └── ConfigApplication.kt │ │ └── resources │ │ └── application.properties │ ├── discovery │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── discovery │ │ │ ├── DiscoveryApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ └── security │ │ │ └── WebSecurityConfiguration.kt │ │ └── resources │ │ └── bootstrap.properties │ └── gateway │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ └── main │ ├── kotlin │ └── com │ │ └── journaler │ │ └── gateway │ │ ├── GatewayApplication.kt │ │ ├── SessionConfiguration.kt │ │ ├── SessionFilter.kt │ │ └── security │ │ └── WebSecurityConfiguration.kt │ └── resources │ └── bootstrap.properties ├── Final Project ├── Dependency injection │ ├── .gitignore │ └── src │ │ ├── ConstructorInjection.kt │ │ ├── FactoryInjection.kt │ │ ├── MusicPlayer.kt │ │ └── MusicPlayerIOC.kt └── Journaler API │ ├── api │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── journaler │ │ │ │ └── api │ │ │ │ ├── ApiApplication.kt │ │ │ │ ├── controller │ │ │ │ ├── NoteController.kt │ │ │ │ ├── NoteFindByTitleRequest.kt │ │ │ │ ├── TodoController.kt │ │ │ │ └── TodoLaterThanRequest.kt │ │ │ │ ├── data │ │ │ │ ├── Note.kt │ │ │ │ ├── NoteDTO.kt │ │ │ │ ├── Todo.kt │ │ │ │ └── TodoDTO.kt │ │ │ │ ├── repository │ │ │ │ ├── NoteRepository.kt │ │ │ │ └── TodoRepository.kt │ │ │ │ ├── security │ │ │ │ └── WebSecurityConfiguration.kt │ │ │ │ └── service │ │ │ │ ├── NoteService.kt │ │ │ │ └── TodoService.kt │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── journaler │ │ ├── NoteTest.kt │ │ ├── SuiteTest.kt │ │ └── TodoTest.kt │ ├── configuration │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── config │ │ │ └── ConfigApplication.kt │ │ └── resources │ │ └── application.properties │ ├── discovery │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── journaler │ │ │ └── discovery │ │ │ ├── DiscoveryApplication.kt │ │ │ ├── SessionConfiguration.kt │ │ │ └── security │ │ │ └── WebSecurityConfiguration.kt │ │ └── resources │ │ └── bootstrap.properties │ └── gateway │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ └── src │ └── main │ ├── kotlin │ └── com │ │ └── journaler │ │ └── gateway │ │ ├── GatewayApplication.kt │ │ ├── SessionConfiguration.kt │ │ ├── SessionFilter.kt │ │ └── security │ │ └── WebSecurityConfiguration.kt │ └── resources │ └── bootstrap.properties ├── LICENSE ├── README.md ├── Software and hardware list.pdf └── discovery.properties /Chapter02/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter02/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter02/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter02/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter02/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter02/Journaler API/api/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | kotlinVersion = '1.1.51' 4 | springBootVersion = '2.0.0.M4' 5 | } 6 | repositories { 7 | mavenCentral() 8 | maven { url "https://repo.spring.io/snapshot" } 9 | maven { url "https://repo.spring.io/milestone" } 10 | } 11 | dependencies { 12 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 13 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}") 14 | classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}") 15 | } 16 | } 17 | 18 | apply plugin: 'kotlin' 19 | apply plugin: 'kotlin-spring' 20 | apply plugin: 'eclipse' 21 | apply plugin: 'org.springframework.boot' 22 | apply plugin: 'io.spring.dependency-management' 23 | 24 | group = 'com.journaler' 25 | version = '0.0.1-SNAPSHOT' 26 | sourceCompatibility = 1.8 27 | compileKotlin { 28 | kotlinOptions.jvmTarget = "1.8" 29 | } 30 | compileTestKotlin { 31 | kotlinOptions.jvmTarget = "1.8" 32 | } 33 | 34 | repositories { 35 | mavenCentral() 36 | maven { url "https://repo.spring.io/snapshot" } 37 | maven { url "https://repo.spring.io/milestone" } 38 | } 39 | 40 | 41 | dependencies { 42 | compile('org.springframework.boot:spring-boot-starter') 43 | compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${kotlinVersion}") 44 | compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") 45 | testCompile('org.springframework.boot:spring-boot-starter-test') 46 | } 47 | -------------------------------------------------------------------------------- /Chapter02/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Chapter02/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Applications-with-Spring-5-and-Kotlin/914a9d5d336e3563c3a12b6ad7b8e3321f3ec46d/Chapter02/Journaler API/api/src/main/resources/application.properties -------------------------------------------------------------------------------- /Chapter02/Journaler API/api/src/test/kotlin/com/journaler/api/ApiApplicationTests.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.junit.Test 4 | import org.junit.runner.RunWith 5 | import org.springframework.boot.test.context.SpringBootTest 6 | import org.springframework.test.context.junit4.SpringRunner 7 | 8 | @RunWith(SpringRunner::class) 9 | @SpringBootTest 10 | class ApiApplicationTests { 11 | 12 | @Test 13 | fun contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Chapter03/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter03/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter03/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter03/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | data class Note( 4 | var id: String = "", 5 | var title: String, 6 | var message: String, 7 | var location: String = "" 8 | ) -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | data class Todo( 4 | var id: String = "", 5 | var title: String, 6 | var message: String, 7 | var schedule: Long, 8 | var location: String = "" 9 | ) -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.stereotype.Service 5 | import java.util.* 6 | 7 | @Service("Note service") 8 | class NoteService { 9 | 10 | fun getNotes(): List = listOf( 11 | Note( 12 | UUID.randomUUID().toString(), 13 | "My first note", 14 | "This is a message for the 1st note." 15 | ), 16 | Note( 17 | UUID.randomUUID().toString(), 18 | "My second note", 19 | "This is a message for the 2nd note." 20 | ) 21 | ) 22 | 23 | fun insertNote(note: Note): Note { 24 | note.id = UUID.randomUUID().toString() 25 | return note 26 | } 27 | 28 | fun deleteNote(id: String): Boolean = false 29 | 30 | fun updateNote(note: Note): Boolean = true 31 | 32 | } -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.stereotype.Service 5 | import java.util.* 6 | 7 | 8 | @Service("Todo service") 9 | class TodoService { 10 | 11 | fun getTodos(): List = listOf( 12 | Todo( 13 | UUID.randomUUID().toString(), 14 | "My first todo", 15 | "This is a message for the 1st todo.", 16 | System.currentTimeMillis() 17 | ), 18 | Todo( 19 | UUID.randomUUID().toString(), 20 | "My second todo", 21 | "This is a message for the 2nd todo.", 22 | System.currentTimeMillis() 23 | ) 24 | ) 25 | 26 | fun insertTodo(todo: Todo): Todo { 27 | todo.id = UUID.randomUUID().toString() 28 | return todo 29 | } 30 | 31 | fun deleteTodo(id: String): Boolean = false 32 | 33 | fun updateTodo(todo: Todo): Boolean = true 34 | 35 | } -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= Journaler API 2 | server.port= 9000 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | # server.servlet.path = /api 13 | # server.servlet.context-path= /api -------------------------------------------------------------------------------- /Chapter03/Journaler API/api/src/test/kotlin/com/journaler/api/ApiApplicationTests.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.junit.Test 4 | import org.junit.runner.RunWith 5 | import org.springframework.boot.test.context.SpringBootTest 6 | import org.springframework.test.context.junit4.SpringRunner 7 | 8 | @RunWith(SpringRunner::class) 9 | @SpringBootTest 10 | class ApiApplicationTests { 11 | 12 | @Test 13 | fun contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Chapter04/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter04/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter04/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter04/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date) -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | var id: String = "" 12 | var created: Date = Date() 13 | var modified: Date = Date() 14 | 15 | constructor(note: Note) : this( 16 | note.title, 17 | note.message, 18 | note.location 19 | ) { 20 | id = note.id 21 | created = note.created 22 | modified = note.modified 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.deleteById(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | var note = repository.findById(noteDto.id).get() 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | note = repository.save(note) 37 | return NoteDTO(note) 38 | } 39 | 40 | fun findByTitle(title: String): Iterable { 41 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO): TodoDTO = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.deleteById(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | var todo = repository.findById(todoDto.id).get() 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | todo = repository.save(todo) 41 | return TodoDTO(todo) 42 | } 43 | 44 | fun getScheduledLaterThan(date: Date): Iterable { 45 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= Journaler API 2 | server.port= 9000 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | # server.servlet.path = /api 13 | # server.servlet.context-path= /api 14 | 15 | spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 16 | spring.datasource.username=root 17 | spring.datasource.password=localInstance2017 18 | spring.datasource.tomcat.test-on-borrow=true 19 | spring.datasource.tomcat.validation-interval=30000 20 | spring.datasource.tomcat.validation-query=SELECT 1 21 | spring.datasource.tomcat.remove-abandoned=true 22 | spring.datasource.tomcat.remove-abandoned-timeout=10000 23 | spring.datasource.tomcat.log-abandoned=true 24 | spring.datasource.tomcat.max-age=1800000 25 | spring.datasource.tomcat.log-validation-errors=true 26 | spring.datasource.tomcat.max-active=50 27 | spring.datasource.tomcat.max-idle=10 28 | 29 | spring.jpa.hibernate.ddl-auto=update -------------------------------------------------------------------------------- /Chapter04/Journaler API/api/src/test/kotlin/com/journaler/api/ApiApplicationTests.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.junit.Test 4 | import org.junit.runner.RunWith 5 | import org.springframework.boot.test.context.SpringBootTest 6 | import org.springframework.test.context.junit4.SpringRunner 7 | 8 | @RunWith(SpringRunner::class) 9 | @SpringBootTest 10 | class ApiApplicationTests { 11 | 12 | @Test 13 | fun contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Chapter05/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter05/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter05/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter05/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date) -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | var id: String = "" 12 | var created: Date = Date() 13 | var modified: Date = Date() 14 | 15 | constructor(note: Note) : this( 16 | note.title, 17 | note.message, 18 | note.location 19 | ) { 20 | id = note.id 21 | created = note.created 22 | modified = note.modified 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/repository/UserRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.security.User 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | interface UserRepository : CrudRepository { 7 | 8 | fun findOneByEmail(email: String): User? 9 | 10 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/security/Admin.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import java.util.* 4 | import javax.persistence.DiscriminatorValue 5 | import javax.persistence.Entity 6 | 7 | @Entity 8 | @DiscriminatorValue(value = "ADMIN") 9 | class Admin( 10 | id: String, 11 | email: String, 12 | pwd: String, 13 | firstName: String, 14 | lastName: String, 15 | roles: String, 16 | enabled: Boolean, 17 | accountNonExpired: Boolean, 18 | accountNonLocked: Boolean, 19 | credentialsNonExpired: Boolean, 20 | created: Date, 21 | modified: Date 22 | ) : User( 23 | id, 24 | email, 25 | pwd, 26 | firstName, 27 | lastName, 28 | roles, 29 | enabled, 30 | accountNonExpired, 31 | accountNonLocked, 32 | credentialsNonExpired, 33 | created, 34 | modified 35 | ) { 36 | 37 | /** 38 | * We need empty constructor for SecurityInitializationTest and Hibernate. 39 | */ 40 | constructor() : this( 41 | "", "", "", "", "", "", true, true, true, true, Date(), Date() 42 | ) 43 | 44 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/security/Member.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import java.util.* 4 | import javax.persistence.DiscriminatorValue 5 | import javax.persistence.Entity 6 | 7 | @Entity 8 | @DiscriminatorValue(value = "MEMBER") 9 | class Member( 10 | id: String, 11 | email: String, 12 | pwd: String, 13 | firstName: String, 14 | lastName: String, 15 | roles: String, 16 | enabled: Boolean, 17 | accountNonExpired: Boolean, 18 | accountNonLocked: Boolean, 19 | credentialsNonExpired: Boolean, 20 | created: Date, 21 | modified: Date 22 | ) : User( 23 | id, 24 | email, 25 | pwd, 26 | firstName, 27 | lastName, 28 | roles, 29 | enabled, 30 | accountNonExpired, 31 | accountNonLocked, 32 | credentialsNonExpired, 33 | created, 34 | modified 35 | ) { 36 | 37 | /** 38 | * We need empty constructor for SecurityInitializationTest and Hibernate. 39 | */ 40 | constructor() : this( 41 | "", "", "", "", "", "", true, true, true, true, Date(), Date() 42 | ) 43 | 44 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/security/UserDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | data class UserDTO( 4 | var email: String, 5 | var password: String, 6 | var firstName: String, 7 | var lastName: String 8 | ) -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/security/UserDetailsDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import java.util.* 4 | 5 | data class UserDetailsDTO( 6 | val id: String, 7 | var email: String, 8 | var firstName: String, 9 | var lastName: String, 10 | var roles: String, 11 | var enabled: Boolean, 12 | var accountNonExpired: Boolean, 13 | var accountNonLocked: Boolean, 14 | var credentialsNonExpired: Boolean, 15 | var created: Date, 16 | var modified: Date 17 | ) -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityAuthSuccessHandler.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.security.core.Authentication 4 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler 5 | import org.springframework.security.web.savedrequest.HttpSessionRequestCache 6 | import org.springframework.stereotype.Component 7 | import org.springframework.util.StringUtils 8 | import javax.servlet.http.HttpServletRequest 9 | import javax.servlet.http.HttpServletResponse 10 | 11 | @Component 12 | class WebSecurityAuthSuccessHandler : SimpleUrlAuthenticationSuccessHandler() { 13 | 14 | var requestCache = HttpSessionRequestCache() 15 | 16 | override fun onAuthenticationSuccess( 17 | request: HttpServletRequest, 18 | response: HttpServletResponse, 19 | authentication: Authentication 20 | ) { 21 | val savedRequest = requestCache.getRequest(request, response) 22 | if (savedRequest == null) { 23 | clearAuthenticationAttributes(request) 24 | return 25 | } 26 | val parameter = request.getParameter(targetUrlParameter) 27 | val ok = isAlwaysUseDefaultTargetUrl || targetUrlParameter != null && StringUtils.hasText(parameter) 28 | if (ok) { 29 | requestCache.removeRequest(request, response) 30 | clearAuthenticationAttributes(request) 31 | return 32 | } 33 | clearAuthenticationAttributes(request) 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityEntryPoint.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.security.core.AuthenticationException 4 | import org.springframework.security.web.AuthenticationEntryPoint 5 | import org.springframework.stereotype.Component 6 | import javax.servlet.http.HttpServletRequest 7 | import javax.servlet.http.HttpServletResponse 8 | 9 | @Component 10 | class WebSecurityEntryPoint : AuthenticationEntryPoint { 11 | 12 | override fun commence( 13 | request: HttpServletRequest?, 14 | response: HttpServletResponse?, 15 | authException: AuthenticationException? 16 | ) { 17 | response?.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied") 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.deleteById(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | var note = repository.findById(noteDto.id).get() 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | note = repository.save(note) 37 | return NoteDTO(note) 38 | } 39 | 40 | fun findByTitle(title: String): Iterable { 41 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO): TodoDTO = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.deleteById(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | var todo = repository.findById(todoDto.id).get() 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | todo = repository.save(todo) 41 | return TodoDTO(todo) 42 | } 43 | 44 | fun getScheduledLaterThan(date: Date): Iterable { 45 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= Journaler API 2 | server.port= 9000 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | # server.servlet.path = /api 13 | # server.servlet.context-path= /api 14 | 15 | spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 16 | spring.datasource.username=root 17 | spring.datasource.password=localInstance2017 18 | spring.datasource.tomcat.test-on-borrow=true 19 | spring.datasource.tomcat.validation-interval=30000 20 | spring.datasource.tomcat.validation-query=SELECT 1 21 | spring.datasource.tomcat.remove-abandoned=true 22 | spring.datasource.tomcat.remove-abandoned-timeout=10000 23 | spring.datasource.tomcat.log-abandoned=true 24 | spring.datasource.tomcat.max-age=1800000 25 | spring.datasource.tomcat.log-validation-errors=true 26 | spring.datasource.tomcat.max-active=50 27 | spring.datasource.tomcat.max-idle=10 28 | 29 | spring.jpa.hibernate.ddl-auto=update -------------------------------------------------------------------------------- /Chapter05/Journaler API/api/src/test/kotlin/com/journaler/api/ApiApplicationTests.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.junit.Test 4 | import org.junit.runner.RunWith 5 | import org.springframework.boot.test.context.SpringBootTest 6 | import org.springframework.test.context.junit4.SpringRunner 7 | 8 | @RunWith(SpringRunner::class) 9 | @SpringBootTest 10 | class ApiApplicationTests { 11 | 12 | @Test 13 | fun contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter06/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter06/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter06/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | 7 | @SpringBootApplication 8 | @EnableEurekaClient 9 | class ApiApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ApiApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) { 4 | 5 | constructor() : this("") 6 | 7 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date? = null) { 6 | 7 | constructor() : this(null) 8 | 9 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | constructor() : this("", "", "") 12 | 13 | var id: String = "" 14 | var created: Date = Date() 15 | var modified: Date = Date() 16 | 17 | constructor(note: Note) : this( 18 | note.title, 19 | note.message, 20 | note.location 21 | ) { 22 | id = note.id 23 | created = note.created 24 | modified = note.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | constructor() : this("", "", -1, "") 28 | 29 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 7 | import org.springframework.core.annotation.Order 8 | 9 | @Configuration 10 | @EnableWebSecurity 11 | @Order(1) 12 | class SecurityConfig : WebSecurityConfigurerAdapter() { 13 | 14 | override fun configure(http: HttpSecurity) { 15 | http 16 | .httpBasic().disable().authorizeRequests() 17 | .antMatchers("/notes").permitAll() 18 | .antMatchers("/notes/**").permitAll() 19 | .antMatchers("/todos").permitAll() 20 | .antMatchers("/todos/**").permitAll() 21 | .anyRequest() 22 | .authenticated() 23 | .and() 24 | .csrf().disable() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.delete(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | var note = repository.findOne(noteDto.id) 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | note = repository.save(note) 37 | return NoteDTO(note) 38 | } 39 | 40 | fun findByTitle(title: String): Iterable { 41 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO): TodoDTO = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.delete(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | var todo = repository.findOne(todoDto.id) 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | todo = repository.save(todo) 41 | return TodoDTO(todo) 42 | } 43 | 44 | fun getScheduledLaterThan(date: Date?): Iterable { 45 | date?.let { 46 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 47 | } 48 | return listOf() 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/api/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=journaler 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | 5 | spring.cloud.config.username=configAdmin 6 | spring.cloud.config.password=configPassword12345 7 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ -------------------------------------------------------------------------------- /Chapter06/Journaler API/configuration/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Configuration Server 2 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/configuration/src/main/kotlin/com/journaler/config/ConfigApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.config 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.config.server.EnableConfigServer 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | class ConfigApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ConfigApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/configuration/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= config 2 | server.port= 9001 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.cloud.config.server.git.uri=file://${user.home}/Projects/Building-Applications-with-Spring-5-and-Kotlin-Config-Repo 13 | 14 | # Or you can clone your existing configuration repo: 15 | # spring.cloud.config.server.git.uri=ssh://some_domain/config-repo 16 | # spring.cloud.config.server.git.clone-on-start=true 17 | # security.user.name=git_username 18 | # security.user.password=git_password 19 | 20 | eureka.client.region = default 21 | eureka.client.registryFetchIntervalSeconds = 5 22 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 23 | 24 | security.user.name=configAdmin 25 | security.user.password=configPassword12345 26 | security.user.role=SYSTEM 27 | 28 | spring.session.store-type=redis -------------------------------------------------------------------------------- /Chapter06/Journaler API/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/discovery/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Discovery Server 2 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/DiscoveryApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | class DiscoveryApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(DiscoveryApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter06/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | import org.springframework.security.config.http.SessionCreationPolicy 11 | 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | @Order(1) 16 | class SecurityConfig : WebSecurityConfigurerAdapter() { 17 | 18 | @Autowired 19 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 20 | auth 21 | .inMemoryAuthentication() 22 | .withUser("discoveryAdmin") 23 | .password("discoveryPassword12345") 24 | .roles("SYSTEM") 25 | } 26 | 27 | override fun configure(http: HttpSecurity) { 28 | http 29 | .sessionManagement() 30 | .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) 31 | .and().requestMatchers().antMatchers("/eureka/**") 32 | .and().authorizeRequests().antMatchers("/eureka/**") 33 | .hasRole("SYSTEM").anyRequest().denyAll().and() 34 | .httpBasic().and().csrf().disable() 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/discovery/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=discovery 2 | spring.cloud.config.uri=http://localhost:9001 3 | spring.cloud.config.username=configAdmin 4 | spring.cloud.config.password=configPassword12345 5 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Gateway Server 2 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/GatewayApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy 7 | 8 | @SpringBootApplication 9 | @EnableZuulProxy 10 | @EnableEurekaClient 11 | class GatewayApplication 12 | 13 | fun main(args: Array) { 14 | SpringApplication.run(GatewayApplication::class.java, *args) 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.session.data.redis.RedisFlushMode 4 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 5 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 6 | 7 | @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) 8 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionFilter.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import com.netflix.zuul.ZuulFilter 4 | import com.netflix.zuul.context.RequestContext 5 | import org.springframework.stereotype.Component 6 | import org.springframework.session.SessionRepository 7 | import org.springframework.beans.factory.annotation.Autowired 8 | 9 | @Component 10 | class SessionFilter : ZuulFilter() { 11 | 12 | @Autowired 13 | lateinit var repository: SessionRepository<*> 14 | 15 | override fun shouldFilter(): Boolean { 16 | return true 17 | } 18 | 19 | override fun run(): Any? { 20 | val context = RequestContext.getCurrentContext() 21 | val httpSession = context.request.session 22 | val session = repository.getSession(httpSession.id) 23 | context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.id) 24 | println("Session ID available: ${session.id}") 25 | return null 26 | } 27 | 28 | override fun filterType(): String { 29 | return "pre" 30 | } 31 | 32 | override fun filterOrder(): Int { 33 | return 0 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | 11 | @Configuration 12 | @EnableWebSecurity 13 | @Order(1) 14 | class SecurityConfig : WebSecurityConfigurerAdapter() { 15 | 16 | @Autowired 17 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 18 | auth 19 | .inMemoryAuthentication() 20 | .withUser("user") 21 | .password("12345") 22 | .roles("USER") 23 | .and() 24 | .withUser("admin") 25 | .password("12345") 26 | .roles("ADMIN") 27 | } 28 | 29 | override fun configure(http: HttpSecurity) { 30 | http 31 | .authorizeRequests() 32 | .antMatchers("/journaler/**") 33 | .permitAll() 34 | .antMatchers("/eureka/**").hasRole("ADMIN") 35 | .anyRequest().authenticated() 36 | .and() 37 | .formLogin() 38 | .and() 39 | .logout().permitAll() 40 | .logoutSuccessUrl("/journaler/**").permitAll() 41 | .and() 42 | .csrf().disable() 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /Chapter06/Journaler API/gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=gateway 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | spring.cloud.config.username=configAdmin 5 | spring.cloud.config.password=configPassword12345 6 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 7 | 8 | -------------------------------------------------------------------------------- /Chapter07/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter07/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter07/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter07/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import com.journaler.api.reactor.NotesCountNotificationConsumer 4 | import com.journaler.api.reactor.TodosCountNotificationConsumer 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.boot.CommandLineRunner 7 | import org.springframework.boot.SpringApplication 8 | import org.springframework.boot.autoconfigure.SpringBootApplication 9 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 10 | import org.springframework.context.annotation.Bean 11 | import reactor.Environment 12 | import reactor.bus.EventBus 13 | import reactor.bus.selector.Selectors.`$` 14 | 15 | 16 | @SpringBootApplication 17 | @EnableEurekaClient 18 | class ApiApplication : CommandLineRunner { 19 | 20 | @Autowired 21 | private lateinit var eventBus: EventBus 22 | 23 | @Autowired 24 | private lateinit var notesCountNotificationConsumer: NotesCountNotificationConsumer 25 | 26 | @Autowired 27 | private lateinit var todosCountNotificationConsumer: TodosCountNotificationConsumer 28 | 29 | @Bean 30 | fun env() = Environment.initializeIfEmpty().assignErrorJournal() 31 | 32 | @Bean 33 | fun createEventBus(env: Environment) = EventBus.create(env, Environment.THREAD_POOL) 34 | 35 | override fun run(vararg args: String) { 36 | eventBus.on(`$`("notesCountNotificationConsumer"), notesCountNotificationConsumer) 37 | eventBus.on(`$`("todosCountNotificationConsumer"), todosCountNotificationConsumer) 38 | } 39 | } 40 | 41 | fun main(args: Array) { 42 | SpringApplication.run(ApiApplication::class.java, *args) 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) { 4 | 5 | constructor() : this("") 6 | 7 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date? = null) { 6 | 7 | constructor() : this(null) 8 | 9 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | constructor() : this("", "", "") 12 | 13 | var id: String = "" 14 | var created: Date = Date() 15 | var modified: Date = Date() 16 | 17 | constructor(note: Note) : this( 18 | note.title, 19 | note.message, 20 | note.location 21 | ) { 22 | id = note.id 23 | created = note.created 24 | modified = note.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | constructor() : this("", "", -1, "") 28 | 29 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/mail/MailMessage.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.mail 2 | 3 | import org.hibernate.validator.constraints.Email 4 | import org.jetbrains.annotations.NotNull 5 | 6 | data class MailMessage( 7 | @Email 8 | @NotNull 9 | val to: String, 10 | val subject: String, 11 | val text: String 12 | ) -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/mail/MailService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.mail 2 | 3 | interface MailService { 4 | 5 | fun sendMessage(message: MailMessage) 6 | 7 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/mail/MailServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.mail 2 | 3 | import org.springframework.beans.factory.annotation.Autowired 4 | import org.springframework.mail.SimpleMailMessage 5 | import org.springframework.mail.javamail.JavaMailSender 6 | import org.springframework.stereotype.Component 7 | 8 | @Component 9 | class MailServiceImpl : MailService { 10 | 11 | @Autowired 12 | lateinit var sender: JavaMailSender 13 | 14 | override fun sendMessage(message: MailMessage) { 15 | val toSend = SimpleMailMessage() 16 | toSend.to = arrayOf(message.to) 17 | toSend.subject = message.subject 18 | toSend.text = message.text 19 | sender.send(toSend) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/NotesCountNotification.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | data class NotesCountNotification(val notesCount: Int) -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/NotesCountNotificationConsumer.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import org.springframework.beans.factory.annotation.Autowired 4 | import org.springframework.stereotype.Service 5 | import reactor.bus.Event 6 | 7 | @Service 8 | class NotesCountNotificationConsumer : NotificationConsumer { 9 | 10 | @Autowired 11 | lateinit var service: NotesCountNotificationService 12 | 13 | override fun accept(e: Event?) { 14 | val data = e?.data 15 | data?.let { 16 | service.notify(data) 17 | } 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/NotesCountNotificationService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import org.springframework.stereotype.Service 4 | 5 | interface NotesCountNotificationService : NotificationService -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/NotesCountNotificationServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import com.journaler.api.mail.MailMessage 4 | import com.journaler.api.mail.MailService 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.stereotype.Service 7 | 8 | @Service 9 | class NotesCountNotificationServiceImpl : NotesCountNotificationService { 10 | 11 | @Autowired 12 | private lateinit var mailService: MailService 13 | 14 | override fun notify(notification: NotesCountNotification) { 15 | val to = "go.reactive.with.spring@mailinator.com" 16 | val subject = "Notes count notification" 17 | val text = "Notes reached ${notification.notesCount} count." 18 | val message = MailMessage(to, subject, text) 19 | mailService.sendMessage(message) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/NotificationConsumer.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import reactor.bus.Event 4 | import reactor.fn.Consumer 5 | 6 | interface NotificationConsumer : Consumer> -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/NotificationService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | interface NotificationService { 4 | 5 | fun notify(notification: T) 6 | 7 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/TodosCountNotification.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | data class TodosCountNotification(val todosCount: Int) -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/TodosCountNotificationConsumer.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import org.springframework.beans.factory.annotation.Autowired 4 | import org.springframework.stereotype.Service 5 | import reactor.bus.Event 6 | 7 | @Service 8 | class TodosCountNotificationConsumer : NotificationConsumer { 9 | 10 | @Autowired 11 | lateinit var service: TodosCountNotificationService 12 | 13 | override fun accept(e: Event?) { 14 | val data = e?.data 15 | data?.let { 16 | service.notify(data) 17 | } 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/TodosCountNotificationService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import org.springframework.stereotype.Service 4 | 5 | interface TodosCountNotificationService : NotificationService -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/reactor/TodosCountNotificationServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.reactor 2 | 3 | import com.journaler.api.mail.MailMessage 4 | import com.journaler.api.mail.MailService 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.stereotype.Service 7 | 8 | @Service 9 | class TodosCountNotificationServiceImpl : TodosCountNotificationService { 10 | 11 | @Autowired 12 | private lateinit var mailService: MailService 13 | 14 | override fun notify(notification: TodosCountNotification) { 15 | val to = "go.reactive.with.spring@mailinator.com" 16 | val subject = "Notes count notification" 17 | val text = "Todos reached ${notification.todosCount} count." 18 | val message = MailMessage(to, subject, text) 19 | mailService.sendMessage(message) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 7 | import org.springframework.core.annotation.Order 8 | 9 | @Configuration 10 | @EnableWebSecurity 11 | @Order(1) 12 | class SecurityConfig : WebSecurityConfigurerAdapter() { 13 | 14 | override fun configure(http: HttpSecurity) { 15 | http 16 | .httpBasic().disable().authorizeRequests() 17 | .antMatchers("/notes").permitAll() 18 | .antMatchers("/notes/**").permitAll() 19 | .antMatchers("/todos").permitAll() 20 | .antMatchers("/todos/**").permitAll() 21 | .anyRequest() 22 | .authenticated() 23 | .and() 24 | .csrf().disable() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/api/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=journaler 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | 5 | spring.cloud.config.username=configAdmin 6 | spring.cloud.config.password=configPassword12345 7 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ -------------------------------------------------------------------------------- /Chapter07/Journaler API/configuration/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Configuration Server 2 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/configuration/src/main/kotlin/com/journaler/config/ConfigApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.config 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.config.server.EnableConfigServer 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | class ConfigApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ConfigApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/configuration/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= config 2 | server.port= 9001 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.cloud.config.server.git.uri=file://${user.home}/Projects/Building-Applications-with-Spring-5-and-Kotlin-Config-Repo 13 | 14 | # Or you can clone your existing configuration repo: 15 | # spring.cloud.config.server.git.uri=ssh://some_domain/config-repo 16 | # spring.cloud.config.server.git.clone-on-start=true 17 | # security.user.name=git_username 18 | # security.user.password=git_password 19 | 20 | eureka.client.region = default 21 | eureka.client.registryFetchIntervalSeconds = 5 22 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 23 | 24 | security.user.name=configAdmin 25 | security.user.password=configPassword12345 26 | security.user.role=SYSTEM 27 | 28 | spring.session.store-type=redis -------------------------------------------------------------------------------- /Chapter07/Journaler API/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/discovery/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Discovery Server 2 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/DiscoveryApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | class DiscoveryApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(DiscoveryApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter07/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | import org.springframework.security.config.http.SessionCreationPolicy 11 | 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | @Order(1) 16 | class SecurityConfig : WebSecurityConfigurerAdapter() { 17 | 18 | @Autowired 19 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 20 | auth 21 | .inMemoryAuthentication() 22 | .withUser("discoveryAdmin") 23 | .password("discoveryPassword12345") 24 | .roles("SYSTEM") 25 | } 26 | 27 | override fun configure(http: HttpSecurity) { 28 | http 29 | .sessionManagement() 30 | .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) 31 | .and().requestMatchers().antMatchers("/eureka/**") 32 | .and().authorizeRequests().antMatchers("/eureka/**") 33 | .hasRole("SYSTEM").anyRequest().denyAll().and() 34 | .httpBasic().and().csrf().disable() 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/discovery/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=discovery 2 | spring.cloud.config.uri=http://localhost:9001 3 | spring.cloud.config.username=configAdmin 4 | spring.cloud.config.password=configPassword12345 5 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Gateway Server 2 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/GatewayApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy 7 | 8 | @SpringBootApplication 9 | @EnableZuulProxy 10 | @EnableEurekaClient 11 | class GatewayApplication 12 | 13 | fun main(args: Array) { 14 | SpringApplication.run(GatewayApplication::class.java, *args) 15 | } 16 | -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.session.data.redis.RedisFlushMode 4 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 5 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 6 | 7 | @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) 8 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionFilter.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import com.netflix.zuul.ZuulFilter 4 | import com.netflix.zuul.context.RequestContext 5 | import org.springframework.stereotype.Component 6 | import org.springframework.session.SessionRepository 7 | import org.springframework.beans.factory.annotation.Autowired 8 | 9 | @Component 10 | class SessionFilter : ZuulFilter() { 11 | 12 | @Autowired 13 | lateinit var repository: SessionRepository<*> 14 | 15 | override fun shouldFilter(): Boolean { 16 | return true 17 | } 18 | 19 | override fun run(): Any? { 20 | val context = RequestContext.getCurrentContext() 21 | val httpSession = context.request.session 22 | val session = repository.getSession(httpSession.id) 23 | context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.id) 24 | println("Session ID available: ${session.id}") 25 | return null 26 | } 27 | 28 | override fun filterType(): String { 29 | return "pre" 30 | } 31 | 32 | override fun filterOrder(): Int { 33 | return 0 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | 11 | @Configuration 12 | @EnableWebSecurity 13 | @Order(1) 14 | class SecurityConfig : WebSecurityConfigurerAdapter() { 15 | 16 | @Autowired 17 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 18 | auth 19 | .inMemoryAuthentication() 20 | .withUser("user") 21 | .password("12345") 22 | .roles("USER") 23 | .and() 24 | .withUser("admin") 25 | .password("12345") 26 | .roles("ADMIN") 27 | } 28 | 29 | override fun configure(http: HttpSecurity) { 30 | http 31 | .authorizeRequests() 32 | .antMatchers("/journaler/**") 33 | .permitAll() 34 | .antMatchers("/eureka/**").hasRole("ADMIN") 35 | .anyRequest().authenticated() 36 | .and() 37 | .formLogin() 38 | .and() 39 | .logout().permitAll() 40 | .logoutSuccessUrl("/journaler/**").permitAll() 41 | .and() 42 | .csrf().disable() 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /Chapter07/Journaler API/gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=gateway 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | spring.cloud.config.username=configAdmin 5 | spring.cloud.config.password=configPassword12345 6 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 7 | 8 | -------------------------------------------------------------------------------- /Chapter09/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter09/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter09/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter09/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) { 4 | 5 | constructor() : this("") 6 | 7 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date? = null) { 6 | 7 | constructor() : this(null) 8 | 9 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | constructor() : this("", "", "") 12 | 13 | var id: String = "" 14 | var created: Date = Date() 15 | var modified: Date = Date() 16 | 17 | constructor(note: Note) : this( 18 | note.title, 19 | note.message, 20 | note.location 21 | ) { 22 | id = note.id 23 | created = note.created 24 | modified = note.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | constructor() : this("", "", -1, "") 28 | 29 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 7 | import org.springframework.core.annotation.Order 8 | 9 | @Configuration 10 | @EnableWebSecurity 11 | @Order(1) 12 | class SecurityConfig : WebSecurityConfigurerAdapter() { 13 | 14 | override fun configure(http: HttpSecurity) { 15 | http 16 | .httpBasic().disable().authorizeRequests() 17 | .antMatchers("/notes").permitAll() 18 | .antMatchers("/notes/**").permitAll() 19 | .antMatchers("/todos").permitAll() 20 | .antMatchers("/todos/**").permitAll() 21 | .anyRequest() 22 | .authenticated() 23 | .and() 24 | .csrf().disable() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.deleteById(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | val note = repository.findById(noteDto.id).get() 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | return NoteDTO(repository.save(note)) 37 | } 38 | 39 | fun findByTitle(title: String): Iterable { 40 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO) = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.deleteById(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | val todo = repository.findById(todoDto.id).get() 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | return TodoDTO(repository.save(todo)) 41 | } 42 | 43 | fun getScheduledLaterThan(date: Date?): Iterable { 44 | date?.let { 45 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 46 | } 47 | return listOf() 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= journaler 2 | server.port= 9000 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 13 | spring.datasource.username=root 14 | spring.datasource.password=localInstance2017 15 | spring.datasource.tomcat.test-on-borrow=true 16 | spring.datasource.tomcat.validation-interval=30000 17 | spring.datasource.tomcat.validation-query=SELECT 1 18 | spring.datasource.tomcat.remove-abandoned=true 19 | spring.datasource.tomcat.remove-abandoned-timeout=10000 20 | spring.datasource.tomcat.log-abandoned=true 21 | spring.datasource.tomcat.max-age=1800000 22 | spring.datasource.tomcat.log-validation-errors=true 23 | spring.datasource.tomcat.max-active=50 24 | spring.datasource.tomcat.max-idle=10 25 | 26 | spring.jpa.hibernate.ddl-auto=update 27 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/api/src/test/kotlin/com/journaler/SuiteTest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler 2 | 3 | import org.junit.runner.RunWith 4 | import org.junit.runners.Suite 5 | 6 | @RunWith(Suite::class) 7 | @Suite.SuiteClasses(NoteTest::class, TodoTest::class) 8 | class SuiteTest -------------------------------------------------------------------------------- /Chapter09/Journaler API/configuration/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Configuration Server 2 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/configuration/src/main/kotlin/com/journaler/config/ConfigApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.config 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.config.server.EnableConfigServer 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | class ConfigApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ConfigApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/configuration/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= config 2 | server.port= 9001 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.cloud.config.server.git.uri=file://${user.home}/Projects/Building-Applications-with-Spring-5-and-Kotlin-Config-Repo 13 | 14 | # Or you can clone your existing configuration repo: 15 | # spring.cloud.config.server.git.uri=ssh://some_domain/config-repo 16 | # spring.cloud.config.server.git.clone-on-start=true 17 | # security.user.name=git_username 18 | # security.user.password=git_password 19 | 20 | eureka.client.region = default 21 | eureka.client.registryFetchIntervalSeconds = 5 22 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 23 | 24 | security.user.name=configAdmin 25 | security.user.password=configPassword12345 26 | security.user.role=SYSTEM 27 | 28 | spring.session.store-type=redis -------------------------------------------------------------------------------- /Chapter09/Journaler API/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/discovery/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Discovery Server 2 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/DiscoveryApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | class DiscoveryApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(DiscoveryApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter09/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | import org.springframework.security.config.http.SessionCreationPolicy 11 | 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | @Order(1) 16 | class SecurityConfig : WebSecurityConfigurerAdapter() { 17 | 18 | @Autowired 19 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 20 | auth 21 | .inMemoryAuthentication() 22 | .withUser("discoveryAdmin") 23 | .password("discoveryPassword12345") 24 | .roles("SYSTEM") 25 | } 26 | 27 | override fun configure(http: HttpSecurity) { 28 | http 29 | .sessionManagement() 30 | .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) 31 | .and().requestMatchers().antMatchers("/eureka/**") 32 | .and().authorizeRequests().antMatchers("/eureka/**") 33 | .hasRole("SYSTEM").anyRequest().denyAll().and() 34 | .httpBasic().and().csrf().disable() 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/discovery/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=discovery 2 | spring.cloud.config.uri=http://localhost:9001 3 | spring.cloud.config.username=configAdmin 4 | spring.cloud.config.password=configPassword12345 5 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Gateway Server 2 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/GatewayApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy 7 | 8 | @SpringBootApplication 9 | @EnableZuulProxy 10 | @EnableEurekaClient 11 | class GatewayApplication 12 | 13 | fun main(args: Array) { 14 | SpringApplication.run(GatewayApplication::class.java, *args) 15 | } 16 | -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.session.data.redis.RedisFlushMode 4 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 5 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 6 | 7 | @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) 8 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionFilter.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import com.netflix.zuul.ZuulFilter 4 | import com.netflix.zuul.context.RequestContext 5 | import org.springframework.stereotype.Component 6 | import org.springframework.session.SessionRepository 7 | import org.springframework.beans.factory.annotation.Autowired 8 | 9 | @Component 10 | class SessionFilter : ZuulFilter() { 11 | 12 | @Autowired 13 | lateinit var repository: SessionRepository<*> 14 | 15 | override fun shouldFilter(): Boolean { 16 | return true 17 | } 18 | 19 | override fun run(): Any? { 20 | val context = RequestContext.getCurrentContext() 21 | val httpSession = context.request.session 22 | val session = repository.getSession(httpSession.id) 23 | context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.id) 24 | println("Session ID available: ${session.id}") 25 | return null 26 | } 27 | 28 | override fun filterType(): String { 29 | return "pre" 30 | } 31 | 32 | override fun filterOrder(): Int { 33 | return 0 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | 11 | @Configuration 12 | @EnableWebSecurity 13 | @Order(1) 14 | class SecurityConfig : WebSecurityConfigurerAdapter() { 15 | 16 | @Autowired 17 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 18 | auth 19 | .inMemoryAuthentication() 20 | .withUser("user") 21 | .password("12345") 22 | .roles("USER") 23 | .and() 24 | .withUser("admin") 25 | .password("12345") 26 | .roles("ADMIN") 27 | } 28 | 29 | override fun configure(http: HttpSecurity) { 30 | http 31 | .authorizeRequests() 32 | .antMatchers("/journaler/**") 33 | .permitAll() 34 | .antMatchers("/eureka/**").hasRole("ADMIN") 35 | .anyRequest().authenticated() 36 | .and() 37 | .formLogin() 38 | .and() 39 | .logout().permitAll() 40 | .logoutSuccessUrl("/journaler/**").permitAll() 41 | .and() 42 | .csrf().disable() 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /Chapter09/Journaler API/gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=gateway 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | spring.cloud.config.username=configAdmin 5 | spring.cloud.config.password=configPassword12345 6 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 7 | 8 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) { 4 | 5 | constructor() : this("") 6 | 7 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date? = null) { 6 | 7 | constructor() : this(null) 8 | 9 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | constructor() : this("", "", "") 12 | 13 | var id: String = "" 14 | var created: Date = Date() 15 | var modified: Date = Date() 16 | 17 | constructor(note: Note) : this( 18 | note.title, 19 | note.message, 20 | note.location 21 | ) { 22 | id = note.id 23 | created = note.created 24 | modified = note.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | constructor() : this("", "", -1, "") 28 | 29 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 7 | import org.springframework.core.annotation.Order 8 | 9 | @Configuration 10 | @EnableWebSecurity 11 | @Order(1) 12 | class SecurityConfig : WebSecurityConfigurerAdapter() { 13 | 14 | override fun configure(http: HttpSecurity) { 15 | http 16 | .httpBasic().disable().authorizeRequests() 17 | .antMatchers("/notes").permitAll() 18 | .antMatchers("/notes/**").permitAll() 19 | .antMatchers("/todos").permitAll() 20 | .antMatchers("/todos/**").permitAll() 21 | .anyRequest() 22 | .authenticated() 23 | .and() 24 | .csrf().disable() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.deleteById(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | val note = repository.findById(noteDto.id).get() 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | return NoteDTO(repository.save(note)) 37 | } 38 | 39 | fun findByTitle(title: String): Iterable { 40 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO) = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.deleteById(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | val todo = repository.findById(todoDto.id).get() 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | return TodoDTO(repository.save(todo)) 41 | } 42 | 43 | fun getScheduledLaterThan(date: Date?): Iterable { 44 | date?.let { 45 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 46 | } 47 | return listOf() 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= journaler 2 | server.port= 80 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 13 | spring.datasource.username=root 14 | spring.datasource.password=localInstance2017 15 | spring.datasource.tomcat.test-on-borrow=true 16 | spring.datasource.tomcat.validation-interval=30000 17 | spring.datasource.tomcat.validation-query=SELECT 1 18 | spring.datasource.tomcat.remove-abandoned=true 19 | spring.datasource.tomcat.remove-abandoned-timeout=10000 20 | spring.datasource.tomcat.log-abandoned=true 21 | spring.datasource.tomcat.max-age=1800000 22 | spring.datasource.tomcat.log-validation-errors=true 23 | spring.datasource.tomcat.max-active=50 24 | spring.datasource.tomcat.max-idle=10 25 | 26 | spring.jpa.hibernate.ddl-auto=update 27 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/api/src/test/kotlin/com/journaler/SuiteTest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler 2 | 3 | import org.junit.runner.RunWith 4 | import org.junit.runners.Suite 5 | 6 | @RunWith(Suite::class) 7 | @Suite.SuiteClasses(NoteTest::class, TodoTest::class) 8 | class SuiteTest -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/configuration/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Configuration Server 2 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/configuration/src/main/kotlin/com/journaler/config/ConfigApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.config 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.config.server.EnableConfigServer 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | class ConfigApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ConfigApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/configuration/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= config 2 | server.port= 9001 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.cloud.config.server.git.uri=file://${user.home}/Projects/Building-Applications-with-Spring-5-and-Kotlin-Config-Repo 13 | 14 | # Or you can clone your existing configuration repo: 15 | # spring.cloud.config.server.git.uri=ssh://some_domain/config-repo 16 | # spring.cloud.config.server.git.clone-on-start=true 17 | # security.user.name=git_username 18 | # security.user.password=git_password 19 | 20 | eureka.client.region = default 21 | eureka.client.registryFetchIntervalSeconds = 5 22 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 23 | 24 | security.user.name=configAdmin 25 | security.user.password=configPassword12345 26 | security.user.role=SYSTEM 27 | 28 | spring.session.store-type=redis -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/discovery/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Discovery Server 2 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/DiscoveryApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | class DiscoveryApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(DiscoveryApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | import org.springframework.security.config.http.SessionCreationPolicy 11 | 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | @Order(1) 16 | class SecurityConfig : WebSecurityConfigurerAdapter() { 17 | 18 | @Autowired 19 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 20 | auth 21 | .inMemoryAuthentication() 22 | .withUser("discoveryAdmin") 23 | .password("discoveryPassword12345") 24 | .roles("SYSTEM") 25 | } 26 | 27 | override fun configure(http: HttpSecurity) { 28 | http 29 | .sessionManagement() 30 | .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) 31 | .and().requestMatchers().antMatchers("/eureka/**") 32 | .and().authorizeRequests().antMatchers("/eureka/**") 33 | .hasRole("SYSTEM").anyRequest().denyAll().and() 34 | .httpBasic().and().csrf().disable() 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/discovery/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=discovery 2 | spring.cloud.config.uri=http://localhost:9001 3 | spring.cloud.config.username=configAdmin 4 | spring.cloud.config.password=configPassword12345 5 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/gateway/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Gateway Server 2 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/GatewayApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy 7 | 8 | @SpringBootApplication 9 | @EnableZuulProxy 10 | @EnableEurekaClient 11 | class GatewayApplication 12 | 13 | fun main(args: Array) { 14 | SpringApplication.run(GatewayApplication::class.java, *args) 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.session.data.redis.RedisFlushMode 4 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 5 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 6 | 7 | @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) 8 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionFilter.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import com.netflix.zuul.ZuulFilter 4 | import com.netflix.zuul.context.RequestContext 5 | import org.springframework.stereotype.Component 6 | import org.springframework.session.SessionRepository 7 | import org.springframework.beans.factory.annotation.Autowired 8 | 9 | @Component 10 | class SessionFilter : ZuulFilter() { 11 | 12 | @Autowired 13 | lateinit var repository: SessionRepository<*> 14 | 15 | override fun shouldFilter(): Boolean { 16 | return true 17 | } 18 | 19 | override fun run(): Any? { 20 | val context = RequestContext.getCurrentContext() 21 | val httpSession = context.request.session 22 | val session = repository.getSession(httpSession.id) 23 | context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.id) 24 | println("Session ID available: ${session.id}") 25 | return null 26 | } 27 | 28 | override fun filterType(): String { 29 | return "pre" 30 | } 31 | 32 | override fun filterOrder(): Int { 33 | return 0 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Chapter10/ProjectA/Journaler API/gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=gateway 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | spring.cloud.config.username=configAdmin 5 | spring.cloud.config.password=configPassword12345 6 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 7 | 8 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer 6 | import org.springframework.boot.builder.SpringApplicationBuilder 7 | 8 | 9 | 10 | @SpringBootApplication 11 | class ApiApplication : SpringBootServletInitializer() { 12 | override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder { 13 | return application.sources(ApiApplication::class.java) 14 | } 15 | } 16 | 17 | fun main(args: Array) { 18 | SpringApplication.run(ApiApplication::class.java, *args) 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) { 4 | 5 | constructor() : this("") 6 | 7 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date? = null) { 6 | 7 | constructor() : this(null) 8 | 9 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | constructor() : this("", "", "") 12 | 13 | var id: String = "" 14 | var created: Date = Date() 15 | var modified: Date = Date() 16 | 17 | constructor(note: Note) : this( 18 | note.title, 19 | note.message, 20 | note.location 21 | ) { 22 | id = note.id 23 | created = note.created 24 | modified = note.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | constructor() : this("", "", -1, "") 28 | 29 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 7 | import org.springframework.core.annotation.Order 8 | 9 | @Configuration 10 | @EnableWebSecurity 11 | @Order(1) 12 | class SecurityConfig : WebSecurityConfigurerAdapter() { 13 | 14 | override fun configure(http: HttpSecurity) { 15 | http 16 | .httpBasic().disable().authorizeRequests() 17 | .antMatchers("/notes").permitAll() 18 | .antMatchers("/notes/**").permitAll() 19 | .antMatchers("/todos").permitAll() 20 | .antMatchers("/todos/**").permitAll() 21 | .anyRequest() 22 | .authenticated() 23 | .and() 24 | .csrf().disable() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.deleteById(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | val note = repository.findById(noteDto.id).get() 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | return NoteDTO(repository.save(note)) 37 | } 38 | 39 | fun findByTitle(title: String): Iterable { 40 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO) = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.deleteById(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | val todo = repository.findById(todoDto.id).get() 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | return TodoDTO(repository.save(todo)) 41 | } 42 | 43 | fun getScheduledLaterThan(date: Date?): Iterable { 44 | date?.let { 45 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 46 | } 47 | return listOf() 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= journaler 2 | server.port= 9000 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 13 | spring.datasource.username=root 14 | spring.datasource.password=localInstance2017 15 | spring.datasource.tomcat.test-on-borrow=true 16 | spring.datasource.tomcat.validation-interval=30000 17 | spring.datasource.tomcat.validation-query=SELECT 1 18 | spring.datasource.tomcat.remove-abandoned=true 19 | spring.datasource.tomcat.remove-abandoned-timeout=10000 20 | spring.datasource.tomcat.log-abandoned=true 21 | spring.datasource.tomcat.max-age=1800000 22 | spring.datasource.tomcat.log-validation-errors=true 23 | spring.datasource.tomcat.max-active=50 24 | spring.datasource.tomcat.max-idle=10 25 | 26 | spring.jpa.hibernate.ddl-auto=update 27 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/api/src/test/kotlin/com/journaler/SuiteTest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler 2 | 3 | import org.junit.runner.RunWith 4 | import org.junit.runners.Suite 5 | 6 | @RunWith(Suite::class) 7 | @Suite.SuiteClasses(NoteTest::class, TodoTest::class) 8 | class SuiteTest -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/configuration/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Configuration Server 2 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/configuration/src/main/kotlin/com/journaler/config/ConfigApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.config 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.config.server.EnableConfigServer 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | class ConfigApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ConfigApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/configuration/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= config 2 | server.port= 9001 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.cloud.config.server.git.uri=file://${user.home}/Projects/Building-Applications-with-Spring-5-and-Kotlin-Config-Repo 13 | 14 | # Or you can clone your existing configuration repo: 15 | # spring.cloud.config.server.git.uri=ssh://some_domain/config-repo 16 | # spring.cloud.config.server.git.clone-on-start=true 17 | # security.user.name=git_username 18 | # security.user.password=git_password 19 | 20 | eureka.client.region = default 21 | eureka.client.registryFetchIntervalSeconds = 5 22 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 23 | 24 | security.user.name=configAdmin 25 | security.user.password=configPassword12345 26 | security.user.role=SYSTEM 27 | 28 | spring.session.store-type=redis -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/discovery/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Discovery Server 2 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/DiscoveryApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | class DiscoveryApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(DiscoveryApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | import org.springframework.security.config.http.SessionCreationPolicy 11 | 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | @Order(1) 16 | class SecurityConfig : WebSecurityConfigurerAdapter() { 17 | 18 | @Autowired 19 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 20 | auth 21 | .inMemoryAuthentication() 22 | .withUser("discoveryAdmin") 23 | .password("discoveryPassword12345") 24 | .roles("SYSTEM") 25 | } 26 | 27 | override fun configure(http: HttpSecurity) { 28 | http 29 | .sessionManagement() 30 | .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) 31 | .and().requestMatchers().antMatchers("/eureka/**") 32 | .and().authorizeRequests().antMatchers("/eureka/**") 33 | .hasRole("SYSTEM").anyRequest().denyAll().and() 34 | .httpBasic().and().csrf().disable() 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/discovery/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=discovery 2 | spring.cloud.config.uri=http://localhost:9001 3 | spring.cloud.config.username=configAdmin 4 | spring.cloud.config.password=configPassword12345 5 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/gateway/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Gateway Server 2 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/GatewayApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy 7 | 8 | @SpringBootApplication 9 | @EnableZuulProxy 10 | @EnableEurekaClient 11 | class GatewayApplication 12 | 13 | fun main(args: Array) { 14 | SpringApplication.run(GatewayApplication::class.java, *args) 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.session.data.redis.RedisFlushMode 4 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 5 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 6 | 7 | @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) 8 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionFilter.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import com.netflix.zuul.ZuulFilter 4 | import com.netflix.zuul.context.RequestContext 5 | import org.springframework.stereotype.Component 6 | import org.springframework.session.SessionRepository 7 | import org.springframework.beans.factory.annotation.Autowired 8 | 9 | @Component 10 | class SessionFilter : ZuulFilter() { 11 | 12 | @Autowired 13 | lateinit var repository: SessionRepository<*> 14 | 15 | override fun shouldFilter(): Boolean { 16 | return true 17 | } 18 | 19 | override fun run(): Any? { 20 | val context = RequestContext.getCurrentContext() 21 | val httpSession = context.request.session 22 | val session = repository.getSession(httpSession.id) 23 | context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.id) 24 | println("Session ID available: ${session.id}") 25 | return null 26 | } 27 | 28 | override fun filterType(): String { 29 | return "pre" 30 | } 31 | 32 | override fun filterOrder(): Int { 33 | return 0 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Chapter10/ProjectB/Journaler API/gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=gateway 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | spring.cloud.config.username=configAdmin 5 | spring.cloud.config.password=configPassword12345 6 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 7 | 8 | -------------------------------------------------------------------------------- /Final Project/Dependency injection/src/ConstructorInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass(val parameter: Any) { 3 | 4 | private val dependency: Any 5 | 6 | init { 7 | dependency = parameter 8 | // Do some work dependency related 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Final Project/Dependency injection/src/FactoryInjection.kt: -------------------------------------------------------------------------------- 1 | 2 | class MyExampleClass2 { 3 | 4 | private val dependency = Factory().create() 5 | 6 | } 7 | 8 | class Factory { 9 | 10 | fun create(): Any { 11 | // To some instantiation work 12 | return Any() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Final Project/Dependency injection/src/MusicPlayer.kt: -------------------------------------------------------------------------------- 1 | 2 | class VolumeControl 3 | 4 | class MusicPlayer { 5 | 6 | val volumeControl = VolumeControl() 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Final Project/Dependency injection/src/MusicPlayerIOC.kt: -------------------------------------------------------------------------------- 1 | 2 | 3 | abstract class VolumeControlAbstract 4 | 5 | class MusicPlayerIOC( 6 | private val volumeControl: VolumeControlAbstract 7 | ) 8 | 9 | class VolumeControlImpl : VolumeControlAbstract() 10 | 11 | fun tryIOC(){ 12 | 13 | // Init. dependency. 14 | val vc = VolumeControlImpl() 15 | 16 | // Pass dependency. 17 | val player = MusicPlayerIOC(vc) 18 | 19 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | 27 | gradlew 28 | gradlew.bat 29 | gradle/* 30 | 31 | .idea/* 32 | 33 | 34 | -------------------------------------------------------------------------------- /Final Project/Journaler API/api/README.md: -------------------------------------------------------------------------------- 1 | # Journaler API -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/ApiApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ApiApplication 8 | 9 | fun main(args: Array) { 10 | SpringApplication.run(ApiApplication::class.java, *args) 11 | } 12 | -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/controller/NoteFindByTitleRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | data class NoteFindByTitleRequest(val title: String) { 4 | 5 | constructor() : this("") 6 | 7 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/controller/TodoLaterThanRequest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.controller 2 | 3 | import java.util.* 4 | 5 | data class TodoLaterThanRequest(val date: Date? = null) { 6 | 7 | constructor() : this(null) 8 | 9 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/data/Note.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "note") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | @NamedQuery( 14 | name = "Note.findByTitle", 15 | query = "SELECT n FROM Note n WHERE n.title LIKE ?1" 16 | ) 17 | data class Note( 18 | @Id 19 | @GeneratedValue(generator = "uuid2") 20 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 21 | @Column(columnDefinition = "varchar(36)") 22 | var id: String = "", 23 | var title: String, 24 | var message: String, 25 | var location: String = "", 26 | @CreationTimestamp 27 | var created: Date = Date(), 28 | @UpdateTimestamp 29 | var modified: Date = Date() 30 | ) { 31 | 32 | /** 33 | * Hibernate tries creates a bean via reflection. 34 | * It does the object creation by calling the no-arg constructor. 35 | * Then it uses the setter methods to set the properties. 36 | * 37 | * If there is no default constructor, the following excpetion happens: 38 | * org.hibernate.InstantiationException: No default constructor for entity... 39 | */ 40 | constructor() : this( 41 | "", "", "", "" 42 | ) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/data/NoteDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class NoteDTO( 6 | var title: String, 7 | var message: String, 8 | var location: String = "" 9 | ) { 10 | 11 | constructor() : this("", "", "") 12 | 13 | var id: String = "" 14 | var created: Date = Date() 15 | var modified: Date = Date() 16 | 17 | constructor(note: Note) : this( 18 | note.title, 19 | note.message, 20 | note.location 21 | ) { 22 | id = note.id 23 | created = note.created 24 | modified = note.modified 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/data/Todo.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude 4 | import org.hibernate.annotations.CreationTimestamp 5 | import org.hibernate.annotations.GenericGenerator 6 | import org.hibernate.annotations.UpdateTimestamp 7 | import java.util.* 8 | import javax.persistence.* 9 | 10 | @Entity 11 | @Table(name = "todo") 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | data class Todo( 14 | @Id 15 | @GeneratedValue(generator = "uuid2") 16 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 17 | @Column(columnDefinition = "varchar(36)") 18 | var id: String = "", 19 | var title: String, 20 | var message: String, 21 | var schedule: Long, 22 | var location: String = "", 23 | @CreationTimestamp 24 | var created: Date = Date(), 25 | @UpdateTimestamp 26 | var modified: Date = Date() 27 | ) { 28 | 29 | /** 30 | * Hibernate tries creates a bean via reflection. 31 | * It does the object creation by calling the no-arg constructor. 32 | * Then it uses the setter methods to set the properties. 33 | * 34 | * If there is no default constructor, the following excpetion happens: 35 | * org.hibernate.InstantiationException: No default constructor for entity... 36 | */ 37 | constructor() : this( 38 | "", "", "", -1, "" 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/data/TodoDTO.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.data 2 | 3 | import java.util.* 4 | 5 | data class TodoDTO( 6 | var title: String, 7 | var message: String, 8 | var schedule: Long, 9 | var location: String = "" 10 | ) { 11 | 12 | var id: String = "" 13 | var created: Date = Date() 14 | var modified: Date = Date() 15 | 16 | constructor(todo: Todo) : this( 17 | todo.title, 18 | todo.message, 19 | todo.schedule, 20 | todo.location 21 | ) { 22 | id = todo.id 23 | created = todo.created 24 | modified = todo.modified 25 | } 26 | 27 | constructor() : this("", "", -1, "") 28 | 29 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/repository/NoteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Note 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | /** 7 | * String is the type for ID we use. 8 | */ 9 | interface NoteRepository : CrudRepository { 10 | 11 | fun findByTitle(title: String): Iterable 12 | 13 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/repository/TodoRepository.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.repository 2 | 3 | import com.journaler.api.data.Todo 4 | import org.springframework.data.jpa.repository.Query 5 | import org.springframework.data.repository.CrudRepository 6 | 7 | /** 8 | * String is the type for ID we use. 9 | */ 10 | interface TodoRepository : CrudRepository { 11 | 12 | @Query("from Todo t where t.schedule > ?1") 13 | fun findScheduledLaterThan(date: Long): Iterable 14 | 15 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.security 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 7 | import org.springframework.core.annotation.Order 8 | 9 | @Configuration 10 | @EnableWebSecurity 11 | @Order(1) 12 | class SecurityConfig : WebSecurityConfigurerAdapter() { 13 | 14 | override fun configure(http: HttpSecurity) { 15 | http 16 | .httpBasic().disable().authorizeRequests() 17 | .antMatchers("/notes").permitAll() 18 | .antMatchers("/notes/**").permitAll() 19 | .antMatchers("/todos").permitAll() 20 | .antMatchers("/todos/**").permitAll() 21 | .anyRequest() 22 | .authenticated() 23 | .and() 24 | .csrf().disable() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/service/NoteService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Note 4 | import com.journaler.api.data.NoteDTO 5 | import com.journaler.api.repository.NoteRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | @Service("Note service") 11 | class NoteService { 12 | 13 | @Autowired 14 | lateinit var repository: NoteRepository 15 | 16 | fun getNotes(): Iterable = repository.findAll().map { it -> NoteDTO(it) } 17 | 18 | fun insertNote(note: NoteDTO) = NoteDTO( 19 | repository.save( 20 | Note( 21 | title = note.title, 22 | message = note.message, 23 | location = note.location 24 | ) 25 | ) 26 | ) 27 | 28 | fun deleteNote(id: String) = repository.deleteById(id) 29 | 30 | fun updateNote(noteDto: NoteDTO): NoteDTO { 31 | val note = repository.findById(noteDto.id).get() 32 | note.title = noteDto.title 33 | note.message = noteDto.message 34 | note.location = noteDto.location 35 | note.modified = Date() 36 | return NoteDTO(repository.save(note)) 37 | } 38 | 39 | fun findByTitle(title: String): Iterable { 40 | return repository.findByTitle(title).map { it -> NoteDTO(it) } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/kotlin/com/journaler/api/service/TodoService.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.api.service 2 | 3 | import com.journaler.api.data.Todo 4 | import com.journaler.api.data.TodoDTO 5 | import com.journaler.api.repository.TodoRepository 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.stereotype.Service 8 | import java.util.* 9 | 10 | 11 | @Service("Todo service") 12 | class TodoService { 13 | 14 | @Autowired 15 | lateinit var repository: TodoRepository 16 | 17 | fun getTodos(): Iterable = repository.findAll().map { it -> TodoDTO(it) } 18 | 19 | fun insertTodo(todo: TodoDTO) = TodoDTO( 20 | repository.save( 21 | Todo( 22 | title = todo.title, 23 | message = todo.message, 24 | location = todo.location, 25 | schedule = todo.schedule 26 | 27 | ) 28 | ) 29 | ) 30 | 31 | fun deleteTodo(id: String) = repository.deleteById(id) 32 | 33 | fun updateTodo(todoDto: TodoDTO): TodoDTO { 34 | val todo = repository.findById(todoDto.id).get() 35 | todo.title = todoDto.title 36 | todo.message = todoDto.message 37 | todo.location = todoDto.location 38 | todo.schedule = todoDto.schedule 39 | todo.modified = Date() 40 | return TodoDTO(repository.save(todo)) 41 | } 42 | 43 | fun getScheduledLaterThan(date: Date?): Iterable { 44 | date?.let { 45 | return repository.findScheduledLaterThan(date.time).map { it -> TodoDTO(it) } 46 | } 47 | return listOf() 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= journaler 2 | server.port= 80 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 13 | spring.datasource.username=root 14 | spring.datasource.password=localInstance2017 15 | spring.datasource.tomcat.test-on-borrow=true 16 | spring.datasource.tomcat.validation-interval=30000 17 | spring.datasource.tomcat.validation-query=SELECT 1 18 | spring.datasource.tomcat.remove-abandoned=true 19 | spring.datasource.tomcat.remove-abandoned-timeout=10000 20 | spring.datasource.tomcat.log-abandoned=true 21 | spring.datasource.tomcat.max-age=1800000 22 | spring.datasource.tomcat.log-validation-errors=true 23 | spring.datasource.tomcat.max-active=50 24 | spring.datasource.tomcat.max-idle=10 25 | 26 | spring.jpa.hibernate.ddl-auto=update 27 | -------------------------------------------------------------------------------- /Final Project/Journaler API/api/src/test/kotlin/com/journaler/SuiteTest.kt: -------------------------------------------------------------------------------- 1 | package com.journaler 2 | 3 | import org.junit.runner.RunWith 4 | import org.junit.runners.Suite 5 | 6 | @RunWith(Suite::class) 7 | @Suite.SuiteClasses(NoteTest::class, TodoTest::class) 8 | class SuiteTest -------------------------------------------------------------------------------- /Final Project/Journaler API/configuration/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Final Project/Journaler API/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Configuration Server 2 | -------------------------------------------------------------------------------- /Final Project/Journaler API/configuration/src/main/kotlin/com/journaler/config/ConfigApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.config 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.config.server.EnableConfigServer 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | class ConfigApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(ConfigApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Final Project/Journaler API/configuration/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= config 2 | server.port= 9001 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | spring.cloud.config.server.git.uri=file://${user.home}/Projects/Building-Applications-with-Spring-5-and-Kotlin-Config-Repo 13 | 14 | # Or you can clone your existing configuration repo: 15 | # spring.cloud.config.server.git.uri=ssh://some_domain/config-repo 16 | # spring.cloud.config.server.git.clone-on-start=true 17 | # security.user.name=git_username 18 | # security.user.password=git_password 19 | 20 | eureka.client.region = default 21 | eureka.client.registryFetchIntervalSeconds = 5 22 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 23 | 24 | security.user.name=configAdmin 25 | security.user.password=configPassword12345 26 | security.user.role=SYSTEM 27 | 28 | spring.session.store-type=redis -------------------------------------------------------------------------------- /Final Project/Journaler API/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Final Project/Journaler API/discovery/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Discovery Server 2 | -------------------------------------------------------------------------------- /Final Project/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/DiscoveryApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | class DiscoveryApplication 10 | 11 | fun main(args: Array) { 12 | SpringApplication.run(DiscoveryApplication::class.java, *args) 13 | } 14 | -------------------------------------------------------------------------------- /Final Project/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 4 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 5 | 6 | @EnableRedisHttpSession 7 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Final Project/Journaler API/discovery/src/main/kotlin/com/journaler/discovery/security/WebSecurityConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.discovery.security 2 | 3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.context.annotation.Configuration 7 | import org.springframework.core.annotation.Order 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity 10 | import org.springframework.security.config.http.SessionCreationPolicy 11 | 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | @Order(1) 16 | class SecurityConfig : WebSecurityConfigurerAdapter() { 17 | 18 | @Autowired 19 | fun configureGlobal(auth: AuthenticationManagerBuilder) { 20 | auth 21 | .inMemoryAuthentication() 22 | .withUser("discoveryAdmin") 23 | .password("discoveryPassword12345") 24 | .roles("SYSTEM") 25 | } 26 | 27 | override fun configure(http: HttpSecurity) { 28 | http 29 | .sessionManagement() 30 | .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) 31 | .and().requestMatchers().antMatchers("/eureka/**") 32 | .and().authorizeRequests().antMatchers("/eureka/**") 33 | .hasRole("SYSTEM").anyRequest().denyAll().and() 34 | .httpBasic().and().csrf().disable() 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/discovery/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=discovery 2 | spring.cloud.config.uri=http://localhost:9001 3 | spring.cloud.config.username=configAdmin 4 | spring.cloud.config.password=configPassword12345 5 | -------------------------------------------------------------------------------- /Final Project/Journaler API/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | out/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ 27 | 28 | gradlew 29 | gradlew.bat 30 | gradle/* 31 | 32 | .idea/* 33 | out/* 34 | 35 | 36 | -------------------------------------------------------------------------------- /Final Project/Journaler API/gateway/README.md: -------------------------------------------------------------------------------- 1 | # Journaler Gateway Server 2 | -------------------------------------------------------------------------------- /Final Project/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/GatewayApplication.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy 7 | 8 | @SpringBootApplication 9 | @EnableZuulProxy 10 | @EnableEurekaClient 11 | class GatewayApplication 12 | 13 | fun main(args: Array) { 14 | SpringApplication.run(GatewayApplication::class.java, *args) 15 | } 16 | -------------------------------------------------------------------------------- /Final Project/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import org.springframework.session.data.redis.RedisFlushMode 4 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession 5 | import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer 6 | 7 | @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) 8 | class SessionConfiguration : AbstractHttpSessionApplicationInitializer() -------------------------------------------------------------------------------- /Final Project/Journaler API/gateway/src/main/kotlin/com/journaler/gateway/SessionFilter.kt: -------------------------------------------------------------------------------- 1 | package com.journaler.gateway 2 | 3 | import com.netflix.zuul.ZuulFilter 4 | import com.netflix.zuul.context.RequestContext 5 | import org.springframework.stereotype.Component 6 | import org.springframework.session.SessionRepository 7 | import org.springframework.beans.factory.annotation.Autowired 8 | 9 | @Component 10 | class SessionFilter : ZuulFilter() { 11 | 12 | @Autowired 13 | lateinit var repository: SessionRepository<*> 14 | 15 | override fun shouldFilter(): Boolean { 16 | return true 17 | } 18 | 19 | override fun run(): Any? { 20 | val context = RequestContext.getCurrentContext() 21 | val httpSession = context.request.session 22 | val session = repository.getSession(httpSession.id) 23 | context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.id) 24 | println("Session ID available: ${session.id}") 25 | return null 26 | } 27 | 28 | override fun filterType(): String { 29 | return "pre" 30 | } 31 | 32 | override fun filterOrder(): Int { 33 | return 0 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Final Project/Journaler API/gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.config.name=gateway 2 | spring.cloud.config.discovery.service-id=config 3 | spring.cloud.config.discovery.enabled=true 4 | spring.cloud.config.username=configAdmin 5 | spring.cloud.config.password=configPassword12345 6 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Software and hardware list.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Applications-with-Spring-5-and-Kotlin/914a9d5d336e3563c3a12b6ad7b8e3321f3ec46d/Software and hardware list.pdf -------------------------------------------------------------------------------- /discovery.properties: -------------------------------------------------------------------------------- 1 | spring.application.name= discovery 2 | server.port= 9002 3 | logging.level.root=INFO 4 | logging.level.com.journaler.api=DEBUG 5 | logging.level.org.springframework.jdbc=ERROR 6 | 7 | endpoints.health.enabled=true 8 | endpoints.trace.enabled=true 9 | endpoints.info.enabled=true 10 | endpoints.metrics.enabled=true 11 | 12 | eureka.instance.hostname=localhost 13 | 14 | eureka.client.serviceUrl.defaultZone=http://discoveryAdmin:discoveryPassword12345@localhost:9002/eureka/ 15 | eureka.client.register-with-eureka=false 16 | eureka.client.fetch-registry=false 17 | 18 | spring.redis.host=localhost 19 | spring.redis.port=6379 20 | --------------------------------------------------------------------------------